StrategyUnion.java

1
package com.jsql.model.injection.strategy;
2
3
import com.jsql.model.InjectionModel;
4
import com.jsql.model.accessible.DataAccess;
5
import com.jsql.model.bean.util.Interaction;
6
import com.jsql.model.bean.util.Request;
7
import com.jsql.model.exception.JSqlException;
8
import com.jsql.model.injection.vendor.model.VendorYaml;
9
import com.jsql.model.suspendable.AbstractSuspendable;
10
import com.jsql.model.suspendable.SuspendableGetIndexes;
11
import com.jsql.util.I18nUtil;
12
import com.jsql.util.LogLevelUtil;
13
import com.jsql.util.StringUtil;
14
import org.apache.commons.lang3.StringUtils;
15
import org.apache.logging.log4j.LogManager;
16
import org.apache.logging.log4j.Logger;
17
18
import java.util.ArrayList;
19
import java.util.Arrays;
20
import java.util.Comparator;
21
import java.util.List;
22
import java.util.regex.Pattern;
23
24
public class StrategyUnion extends AbstractStrategy {
25
    
26
    private static final Logger LOGGER = LogManager.getRootLogger();
27
28
    protected String visibleIndex;  // matching index
29
    protected String sourceIndexesFound = StringUtils.EMPTY;  // matching page source
30
    private int nbIndexesFound = 0;
31
32
    private String performanceLength = "0";
33
    
34
    public StrategyUnion(InjectionModel injectionModel) {
35
        super(injectionModel);
36
    }
37
38
    @Override
39
    public void checkApplicability() throws JSqlException {
40 1 1. checkApplicability : negated conditional → NO_COVERAGE
        if (this.injectionModel.getMediatorUtils().getPreferencesUtil().isStrategyUnionDisabled()) {
41
            LOGGER.log(LogLevelUtil.CONSOLE_INFORM, AbstractStrategy.FORMAT_SKIP_STRATEGY_DISABLED, this.getName());
42
            return;
43
        }
44
45 1 1. checkApplicability : removed call to com/jsql/model/injection/strategy/StrategyUnion::logChecking → NO_COVERAGE
        this.logChecking();
46
47 1 1. checkApplicability : removed call to com/jsql/model/InjectionModel::setIndexesInUrl → NO_COVERAGE
        this.injectionModel.setIndexesInUrl(new SuspendableGetIndexes(this.injectionModel).run());
48
49
        // Define visibleIndex, i.e, 2 in "..union select 1,2,..", if 2 is found in HTML body
50 1 1. checkApplicability : negated conditional → NO_COVERAGE
        if (StringUtils.isNotEmpty(this.injectionModel.getIndexesInUrl())) {
51
            this.visibleIndex = this.getVisibleIndex(this.sourceIndexesFound);
52
        }
53
        
54 1 1. checkApplicability : negated conditional → NO_COVERAGE
        this.isApplicable = StringUtils.isNotEmpty(this.injectionModel.getIndexesInUrl())
55 2 1. checkApplicability : changed conditional boundary → NO_COVERAGE
2. checkApplicability : negated conditional → NO_COVERAGE
            && Integer.parseInt(this.injectionModel.getMediatorStrategy().getUnion().getPerformanceLength()) > 0
56 1 1. checkApplicability : negated conditional → NO_COVERAGE
            && StringUtils.isNotBlank(this.visibleIndex);
57
        
58 1 1. checkApplicability : negated conditional → NO_COVERAGE
        if (this.isApplicable) {
59
            LOGGER.log(
60
                LogLevelUtil.CONSOLE_SUCCESS,
61
                "{} [{}] at index [{}] showing [{}] characters",
62 1 1. lambda$checkApplicability$0 : replaced return value with null for com/jsql/model/injection/strategy/StrategyUnion::lambda$checkApplicability$0 → NO_COVERAGE
                () -> I18nUtil.valueByKey("LOG_VULNERABLE"),
63
                this::getName,
64 1 1. lambda$checkApplicability$1 : replaced return value with null for com/jsql/model/injection/strategy/StrategyUnion::lambda$checkApplicability$1 → NO_COVERAGE
                () -> this.visibleIndex,
65 1 1. lambda$checkApplicability$2 : replaced return value with null for com/jsql/model/injection/strategy/StrategyUnion::lambda$checkApplicability$2 → NO_COVERAGE
                () -> this.performanceLength
66
            );
67 1 1. checkApplicability : removed call to com/jsql/model/injection/strategy/StrategyUnion::allow → NO_COVERAGE
            this.allow();
68
        } else {
69 1 1. checkApplicability : removed call to com/jsql/model/injection/strategy/StrategyUnion::unallow → NO_COVERAGE
            this.unallow();
70
        }
71
    }
72
73
    @Override
74
    public void allow(int... i) {
75 1 1. allow : removed call to com/jsql/model/InjectionModel::appendAnalysisReport → NO_COVERAGE
        this.injectionModel.appendAnalysisReport(
76
            StringUtil.formatReport(LogLevelUtil.COLOR_BLU, "### Strategy: " + this.getName())
77
            + this.injectionModel.getReportWithIndexes(
78
                this.injectionModel.getMediatorVendor().getVendor().instance().sqlUnion(StringUtil.formatReport(LogLevelUtil.COLOR_GREEN, "<query>"), "0", true),
79
                "metadataInjectionProcess"
80
            )
81
        );
82 1 1. allow : removed call to com/jsql/model/injection/strategy/StrategyUnion::markVulnerability → NO_COVERAGE
        this.markVulnerability(Interaction.MARK_UNION_VULNERABLE);
83
    }
84
85
    @Override
86
    public void unallow(int... i) {
87 1 1. unallow : removed call to com/jsql/model/injection/strategy/StrategyUnion::markVulnerability → NO_COVERAGE
        this.markVulnerability(Interaction.MARK_UNION_INVULNERABLE);
88
    }
89
90
    @Override
91
    public String inject(String sqlQuery, String startPosition, AbstractSuspendable stoppable, String metadataInjectionProcess) {
92 1 1. inject : replaced return value with "" for com/jsql/model/injection/strategy/StrategyUnion::inject → NO_COVERAGE
        return this.injectionModel.injectWithIndexes(
93
            this.injectionModel.getMediatorVendor().getVendor().instance().sqlUnion(sqlQuery, startPosition, false),
94
            metadataInjectionProcess
95
        );
96
    }
97
98
    @Override
99
    public void activateWhenApplicable() {
100 2 1. activateWhenApplicable : negated conditional → NO_COVERAGE
2. activateWhenApplicable : negated conditional → NO_COVERAGE
        if (this.injectionModel.getMediatorStrategy().getStrategy() == null && this.isApplicable()) {
101
            LOGGER.log(
102
                LogLevelUtil.CONSOLE_INFORM,
103
                "{} [{}]",
104 1 1. lambda$activateWhenApplicable$3 : replaced return value with null for com/jsql/model/injection/strategy/StrategyUnion::lambda$activateWhenApplicable$3 → NO_COVERAGE
                () -> I18nUtil.valueByKey("LOG_USING_STRATEGY"),
105
                this::getName
106
            );
107 1 1. activateWhenApplicable : removed call to com/jsql/model/injection/strategy/MediatorStrategy::setStrategy → NO_COVERAGE
            this.injectionModel.getMediatorStrategy().setStrategy(this);
108
109
            var request = new Request();
110 1 1. activateWhenApplicable : removed call to com/jsql/model/bean/util/Request::setMessage → NO_COVERAGE
            request.setMessage(Interaction.MARK_UNION_STRATEGY);
111 1 1. activateWhenApplicable : removed call to com/jsql/model/InjectionModel::sendToViews → NO_COVERAGE
            this.injectionModel.sendToViews(request);
112
        }
113
    }
114
    
115
    /**
116
     * Runnable class, search the most efficient index.<br>
117
     * Some indexes will display a lots of characters, others won't,
118
     * so sort them by order of efficiency:<br>
119
     * find the one that displays the most number of characters.
120
     * @return Integer index with most efficiency and visible in source code
121
     */
122
    public String getVisibleIndex(String firstSuccessPageSource) {
123
        // Parse all indexes found
124
        // Fix #4007 (initialize firstSuccessPageSource to empty String instead of null)
125
        String regexAllIndexes = String.format(VendorYaml.FORMAT_INDEX, "(\\d+?)");
126
        var regexSearch = Pattern.compile("(?s)"+ regexAllIndexes).matcher(firstSuccessPageSource);
127
        
128
        List<String> foundIndexes = new ArrayList<>();
129 1 1. getVisibleIndex : negated conditional → NO_COVERAGE
        while (regexSearch.find()) {
130
            foundIndexes.add(regexSearch.group(1));
131
        }
132
133
        String[] indexes = foundIndexes.toArray(new String[0]);
134
135
        // Make url shorter, replace useless indexes from 1337[index]7331 to 1
136
        String regexAllExceptIndexesFound = String.format(
137
            VendorYaml.FORMAT_INDEX,
138
            "(?!"+ String.join("|", indexes) +"7331)\\d*"
139
        );
140
        String indexesInUrl = this.injectionModel.getIndexesInUrl().replaceAll(regexAllExceptIndexesFound, "1");
141
142
        // Replace correct indexes from 1337(index)7331 to
143
        // ==> ${lead}(index)######...######
144
        // Search for index that displays the most #
145
        String performanceQuery = this.injectionModel.getMediatorVendor().getVendor().instance().sqlCapacity(indexes);
146
        String performanceSourcePage = this.injectionModel.injectWithoutIndex(performanceQuery, "union#size");
147
148
        // Build a 2D array of string with:
149
        //     column 1: index
150
        //     column 2: # found, so #######...#######
151
        regexSearch = Pattern.compile("(?s)"+ DataAccess.LEAD +"(\\d+)("+ VendorYaml.CALIBRATOR_SQL +"+)").matcher(performanceSourcePage);
152
        List<String[]> performanceResults = new ArrayList<>();
153 1 1. getVisibleIndex : negated conditional → NO_COVERAGE
        while (regexSearch.find()) {
154
            performanceResults.add(new String[]{regexSearch.group(1), regexSearch.group(2)});
155
        }
156
157 1 1. getVisibleIndex : negated conditional → NO_COVERAGE
        if (performanceResults.isEmpty()) {
158
            this.performanceLength = "0";
159 1 1. getVisibleIndex : replaced return value with "" for com/jsql/model/injection/strategy/StrategyUnion::getVisibleIndex → NO_COVERAGE
            return null;
160
        }
161
        
162
        // Switch from previous array to 2D integer array
163
        //     column 1: length of #######...#######
164
        //     column 2: index
165
        var lengthFields = new Integer[performanceResults.size()][2];
166
        
167 2 1. getVisibleIndex : changed conditional boundary → NO_COVERAGE
2. getVisibleIndex : negated conditional → NO_COVERAGE
        for (var i = 0 ; i < performanceResults.size() ; i++) {
168
            lengthFields[i] = new Integer[] {
169 1 1. getVisibleIndex : Replaced integer addition with subtraction → NO_COVERAGE
                performanceResults.get(i)[1].length() + performanceResults.get(i)[0].length(),
170
                Integer.parseInt(performanceResults.get(i)[0])
171
            };
172
        }
173
174
        // Sort by length of #######...#######
175 2 1. getVisibleIndex : removed call to java/util/Arrays::sort → NO_COVERAGE
2. lambda$getVisibleIndex$4 : replaced Integer return value with 0 for com/jsql/model/injection/strategy/StrategyUnion::lambda$getVisibleIndex$4 → NO_COVERAGE
        Arrays.sort(lengthFields, Comparator.comparing((Integer[] s) -> s[0]));
176 1 1. getVisibleIndex : Replaced integer subtraction with addition → NO_COVERAGE
        Integer[] bestLengthFields = lengthFields[lengthFields.length - 1];
177
        this.performanceLength = bestLengthFields[0].toString();
178
179
        // Reduce all others indexes
180
        String regexAllIndexesExceptBest = String.format(
181
            VendorYaml.FORMAT_INDEX,
182
            "(?!"+ bestLengthFields[1] +"7331)\\d*"
183
        );
184
        indexesInUrl = indexesInUrl.replaceAll(regexAllIndexesExceptBest, "1");
185
        
186 1 1. getVisibleIndex : removed call to com/jsql/model/InjectionModel::setIndexesInUrl → NO_COVERAGE
        this.injectionModel.setIndexesInUrl(indexesInUrl);
187
        
188 1 1. getVisibleIndex : replaced return value with "" for com/jsql/model/injection/strategy/StrategyUnion::getVisibleIndex → NO_COVERAGE
        return Integer.toString(bestLengthFields[1]);
189
    }
190
    
191
    
192
    // Getters and setters
193
    
194
    @Override
195
    public String getPerformanceLength() {
196 1 1. getPerformanceLength : replaced return value with "" for com/jsql/model/injection/strategy/StrategyUnion::getPerformanceLength → NO_COVERAGE
        return this.performanceLength;
197
    }
198
    
199
    @Override
200
    public String getName() {
201 1 1. getName : replaced return value with "" for com/jsql/model/injection/strategy/StrategyUnion::getName → NO_COVERAGE
        return "Union";
202
    }
203
204
    public String getVisibleIndex() {
205 1 1. getVisibleIndex : replaced return value with "" for com/jsql/model/injection/strategy/StrategyUnion::getVisibleIndex → NO_COVERAGE
        return this.visibleIndex;
206
    }
207
208
    public void setVisibleIndex(String visibleIndex) {
209
        this.visibleIndex = visibleIndex;
210
    }
211
212
    public void setSourceIndexesFound(String sourceIndexesFound) {
213
        this.sourceIndexesFound = sourceIndexesFound;
214
    }
215
216
    public int getNbIndexesFound() {
217 1 1. getNbIndexesFound : replaced int return with 0 for com/jsql/model/injection/strategy/StrategyUnion::getNbIndexesFound → NO_COVERAGE
        return this.nbIndexesFound;
218
    }
219
220
    public void setNbIndexesFound(int nbIndexesFound) {
221
        this.nbIndexesFound = nbIndexesFound;
222
    }
223
}

