MediatorStrategy.java

1
package com.jsql.model.injection.strategy;
2
3
import com.jsql.model.InjectionModel;
4
import com.jsql.model.exception.JSqlException;
5
import com.jsql.model.injection.engine.model.EngineYaml;
6
import com.jsql.model.suspendable.Input;
7
import com.jsql.model.suspendable.SuspendableGetCharInsertion;
8
import com.jsql.model.suspendable.SuspendableGetEngine;
9
import com.jsql.util.LogLevelUtil;
10
import com.jsql.util.StringUtil;
11
import org.apache.commons.lang3.StringUtils;
12
import org.apache.logging.log4j.LogManager;
13
import org.apache.logging.log4j.Logger;
14
15
import java.util.AbstractMap.SimpleEntry;
16
import java.util.Arrays;
17
import java.util.List;
18
import java.util.regex.Matcher;
19
20
public class MediatorStrategy {
21
22
    private static final Logger LOGGER = LogManager.getRootLogger();
23
    
24
    private final AbstractStrategy time;
25
    private final AbstractStrategy blindBit;
26
    private final AbstractStrategy blindBin;
27
    private final AbstractStrategy multibit;
28
    private final AbstractStrategy dns;
29
    private final StrategyError error;
30
    private final AbstractStrategy union;
31
    private final AbstractStrategy stack;
32
33
    private final List<AbstractStrategy> strategies;
34
    
35
    /**
36
     * Current injection strategy.
37
     */
38
    private AbstractStrategy strategy;
39
40
    private final InjectionModel injectionModel;
41
    
42
    public MediatorStrategy(InjectionModel injectionModel) {
43
        this.injectionModel = injectionModel;
44
        
45
        this.time = new StrategyTime(this.injectionModel);
46
        this.blindBit = new StrategyBlindBit(this.injectionModel);
47
        this.blindBin = new StrategyBlindBin(this.injectionModel);
48
        this.multibit = new StrategyMultibit(this.injectionModel);
49
        this.dns = new StrategyDns(this.injectionModel);
50
        this.error = new StrategyError(this.injectionModel);
51
        this.union = new StrategyUnion(this.injectionModel);
52
        this.stack = new StrategyStack(this.injectionModel);
53
54
        this.strategies = Arrays.asList(this.time, this.blindBin, this.blindBit, this.multibit, this.error, this.dns, this.stack, this.union);
55
    }
56
    
57
    public String getMeta() {
58 1 1. getMeta : negated conditional → NO_COVERAGE
        String strategyName = this.strategy == null ? StringUtils.EMPTY : this.strategy.toString().toLowerCase();
59
        var strategyMode = "default";
60 1 1. getMeta : negated conditional → NO_COVERAGE
        if (this.injectionModel.getMediatorUtils().preferencesUtil().isDiosStrategy()) {
61
            strategyMode = "dios";
62 1 1. getMeta : negated conditional → NO_COVERAGE
        } else if (this.injectionModel.getMediatorUtils().preferencesUtil().isZipStrategy()) {
63
            strategyMode = "zip";
64
        }
65 1 1. getMeta : replaced return value with "" for com/jsql/model/injection/strategy/MediatorStrategy::getMeta → NO_COVERAGE
        return String.format("%s#%s", strategyName.replace(" ", "-"), strategyMode);
66
    }
67
    
68
    /**
69
     * Build correct data for GET, POST, HEADER.
70
     * Each can be either raw data (no injection), SQL query without index requirement,
71
     * or SQL query with index requirement.
72
     * @param urlBase Beginning of the request data
73
     * @param isUsingIndex False if request doesn't use indexes
74
     * @param sqlTrail SQL statement
75
     * @return Final data
76
     */
77
    public String buildPath(String urlBase, boolean isUsingIndex, String sqlTrail) {
78
        String result = urlBase;
79 1 1. buildPath : negated conditional → NO_COVERAGE
        if (urlBase.contains(InjectionModel.STAR)) {
80 1 1. buildPath : negated conditional → NO_COVERAGE
            if (!isUsingIndex) {
81
                result = urlBase.replace(InjectionModel.STAR, this.encodePath(sqlTrail));
82
            } else {
83
                result = urlBase.replace(
84
                    InjectionModel.STAR,
85
                    this.encodePath(
86
                        this.getSpecificUnion().getIndexesInUrl().replaceAll(
87
                            String.format(EngineYaml.FORMAT_INDEX, this.getSpecificUnion().getVisibleIndex()),
88
                            Matcher.quoteReplacement(sqlTrail)  // Oracle column can contain regex char $ => quoteReplacement()
89
                        )
90
                    )
91
                );
92
            }
93
        }
94 1 1. buildPath : replaced return value with "" for com/jsql/model/injection/strategy/MediatorStrategy::buildPath → NO_COVERAGE
        return result;
95
    }
96
97
    private String encodePath(String sqlTrail) {
98
        String sqlTrailEncoded = StringUtil.cleanSql(sqlTrail);
99
100 1 1. encodePath : negated conditional → NO_COVERAGE
        if (!this.injectionModel.getMediatorUtils().preferencesUtil().isUrlEncodingDisabled()) {
101
            sqlTrailEncoded = sqlTrailEncoded
102
                .replace("'", "%27")
103
                .replace("(", "%28")
104
                .replace(")", "%29")
105
                .replace("{", "%7b")
106
                .replace("[", "%5b")
107
                .replace("]", "%5d")
108
                .replace("}", "%7d")
109
                .replace(">", "%3e")
110
                .replace("<", "%3c")
111
                .replace("?", "%3f")
112
                .replace("_", "%5f")
113
                .replace("\\", "%5c")
114
                .replace(",", "%2c");
115
        }
116
117
        // URL forbidden characters
118 1 1. encodePath : replaced return value with "" for com/jsql/model/injection/strategy/MediatorStrategy::encodePath → NO_COVERAGE
        return (sqlTrailEncoded + this.injectionModel.getMediatorEngine().getEngine().instance().endingComment())
119
            .replace("\"", "%22")
120
            .replace("|", "%7c")
121
            .replace("`", "%60")
122
            .replace(StringUtils.SPACE, "%20")
123
            .replace("+", "%20");
124
    }
125
    
126
    /**
127
     * Find the insertion character, test each strategy, inject metadata and list databases.
128
     * @param parameterToInject to be tested, null when injection point
129
     * @return true when successful injection
130
     * @throws JSqlException when no params integrity, process stopped by user, or injection failure
131
     */
132
    public boolean testStrategies(SimpleEntry<String, String> parameterToInject) throws JSqlException {
133
        // Define insertionCharacter, i.e, -1 in "[..].php?id=-1 union select[..]",
134
        
135
        String parameterOriginalValue = null;
136
        
137
        // Fingerprint database
138 1 1. testStrategies : removed call to com/jsql/model/injection/engine/MediatorEngine::setEngine → NO_COVERAGE
        this.injectionModel.getMediatorEngine().setEngine(this.injectionModel.getMediatorEngine().fingerprintEngine());
139
        
140
        // If not an injection point then find insertion character.
141
        // Force to 1 if no insertion char works and empty value from user,
142
        // Force to user's value if no insertion char works,
143
        // Force to insertion char otherwise.
144
        // parameterToInject null on true STAR injection
145
        // TODO Use also on Json injection where parameter == null
146 1 1. testStrategies : negated conditional → NO_COVERAGE
        if (parameterToInject != null) {
147
            parameterOriginalValue = parameterToInject.getValue();
148
                     
149
            // Test for params integrity
150
            String characterInsertionByUser = this.injectionModel.getMediatorUtils().parameterUtil().initStar(parameterToInject);
151
            
152 1 1. testStrategies : negated conditional → NO_COVERAGE
            String characterInsertion = this.injectionModel.getMediatorUtils().preferencesUtil().isNotSearchingCharInsertion()
153
                ? characterInsertionByUser
154
                : new SuspendableGetCharInsertion(this.injectionModel).run(
155
                    new Input(characterInsertionByUser)
156
                );
157 1 1. testStrategies : negated conditional → NO_COVERAGE
            if (characterInsertion.contains(InjectionModel.STAR)) {  // When injecting all parameters or JSON
158
                parameterToInject.setValue(characterInsertion);
159
            } else {  // When injecting last parameter
160
                parameterToInject.setValue(characterInsertion.replaceAll("(\\w)$", "$1+") + InjectionModel.STAR);
161
            }
162 1 1. testStrategies : negated conditional → NO_COVERAGE
        } else if (this.injectionModel.getMediatorUtils().connectionUtil().getUrlBase().contains(InjectionModel.STAR)) {
163
            String characterInsertion = new SuspendableGetCharInsertion(this.injectionModel).run(
164
                new Input(StringUtils.EMPTY)
165
            );
166
            String urlBase = this.injectionModel.getMediatorUtils().connectionUtil().getUrlBase();
167 1 1. testStrategies : removed call to com/jsql/util/ConnectionUtil::setUrlBase → NO_COVERAGE
            this.injectionModel.getMediatorUtils().connectionUtil().setUrlBase(
168
                // Space %20 for URL, do not use +
169
                urlBase.replace(InjectionModel.STAR, characterInsertion.replaceAll("(\\w)$", "$1%20") + InjectionModel.STAR)
170
            );
171
        }
172
173 1 1. testStrategies : negated conditional → NO_COVERAGE
        if (this.injectionModel.getMediatorEngine().getEngineByUser() == this.injectionModel.getMediatorEngine().getAuto()) {
174
            new SuspendableGetEngine(this.injectionModel).run();
175
        }
176
177
        // Test each injection strategies: time < blind binary < blind bitwise < multibit < error < stack < union
178 1 1. testStrategies : removed call to com/jsql/model/injection/strategy/AbstractStrategy::checkApplicability → NO_COVERAGE
        this.time.checkApplicability();
179 1 1. testStrategies : removed call to com/jsql/model/injection/strategy/AbstractStrategy::checkApplicability → NO_COVERAGE
        this.blindBin.checkApplicability();
180 1 1. testStrategies : removed call to com/jsql/model/injection/strategy/AbstractStrategy::checkApplicability → NO_COVERAGE
        this.blindBit.checkApplicability();
181
182 1 1. testStrategies : negated conditional → NO_COVERAGE
        if (parameterToInject != null) {
183
            // Multibit requires '0'
184
            // TODO char insertion 0' should also work on "where x='$param'"
185
            var backupCharacterInsertion = parameterToInject.getValue();
186
            parameterToInject.setValue(InjectionModel.STAR);
187 1 1. testStrategies : removed call to com/jsql/model/injection/strategy/AbstractStrategy::checkApplicability → NO_COVERAGE
            this.multibit.checkApplicability();
188
            parameterToInject.setValue(backupCharacterInsertion);
189
        } else {
190 1 1. testStrategies : removed call to com/jsql/model/injection/strategy/AbstractStrategy::checkApplicability → NO_COVERAGE
            this.multibit.checkApplicability();
191
        }
192
193 1 1. testStrategies : removed call to com/jsql/model/injection/strategy/AbstractStrategy::checkApplicability → NO_COVERAGE
        this.dns.checkApplicability();
194 1 1. testStrategies : removed call to com/jsql/model/injection/strategy/StrategyError::checkApplicability → NO_COVERAGE
        this.error.checkApplicability();
195 1 1. testStrategies : removed call to com/jsql/model/injection/strategy/AbstractStrategy::checkApplicability → NO_COVERAGE
        this.stack.checkApplicability();
196 1 1. testStrategies : removed call to com/jsql/model/injection/strategy/AbstractStrategy::checkApplicability → NO_COVERAGE
        this.union.checkApplicability();
197
198
        // Set most efficient strategy first
199 1 1. testStrategies : removed call to com/jsql/model/injection/strategy/AbstractStrategy::activateWhenApplicable → NO_COVERAGE
        this.union.activateWhenApplicable();
200 1 1. testStrategies : removed call to com/jsql/model/injection/strategy/AbstractStrategy::activateWhenApplicable → NO_COVERAGE
        this.stack.activateWhenApplicable();
201 1 1. testStrategies : removed call to com/jsql/model/injection/strategy/StrategyError::activateWhenApplicable → NO_COVERAGE
        this.error.activateWhenApplicable();
202 1 1. testStrategies : removed call to com/jsql/model/injection/strategy/AbstractStrategy::activateWhenApplicable → NO_COVERAGE
        this.dns.activateWhenApplicable();
203 1 1. testStrategies : removed call to com/jsql/model/injection/strategy/AbstractStrategy::activateWhenApplicable → NO_COVERAGE
        this.multibit.activateWhenApplicable();
204 1 1. testStrategies : removed call to com/jsql/model/injection/strategy/AbstractStrategy::activateWhenApplicable → NO_COVERAGE
        this.blindBit.activateWhenApplicable();
205 1 1. testStrategies : removed call to com/jsql/model/injection/strategy/AbstractStrategy::activateWhenApplicable → NO_COVERAGE
        this.blindBin.activateWhenApplicable();
206 1 1. testStrategies : removed call to com/jsql/model/injection/strategy/AbstractStrategy::activateWhenApplicable → NO_COVERAGE
        this.time.activateWhenApplicable();
207
208 1 1. testStrategies : negated conditional → NO_COVERAGE
        if (this.injectionModel.getMediatorStrategy().getStrategy() == null) {  // no strategy found
209
            // Restore initial parameter value on injection failure
210
            // Only when not true STAR injection
211 1 1. testStrategies : negated conditional → NO_COVERAGE
            if (parameterOriginalValue != null) {
212
                parameterToInject.setValue(parameterOriginalValue.replace(InjectionModel.STAR, StringUtils.EMPTY));
213
            }
214
215
            LOGGER.log(LogLevelUtil.CONSOLE_ERROR, "No injection found");
216 1 1. testStrategies : replaced boolean return with true for com/jsql/model/injection/strategy/MediatorStrategy::testStrategies → NO_COVERAGE
            return false;
217
        }
218
        
219 1 1. testStrategies : replaced boolean return with false for com/jsql/model/injection/strategy/MediatorStrategy::testStrategies → NO_COVERAGE
        return true;
220
    }
221
    
222
    
223
    // Getter and setter
224
225
    public AbstractStrategy getUnion() {
226 1 1. getUnion : replaced return value with null for com/jsql/model/injection/strategy/MediatorStrategy::getUnion → NO_COVERAGE
        return this.union;
227
    }
228
229
    public StrategyUnion getSpecificUnion() {
230 1 1. getSpecificUnion : replaced return value with null for com/jsql/model/injection/strategy/MediatorStrategy::getSpecificUnion → NO_COVERAGE
        return (StrategyUnion) this.union;
231
    }
232
233
    public StrategyError getError() {
234 1 1. getError : replaced return value with null for com/jsql/model/injection/strategy/MediatorStrategy::getError → NO_COVERAGE
        return this.error;
235
    }
236
237
    public AbstractStrategy getBlindBit() {
238 1 1. getBlindBit : replaced return value with null for com/jsql/model/injection/strategy/MediatorStrategy::getBlindBit → NO_COVERAGE
        return this.blindBit;
239
    }
240
241
    public AbstractStrategy getBlindBin() {
242 1 1. getBlindBin : replaced return value with null for com/jsql/model/injection/strategy/MediatorStrategy::getBlindBin → NO_COVERAGE
        return this.blindBin;
243
    }
244
245
    public AbstractStrategy getMultibit() {
246 1 1. getMultibit : replaced return value with null for com/jsql/model/injection/strategy/MediatorStrategy::getMultibit → SURVIVED
        return this.multibit;
247
    }
248
249
    public AbstractStrategy getTime() {
250 1 1. getTime : replaced return value with null for com/jsql/model/injection/strategy/MediatorStrategy::getTime → NO_COVERAGE
        return this.time;
251
    }
252
253
    public AbstractStrategy getStack() {
254 1 1. getStack : replaced return value with null for com/jsql/model/injection/strategy/MediatorStrategy::getStack → NO_COVERAGE
        return this.stack;
255
    }
256
257
    public AbstractStrategy getDns() {
258 1 1. getDns : replaced return value with null for com/jsql/model/injection/strategy/MediatorStrategy::getDns → NO_COVERAGE
        return this.dns;
259
    }
260
261
    public List<AbstractStrategy> getStrategies() {
262 1 1. getStrategies : replaced return value with Collections.emptyList for com/jsql/model/injection/strategy/MediatorStrategy::getStrategies → NO_COVERAGE
        return this.strategies;
263
    }
264
265
    public AbstractStrategy getStrategy() {
266 1 1. getStrategy : replaced return value with null for com/jsql/model/injection/strategy/MediatorStrategy::getStrategy → SURVIVED
        return this.strategy;
267
    }
268
269
    public void setStrategy(AbstractStrategy strategy) {
270
        this.strategy = strategy;
271
    }
272
}

