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

Mutations

50

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

59

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

62

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

65

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

69

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

70

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

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

71

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

73

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

78

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

80

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

81

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

83

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

86

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

93

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

100

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

105

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

110

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

119

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

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

124

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

127

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

130

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

131

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

150

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

176

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

180

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

183

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

191

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

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

194

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

200

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

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

201

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

211

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

213

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

221

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

226

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

230

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

Active mutators

Tests examined


Report generated by PIT 1.16.1