Mutations

40

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

45

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

47

1.1
Location : checkApplicability
Killed by : none
removed call to com/jsql/model/InjectionModel::setIndexesInUrl → NO_COVERAGE

50

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

54

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

55

1.1
Location : checkApplicability
Killed by : none
changed conditional boundary → NO_COVERAGE

2.2
Location : checkApplicability
Killed by : none
negated conditional → NO_COVERAGE

56

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

58

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

62

1.1
Location : lambda$checkApplicability$0
Killed by : none
replaced return value with null for com/jsql/model/injection/strategy/StrategyUnion::lambda$checkApplicability$0 → NO_COVERAGE

64

1.1
Location : lambda$checkApplicability$1
Killed by : none
replaced return value with null for com/jsql/model/injection/strategy/StrategyUnion::lambda$checkApplicability$1 → NO_COVERAGE

65

1.1
Location : lambda$checkApplicability$2
Killed by : none
replaced return value with null for com/jsql/model/injection/strategy/StrategyUnion::lambda$checkApplicability$2 → NO_COVERAGE

67

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

69

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

75

1.1
Location : allow
Killed by : none
removed call to com/jsql/model/InjectionModel::appendAnalysisReport → NO_COVERAGE

82

1.1
Location : allow
Killed by : none
removed call to com/jsql/model/injection/strategy/StrategyUnion::markVulnerability → NO_COVERAGE