Mutations

58

1.1
Location : getMeta
Killed by : none
negated conditional → NO_COVERAGE

60

1.1
Location : getMeta
Killed by : none
negated conditional → NO_COVERAGE

62

1.1
Location : getMeta
Killed by : none
negated conditional → NO_COVERAGE

65

1.1
Location : getMeta
Killed by : none
replaced return value with "" for com/jsql/model/injection/strategy/MediatorStrategy::getMeta → NO_COVERAGE

79

1.1
Location : buildPath
Killed by : none
negated conditional → NO_COVERAGE

80

1.1
Location : buildPath
Killed by : none
negated conditional → NO_COVERAGE

94

1.1
Location : buildPath
Killed by : none
replaced return value with "" for com/jsql/model/injection/strategy/MediatorStrategy::buildPath → NO_COVERAGE

100

1.1
Location : encodePath
Killed by : none
negated conditional → NO_COVERAGE

118

1.1
Location : encodePath
Killed by : none
replaced return value with "" for com/jsql/model/injection/strategy/MediatorStrategy::encodePath → NO_COVERAGE

138

1.1
Location : testStrategies
Killed by : none
removed call to com/jsql/model/injection/engine/MediatorEngine::setEngine → NO_COVERAGE

146

1.1
Location : testStrategies
Killed by : none
negated conditional → NO_COVERAGE

