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

Mutations

55

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

57

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

59

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

62

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

76

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

77

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

91

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

97

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

115

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

135

1.1
Location : testStrategies
Killed by : none
removed call to com/jsql/model/injection/vendor/MediatorVendor::setVendor → NO_COVERAGE

143

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

149

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

160

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

166

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

171

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

172

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

173

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
negated conditional → NO_COVERAGE

180

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

187

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

188

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

192

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

193

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

197

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
negated conditional → NO_COVERAGE

202

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

207

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

210

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

217

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

221

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

225

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

229

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

233

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

237

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

241

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

245

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

249

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

253

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.19.1