InjectionBlind.java

1
package com.jsql.model.injection.strategy.blind;
2
3
import com.jsql.model.InjectionModel;
4
import com.jsql.model.exception.StoppedByUserSlidingException;
5
import com.jsql.model.injection.strategy.blind.patch.Diff;
6
import com.jsql.util.LogLevelUtil;
7
import org.apache.commons.lang3.StringUtils;
8
import org.apache.logging.log4j.LogManager;
9
import org.apache.logging.log4j.Logger;
10
11
import java.util.ArrayList;
12
import java.util.Collection;
13
import java.util.List;
14
import java.util.concurrent.ExecutionException;
15
import java.util.concurrent.ExecutorService;
16
import java.util.concurrent.Future;
17
18
/**
19
 * A blind attack class using concurrent threads.
20
 */
21
public class InjectionBlind extends AbstractInjectionMonobit<CallableBlind> {
22
    
23
    /**
24
     * Log4j logger sent to view.
25
     */
26
    private static final Logger LOGGER = LogManager.getRootLogger();
27
28
    // Source code of the TRUE web page (usually ?id=1)
29
    private String sourceReferencePage;
30
31
    /**
32
     * List of string differences found in all the FALSE queries, compared
33
     * to the reference page. Each FALSE pages should contain
34
     * at least one same string, which shouldn't be present in all
35
     * the TRUE queries.
36
     */
37
    private List<Diff> falseDiffs = new ArrayList<>();
38
39
    /**
40
     * Create blind attack initialization.
41
     * If every false diffs are not in true diffs and every true diffs are in
42
     * true diffs, then Blind attack is confirmed.
43
     * @param blindMode
44
     */
45
    public InjectionBlind(InjectionModel injectionModel, BooleanMode blindMode) {
46
        
47
        super(injectionModel, blindMode);
48
        
49
        // No blind
50 2 1. <init> : negated conditional → NO_COVERAGE
2. <init> : negated conditional → NO_COVERAGE
        if (this.falsy.isEmpty() || this.injectionModel.isStoppedByUser()) {
51
            return;
52
        }
53
        
54
        // Call the SQL request which must be TRUE (usually ?id=1)
55
        this.sourceReferencePage = this.callUrl(StringUtils.EMPTY, "blind#ref");
56
57
        // Concurrent calls to the FALSE statements,
58
        // it will use inject() from the model
59
        ExecutorService taskExecutor = this.injectionModel.getMediatorUtils().getThreadUtil().getExecutor("CallableGetBlindTagFalse");
60
        Collection<CallableBlind> callablesFalseTest = new ArrayList<>();
61
        
62
        for (String falseTest: this.falsy) {
63
            callablesFalseTest.add(new CallableBlind(
64
                falseTest,
65
                injectionModel,
66
                this,
67
                blindMode,
68
                "blind#falsy"
69
            ));
70
        }
71
        
72
        // Delete junk from the results of FALSE statements,
73
        // keep only diffs found in each and every FALSE pages.
74
        // Allow the user to stop the loop
75
        try {
76
            List<Future<CallableBlind>> futuresFalseTest = taskExecutor.invokeAll(callablesFalseTest);
77 1 1. <init> : removed call to com/jsql/util/ThreadUtil::shutdown → NO_COVERAGE
            this.injectionModel.getMediatorUtils().getThreadUtil().shutdown(taskExecutor);
78
79
            for (Future<CallableBlind> futureFalseTest: futuresFalseTest) {
80
81 1 1. <init> : negated conditional → NO_COVERAGE
                if (this.injectionModel.isStoppedByUser()) {
82
                    return;
83
                }
84
85 1 1. <init> : negated conditional → NO_COVERAGE
                if (this.falseDiffs.isEmpty()) {
86
                    this.falseDiffs = futureFalseTest.get().getDiffsWithReference();  // Init diffs
87
                } else {
88
                    this.falseDiffs.retainAll(futureFalseTest.get().getDiffsWithReference());  // Clean un-matching diffs
89
                }
90
            }
91
        } catch (ExecutionException e) {
92
            LOGGER.log(LogLevelUtil.CONSOLE_JAVA, e, e);
93
        } catch (InterruptedException e) {
94
            
95
            LOGGER.log(LogLevelUtil.IGNORE, e, e);
96 1 1. <init> : removed call to java/lang/Thread::interrupt → NO_COVERAGE
            Thread.currentThread().interrupt();
97
        }
98
99 1 1. <init> : negated conditional → NO_COVERAGE
        if (this.injectionModel.isStoppedByUser()) {
100
            return;
101
        }
102
        
103 1 1. <init> : removed call to com/jsql/model/injection/strategy/blind/InjectionBlind::cleanTrueDiffs → NO_COVERAGE
        this.cleanTrueDiffs(injectionModel, blindMode);
104
    }
105
106
    private void cleanTrueDiffs(InjectionModel injectionModel, BooleanMode blindMode) {
107
        
108
        // Concurrent calls to the TRUE statements,
109
        // it will use inject() from the model.
110
        ExecutorService taskExecutor = this.injectionModel.getMediatorUtils().getThreadUtil().getExecutor("CallableGetBlindTagTrue");
111
112
        Collection<CallableBlind> callablesTrueTest = new ArrayList<>();
113
        
114
        for (String trueTest: this.truthy) {
115
            callablesTrueTest.add(new CallableBlind(
116
                trueTest,
117
                injectionModel,
118
                this,
119
                blindMode,
120
                "blind#truthy"
121
            ));
122
        }
123
        
124
        // Remove TRUE diffs in the FALSE diffs, because
125
        // a significant FALSE statement shouldn't contain any TRUE diff.
126
        // Allow the user to stop the loop.
127
        try {
128
            List<Future<CallableBlind>> futuresTrueTest = taskExecutor.invokeAll(callablesTrueTest);
129 1 1. cleanTrueDiffs : removed call to com/jsql/util/ThreadUtil::shutdown → NO_COVERAGE
            this.injectionModel.getMediatorUtils().getThreadUtil().shutdown(taskExecutor);
130
        
131
            for (Future<CallableBlind> futureTrueTest: futuresTrueTest) {
132
                
133 1 1. cleanTrueDiffs : negated conditional → NO_COVERAGE
                if (this.injectionModel.isStoppedByUser()) {
134
                    return;
135
                }
136
                this.falseDiffs.removeAll(futureTrueTest.get().getDiffsWithReference());
137
            }
138
        } catch (ExecutionException e) {
139
            LOGGER.log(LogLevelUtil.CONSOLE_JAVA, e, e);
140
        } catch (InterruptedException e) {
141
            
142
            LOGGER.log(LogLevelUtil.IGNORE, e, e);
143 1 1. cleanTrueDiffs : removed call to java/lang/Thread::interrupt → NO_COVERAGE
            Thread.currentThread().interrupt();
144
        }
145
    }
146
147
    @Override
148
    public CallableBlind getCallableBitTest(String sqlQuery, int indexCharacter, int bit) {
149 1 1. getCallableBitTest : replaced return value with null for com/jsql/model/injection/strategy/blind/InjectionBlind::getCallableBitTest → NO_COVERAGE
        return new CallableBlind(
150
            sqlQuery,
151
            indexCharacter,
152
            bit,
153
            this.injectionModel,
154
            this,
155
            this.booleanMode,
156
            "bit#" + indexCharacter + "~" + bit
157
        );
158
    }
159
160
    @Override
161
    public boolean isInjectable() throws StoppedByUserSlidingException {
162
        
163 1 1. isInjectable : negated conditional → NO_COVERAGE
        if (this.injectionModel.isStoppedByUser()) {
164
            throw new StoppedByUserSlidingException();
165
        }
166
        
167
        var blindTest = new CallableBlind(
168
            this.injectionModel.getMediatorVendor().getVendor().instance().sqlTestBooleanInitialization(),
169
            this.injectionModel,
170
            this,
171
            this.booleanMode,
172
            "blind#confirm"
173
        );
174
        
175
        try {
176
            blindTest.call();
177
        } catch (Exception e) {
178
            LOGGER.log(LogLevelUtil.CONSOLE_JAVA, e, e);
179
        }
180
181 3 1. isInjectable : replaced boolean return with true for com/jsql/model/injection/strategy/blind/InjectionBlind::isInjectable → NO_COVERAGE
2. isInjectable : negated conditional → NO_COVERAGE
3. isInjectable : negated conditional → NO_COVERAGE
        return blindTest.isTrue() && !this.falseDiffs.isEmpty();
182
    }
183
184
    @Override
185
    public String getInfoMessage() {
186 1 1. getInfoMessage : replaced return value with "" for com/jsql/model/injection/strategy/blind/InjectionBlind::getInfoMessage → NO_COVERAGE
        return "- Strategy Blind: query True when Diffs are matching " + this.falseDiffs + "\n\n";
187
    }
188
    
189
    
190
    // Getter and setter
191
192
    public String getSourceReferencePage() {
193 1 1. getSourceReferencePage : replaced return value with "" for com/jsql/model/injection/strategy/blind/InjectionBlind::getSourceReferencePage → NO_COVERAGE
        return this.sourceReferencePage;
194
    }
195
    
196
    public List<Diff> getFalseDiffs() {
197 1 1. getFalseDiffs : replaced return value with Collections.emptyList for com/jsql/model/injection/strategy/blind/InjectionBlind::getFalseDiffs → NO_COVERAGE
        return this.falseDiffs;
198
    }
199
}