152

1.1
Location : testStrategies
Killed by : none
negated conditional → NO_COVERAGE

157

1.1
Location : testStrategies
Killed by : none
negated conditional → NO_COVERAGE

162

1.1
Location : testStrategies
Killed by : none
negated conditional → NO_COVERAGE

167

1.1
Location : testStrategies
Killed by : none
removed call to com/jsql/util/ConnectionUtil::setUrlBase → NO_COVERAGE

173

1.1
Location : testStrategies
Killed by : none
negated conditional → NO_COVERAGE

178

1.1
Location : testStrategies
Killed by : none
removed call to com/jsql/model/injection/strategy/AbstractStrategy::checkApplicability → NO_COVERAGE

179

1.1
Location : testStrategies
Killed by : none
removed call to com/jsql/model/injection/strategy/AbstractStrategy::checkApplicability → NO_COVERAGE

180

1.1
Location : testStrategies
Killed by : none
removed call to com/jsql/model/injection/strategy/AbstractStrategy::checkApplicability → NO_COVERAGE

182

1.1
Location : testStrategies
Killed by : none
negated conditional → NO_COVERAGE

187

1.1
Location : testStrategies
Killed by : none
removed call to com/jsql/model/injection/strategy/AbstractStrategy::checkApplicability → NO_COVERAGE