87

1.1
Location : unallow
Killed by : none
removed call to com/jsql/model/injection/strategy/StrategyUnion::markVulnerability → NO_COVERAGE

92

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

100

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

2.2
Location : activateWhenApplicable
Killed by : none
negated conditional → NO_COVERAGE

104

1.1
Location : lambda$activateWhenApplicable$3
Killed by : none
replaced return value with null for com/jsql/model/injection/strategy/StrategyUnion::lambda$activateWhenApplicable$3 → NO_COVERAGE

107

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

110

1.1
Location : activateWhenApplicable
Killed by : none
removed call to com/jsql/model/bean/util/Request::setMessage → NO_COVERAGE

111

1.1
Location : activateWhenApplicable
Killed by : none
removed call to com/jsql/model/InjectionModel::sendToViews → NO_COVERAGE

129

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

153

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

157

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

159

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

167

1.1
Location : getVisibleIndex
Killed by : none
changed conditional boundary → NO_COVERAGE

2.2
Location : getVisibleIndex
Killed by : none
negated conditional → NO_COVERAGE

169

1.1
Location : getVisibleIndex
Killed by : none
Replaced integer addition with subtraction → NO_COVERAGE

175

1.1
Location : getVisibleIndex
Killed by : none
removed call to java/util/Arrays::sort → NO_COVERAGE

2.2
Location : lambda$getVisibleIndex$4
Killed by : none
replaced Integer return value with 0 for com/jsql/model/injection/strategy/StrategyUnion::lambda$getVisibleIndex$4 → NO_COVERAGE

176

1.1
Location : getVisibleIndex
Killed by : none
Replaced integer subtraction with addition → NO_COVERAGE

186

1.1
Location : getVisibleIndex
Killed by : none
removed call to com/jsql/model/InjectionModel::setIndexesInUrl → NO_COVERAGE

188

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

196

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

201

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

205

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

217

1.1
Location : getNbIndexesFound
Killed by : none
replaced int return with 0 for com/jsql/model/injection/strategy/StrategyUnion::getNbIndexesFound → NO_COVERAGE

Active mutators

Tests examined


Report generated by PIT 1.19.1