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

Mutations

50

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

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

76

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

78

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

81

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

91

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

94

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

98

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

121

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

123

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

132

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

139

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

152

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

167

1.1
Location : isInjectable
Killed by : none
replaced boolean return with true for com/jsql/model/injection/strategy/blind/InjectionBlindBit::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

172

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

179

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

183

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

Active mutators

Tests examined


Report generated by PIT 1.19.1