190

1.1
Location : testStrategies
Killed by : none
removed call to com/jsql/model/injection/strategy/AbstractStrategy::checkApplicability → NO_COVERAGE

193

1.1
Location : testStrategies
Killed by : none
removed call to com/jsql/model/injection/strategy/AbstractStrategy::checkApplicability → NO_COVERAGE

194

1.1
Location : testStrategies
Killed by : none
removed call to com/jsql/model/injection/strategy/StrategyError::checkApplicability → NO_COVERAGE

195

1.1
Location : testStrategies
Killed by : none
removed call to com/jsql/model/injection/strategy/AbstractStrategy::checkApplicability → NO_COVERAGE

196

1.1
Location : testStrategies
Killed by : none
removed call to com/jsql/model/injection/strategy/AbstractStrategy::checkApplicability → NO_COVERAGE

199

1.1
Location : testStrategies
Killed by : none
removed call to com/jsql/model/injection/strategy/AbstractStrategy::activateWhenApplicable → NO_COVERAGE

200

1.1
Location : testStrategies
Killed by : none
removed call to com/jsql/model/injection/strategy/AbstractStrategy::activateWhenApplicable → NO_COVERAGE

201

1.1
Location : testStrategies
Killed by : none
removed call to com/jsql/model/injection/strategy/StrategyError::activateWhenApplicable → NO_COVERAGE

