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.vendor.model.VendorYaml;
6
import com.jsql.model.suspendable.SuspendableGetCharInsertion;
7
import com.jsql.model.suspendable.SuspendableGetVendor;
8
import com.jsql.util.LogLevelUtil;
9
import com.jsql.util.StringUtil;
10
import org.apache.commons.lang3.StringUtils;
11
import org.apache.logging.log4j.LogManager;
12
import org.apache.logging.log4j.Logger;
13
14
import java.util.AbstractMap.SimpleEntry;
15
import java.util.Arrays;
16
import java.util.List;
17
import java.util.regex.Matcher;
18
19
public class MediatorStrategy {
20
21
    /**
22
     * Log4j logger sent to view.
23
     */
24
    private static final Logger LOGGER = LogManager.getRootLogger();
25
    
26
    private final AbstractStrategy time;
27
    private final AbstractStrategy blindBit;
28
    private final AbstractStrategy blindBin;
29
    private final AbstractStrategy multibit;
30
    private final StrategyError error;
31
    private final AbstractStrategy union;
32
    private final AbstractStrategy stack;
33
34
    private final List<AbstractStrategy> strategies;
35
    
36
    /**
37
     * Current injection strategy.
38
     */
39
    private AbstractStrategy strategy;
40
41
    private final InjectionModel injectionModel;
42
    
43
    public MediatorStrategy(InjectionModel injectionModel) {
44
        this.injectionModel = injectionModel;
45
        
46
        this.time = new StrategyTime(this.injectionModel);
47
        this.blindBit = new StrategyBlindBit(this.injectionModel);
48
        this.blindBin = new StrategyBlindBin(this.injectionModel);
49
        this.multibit = new StrategyMultibit(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.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().getPreferencesUtil().isDiosStrategy()) {
61
            strategyMode = "dios";
62 1 1. getMeta : negated conditional → NO_COVERAGE
        } else if (this.injectionModel.getMediatorUtils().getPreferencesUtil().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.injectionModel.getIndexesInUrl().replaceAll(
87
                            String.format(VendorYaml.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().getPreferencesUtil().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.getMediatorVendor().getVendor().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/vendor/MediatorVendor::setVendor → NO_COVERAGE
        this.injectionModel.getMediatorVendor().setVendor(this.injectionModel.getMediatorVendor().fingerprintVendor());
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().getParameterUtil().initStar(parameterToInject);
151
            
152 1 1. testStrategies : negated conditional → NO_COVERAGE
            String characterInsertion = this.injectionModel.getMediatorUtils().getPreferencesUtil().isNotSearchingCharInsertion()
153
                ? characterInsertionByUser
154
                : new SuspendableGetCharInsertion(this.injectionModel).run(characterInsertionByUser);
155 1 1. testStrategies : negated conditional → NO_COVERAGE
            if (characterInsertion.contains(InjectionModel.STAR)) {  // When injecting all parameters or JSON
156
                parameterToInject.setValue(characterInsertion);
157
            } else {  // When injecting last parameter
158
                parameterToInject.setValue(characterInsertion.replaceAll("(\\w)$", "$1+") + InjectionModel.STAR);
159
            }
160 1 1. testStrategies : negated conditional → NO_COVERAGE
        } else if (this.injectionModel.getMediatorUtils().getConnectionUtil().getUrlBase().contains(InjectionModel.STAR)) {
161
            String characterInsertion = new SuspendableGetCharInsertion(this.injectionModel).run(StringUtils.EMPTY);
162
            String urlBase = this.injectionModel.getMediatorUtils().getConnectionUtil().getUrlBase();
163 1 1. testStrategies : removed call to com/jsql/util/ConnectionUtil::setUrlBase → NO_COVERAGE
            this.injectionModel.getMediatorUtils().getConnectionUtil().setUrlBase(
164
                // Space %20 for URL, do not use +
165
                urlBase.replace(InjectionModel.STAR, characterInsertion.replaceAll("(\\w)$", "$1%20") + InjectionModel.STAR)
166
            );
167
        }
168
169 1 1. testStrategies : negated conditional → NO_COVERAGE
        if (this.injectionModel.getMediatorVendor().getVendorByUser() == this.injectionModel.getMediatorVendor().getAuto()) {
170
            new SuspendableGetVendor(this.injectionModel).run();
171
        }
172
173
        // Test each injection strategies: time < blind binary < blind bitwise < multibit < error < stack < union
174 1 1. testStrategies : removed call to com/jsql/model/injection/strategy/AbstractStrategy::checkApplicability → NO_COVERAGE
        this.time.checkApplicability();
175 1 1. testStrategies : removed call to com/jsql/model/injection/strategy/AbstractStrategy::checkApplicability → NO_COVERAGE
        this.blindBin.checkApplicability();
176 1 1. testStrategies : removed call to com/jsql/model/injection/strategy/AbstractStrategy::checkApplicability → NO_COVERAGE
        this.blindBit.checkApplicability();
177
178 1 1. testStrategies : negated conditional → NO_COVERAGE
        if (parameterToInject != null) {
179
            // Multibit requires '0'
180
            // TODO char insertion 0' should also work on "where x='$param'"
181
            var backupCharacterInsertion = parameterToInject.getValue();
182
            parameterToInject.setValue(InjectionModel.STAR);
183 1 1. testStrategies : removed call to com/jsql/model/injection/strategy/AbstractStrategy::checkApplicability → NO_COVERAGE
            this.multibit.checkApplicability();
184
            parameterToInject.setValue(backupCharacterInsertion);
185
        } else {
186 1 1. testStrategies : removed call to com/jsql/model/injection/strategy/AbstractStrategy::checkApplicability → NO_COVERAGE
            this.multibit.checkApplicability();
187
        }
188
189 1 1. testStrategies : removed call to com/jsql/model/injection/strategy/StrategyError::checkApplicability → NO_COVERAGE
        this.error.checkApplicability();
190 1 1. testStrategies : removed call to com/jsql/model/injection/strategy/AbstractStrategy::checkApplicability → NO_COVERAGE
        this.stack.checkApplicability();
191 1 1. testStrategies : removed call to com/jsql/model/injection/strategy/AbstractStrategy::checkApplicability → NO_COVERAGE
        this.union.checkApplicability();
192
193
        // Set most efficient strategy first: union > stack > error > multibit > blind bitwise > blind binary > time
194 1 1. testStrategies : removed call to com/jsql/model/injection/strategy/AbstractStrategy::activateWhenApplicable → NO_COVERAGE
        this.union.activateWhenApplicable();
195 1 1. testStrategies : removed call to com/jsql/model/injection/strategy/AbstractStrategy::activateWhenApplicable → NO_COVERAGE
        this.stack.activateWhenApplicable();
196 1 1. testStrategies : removed call to com/jsql/model/injection/strategy/StrategyError::activateWhenApplicable → NO_COVERAGE
        this.error.activateWhenApplicable();
197 1 1. testStrategies : removed call to com/jsql/model/injection/strategy/AbstractStrategy::activateWhenApplicable → NO_COVERAGE
        this.multibit.activateWhenApplicable();
198 1 1. testStrategies : removed call to com/jsql/model/injection/strategy/AbstractStrategy::activateWhenApplicable → NO_COVERAGE
        this.blindBit.activateWhenApplicable();
199 1 1. testStrategies : removed call to com/jsql/model/injection/strategy/AbstractStrategy::activateWhenApplicable → NO_COVERAGE
        this.blindBin.activateWhenApplicable();
200 1 1. testStrategies : removed call to com/jsql/model/injection/strategy/AbstractStrategy::activateWhenApplicable → NO_COVERAGE
        this.time.activateWhenApplicable();
201
202 1 1. testStrategies : negated conditional → NO_COVERAGE
        if (this.injectionModel.getMediatorStrategy().getStrategy() == null) {  // no strategy found
203
            // Restore initial parameter value on injection failure
204
            // Only when not true STAR injection
205 1 1. testStrategies : negated conditional → NO_COVERAGE
            if (parameterOriginalValue != null) {
206
                parameterToInject.setValue(parameterOriginalValue.replace(InjectionModel.STAR, StringUtils.EMPTY));
207
            }
208
209
            LOGGER.log(LogLevelUtil.CONSOLE_ERROR, "No injection found");
210 1 1. testStrategies : replaced boolean return with true for com/jsql/model/injection/strategy/MediatorStrategy::testStrategies → NO_COVERAGE
            return false;
211
        }
212
        
213 1 1. testStrategies : replaced boolean return with false for com/jsql/model/injection/strategy/MediatorStrategy::testStrategies → NO_COVERAGE
        return true;
214
    }
215
    
216
    
217
    // Getter and setter
218
219
    public AbstractStrategy getUnion() {
220 1 1. getUnion : replaced return value with null for com/jsql/model/injection/strategy/MediatorStrategy::getUnion → NO_COVERAGE
        return this.union;
221
    }
222
223
    public StrategyUnion getSpecificUnion() {
224 1 1. getSpecificUnion : replaced return value with null for com/jsql/model/injection/strategy/MediatorStrategy::getSpecificUnion → NO_COVERAGE
        return (StrategyUnion) this.union;
225
    }
226
227
    public StrategyError getError() {
228 1 1. getError : replaced return value with null for com/jsql/model/injection/strategy/MediatorStrategy::getError → NO_COVERAGE
        return this.error;
229
    }
230
231
    public AbstractStrategy getBlindBit() {
232 1 1. getBlindBit : replaced return value with null for com/jsql/model/injection/strategy/MediatorStrategy::getBlindBit → NO_COVERAGE
        return this.blindBit;
233
    }
234
235
    public AbstractStrategy getMultibit() {
236 1 1. getMultibit : replaced return value with null for com/jsql/model/injection/strategy/MediatorStrategy::getMultibit → SURVIVED
        return this.multibit;
237
    }
238
239
    public AbstractStrategy getTime() {
240 1 1. getTime : replaced return value with null for com/jsql/model/injection/strategy/MediatorStrategy::getTime → NO_COVERAGE
        return this.time;
241
    }
242
243
    public AbstractStrategy getStack() {
244 1 1. getStack : replaced return value with null for com/jsql/model/injection/strategy/MediatorStrategy::getStack → NO_COVERAGE
        return this.stack;
245
    }
246
247
    public List<AbstractStrategy> getStrategies() {
248 1 1. getStrategies : replaced return value with Collections.emptyList for com/jsql/model/injection/strategy/MediatorStrategy::getStrategies → NO_COVERAGE
        return this.strategies;
249
    }
250
251
    public AbstractStrategy getStrategy() {
252 1 1. getStrategy : replaced return value with null for com/jsql/model/injection/strategy/MediatorStrategy::getStrategy → SURVIVED
        return this.strategy;
253
    }
254
255
    public void setStrategy(AbstractStrategy strategy) {
256
        this.strategy = strategy;
257
    }
258
259
    public AbstractStrategy getBlindBin() {
260 1 1. getBlindBin : replaced return value with null for com/jsql/model/injection/strategy/MediatorStrategy::getBlindBin → NO_COVERAGE
        return this.blindBin;
261
    }
262
}

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/vendor/MediatorVendor::setVendor → 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

155

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

160

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

163

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

169

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

174

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

175

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

176

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

178

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

183

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

186

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

189

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

190

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

191

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/AbstractStrategy::activateWhenApplicable → NO_COVERAGE

195

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

196

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

197

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

198

1.1
Location : testStrategies
Killed by : none
removed call to com/jsql/model/injection/strategy/AbstractStrategy::activateWhenApplicable → 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

202

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

205

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

210

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

213

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

220

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

224

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

228

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

232

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

236

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

240

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

244

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

248

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

252

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

260

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

Active mutators

Tests examined


Report generated by PIT 1.19.1