Mutations

50

1.1
Location : <init>
Killed by : none
negated conditional → NO_COVERAGE

2.2
Location : <init>
Killed by : none
negated conditional → NO_COVERAGE

77

1.1
Location : <init>
Killed by : none
removed call to com/jsql/util/ThreadUtil::shutdown → NO_COVERAGE

81

1.1
Location : <init>
Killed by : none
negated conditional → NO_COVERAGE

85

1.1
Location : <init>
Killed by : none
negated conditional → NO_COVERAGE

96

1.1
Location : <init>
Killed by : none
removed call to java/lang/Thread::interrupt → NO_COVERAGE

99

1.1
Location : <init>
Killed by : none
negated conditional → NO_COVERAGE

103

1.1
Location : <init>
Killed by : none
removed call to com/jsql/model/injection/strategy/blind/InjectionBlind::cleanTrueDiffs → NO_COVERAGE

129

1.1
Location : cleanTrueDiffs
Killed by : none
removed call to com/jsql/util/ThreadUtil::shutdown → NO_COVERAGE

133

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

143

1.1
Location : cleanTrueDiffs
Killed by : none
removed call to java/lang/Thread::interrupt → NO_COVERAGE

149

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

163

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

181

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

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

3.3
Location : isInjectable
Killed by : none
negated conditional → NO_COVERAGE

186

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

193

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

197

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

Active mutators

Tests examined


Report generated by PIT 1.16.1