202

1.1
Location : testStrategies
Killed by : none
removed call to com/jsql/model/injection/strategy/AbstractStrategy::activateWhenApplicable → NO_COVERAGE

203

1.1
Location : testStrategies
Killed by : none
removed call to com/jsql/model/injection/strategy/AbstractStrategy::activateWhenApplicable → NO_COVERAGE

204

1.1
Location : testStrategies
Killed by : none
removed call to com/jsql/model/injection/strategy/AbstractStrategy::activateWhenApplicable → NO_COVERAGE

205

1.1
Location : testStrategies
Killed by : none
removed call to com/jsql/model/injection/strategy/AbstractStrategy::activateWhenApplicable → NO_COVERAGE

206

1.1
Location : testStrategies
Killed by : none
removed call to com/jsql/model/injection/strategy/AbstractStrategy::activateWhenApplicable → NO_COVERAGE

208

1.1
Location : testStrategies
Killed by : none
negated conditional → NO_COVERAGE

211

1.1
Location : testStrategies
Killed by : none
negated conditional → NO_COVERAGE

216

1.1
Location : testStrategies
Killed by : none
replaced boolean return with true for com/jsql/model/injection/strategy/MediatorStrategy::testStrategies → NO_COVERAGE

219

1.1
Location : testStrategies
Killed by : none
replaced boolean return with false for com/jsql/model/injection/strategy/MediatorStrategy::testStrategies → NO_COVERAGE

226

1.1
Location : getUnion
Killed by : none
replaced return value with null for com/jsql/model/injection/strategy/MediatorStrategy::getUnion → NO_COVERAGE

230

1.1
Location : getSpecificUnion
Killed by : none
replaced return value with null for com/jsql/model/injection/strategy/MediatorStrategy::getSpecificUnion → NO_COVERAGE

234

1.1
Location : getError
Killed by : none
replaced return value with null for com/jsql/model/injection/strategy/MediatorStrategy::getError → NO_COVERAGE

238

1.1
Location : getBlindBit
Killed by : none
replaced return value with null for com/jsql/model/injection/strategy/MediatorStrategy::getBlindBit → NO_COVERAGE

242

1.1
Location : getBlindBin
Killed by : none
replaced return value with null for com/jsql/model/injection/strategy/MediatorStrategy::getBlindBin → NO_COVERAGE

246

1.1
Location : getMultibit
Killed by : none
replaced return value with null for com/jsql/model/injection/strategy/MediatorStrategy::getMultibit → SURVIVED
Covering tests

250

1.1
Location : getTime
Killed by : none
replaced return value with null for com/jsql/model/injection/strategy/MediatorStrategy::getTime → NO_COVERAGE

254

1.1
Location : getStack
Killed by : none
replaced return value with null for com/jsql/model/injection/strategy/MediatorStrategy::getStack → NO_COVERAGE

258

1.1
Location : getDns
Killed by : none
replaced return value with null for com/jsql/model/injection/strategy/MediatorStrategy::getDns → NO_COVERAGE

262

1.1
Location : getStrategies
Killed by : none
replaced return value with Collections.emptyList for com/jsql/model/injection/strategy/MediatorStrategy::getStrategies → NO_COVERAGE

266

1.1
Location : getStrategy
Killed by : none
replaced return value with null for com/jsql/model/injection/strategy/MediatorStrategy::getStrategy → SURVIVED
Covering tests

Active mutators

Tests examined


Report generated by PIT 1.22.1