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.model.injection.strategy.blind.patch.Diff;
7 import com.jsql.model.injection.strategy.blind.patch.DiffMatchPatch;
8 import com.jsql.util.LogLevelUtil;
9 import org.apache.commons.lang3.StringUtils;
10 import org.apache.logging.log4j.LogManager;
11 import org.apache.logging.log4j.Logger;
12
13 import java.util.ArrayList;
14 import java.util.Collection;
15 import java.util.List;
16 import java.util.concurrent.ExecutionException;
17 import java.util.concurrent.ExecutorService;
18 import java.util.concurrent.Future;
19
20
21
22
23 public class InjectionBlindBit extends AbstractInjectionMonobit<CallableBlindBit> {
24
25 private static final Logger LOGGER = LogManager.getRootLogger();
26
27 private String sourceReferencePage;
28
29
30
31
32
33
34
35 private List<Diff> falseDiffs = new ArrayList<>();
36 private List<Diff> trueDiffs = new ArrayList<>();
37
38
39
40
41
42
43 public InjectionBlindBit(InjectionModel injectionModel, BlindOperator blindOperator) {
44 super(injectionModel, blindOperator);
45
46 List<String> falsys = this.injectionModel.getMediatorVendor().getVendor().instance().getFalsyBit();
47 if (falsys.isEmpty() || this.injectionModel.isStoppedByUser()) {
48 return;
49 }
50
51
52 this.sourceReferencePage = this.callUrl(StringUtils.EMPTY, "bit#ref:"+ blindOperator.toString().toLowerCase());
53
54
55
56 ExecutorService taskExecutor = this.injectionModel.getMediatorUtils().getThreadUtil().getExecutor("CallableGetBlindBitTagFalse");
57 Collection<CallableBlindBit> callablesFalsys = new ArrayList<>();
58 for (String falsy: falsys) {
59 callablesFalsys.add(new CallableBlindBit(
60 falsy,
61 injectionModel,
62 this,
63 blindOperator,
64 "bit#falsy"
65 ));
66 }
67
68
69
70
71 try {
72 List<Future<CallableBlindBit>> futuresFalsys = taskExecutor.invokeAll(callablesFalsys);
73 this.injectionModel.getMediatorUtils().getThreadUtil().shutdown(taskExecutor);
74 for (Future<CallableBlindBit> futureFalsy: futuresFalsys) {
75 if (this.injectionModel.isStoppedByUser()) {
76 return;
77 }
78 if (this.falseDiffs.isEmpty()) {
79 this.falseDiffs = futureFalsy.get().getDiffsWithReference();
80 } else {
81 this.falseDiffs.retainAll(futureFalsy.get().getDiffsWithReference());
82 }
83 }
84 } catch (ExecutionException e) {
85 LOGGER.log(LogLevelUtil.CONSOLE_JAVA, e, e);
86 } catch (InterruptedException e) {
87 LOGGER.log(LogLevelUtil.IGNORE, e, e);
88 Thread.currentThread().interrupt();
89 }
90
91 if (this.injectionModel.isStoppedByUser()) {
92 return;
93 }
94
95 this.cleanTrueDiffs(injectionModel, blindOperator);
96 }
97
98 private void cleanTrueDiffs(InjectionModel injectionModel, BlindOperator blindOperator) {
99 ExecutorService taskExecutor = this.injectionModel.getMediatorUtils().getThreadUtil().getExecutor("CallableGetBlindBitTagTrue");
100 Collection<CallableBlindBit> callablesTruthys = new ArrayList<>();
101 List<String> truthys = this.injectionModel.getMediatorVendor().getVendor().instance().getTruthyBit();
102 for (String truthy: truthys) {
103 callablesTruthys.add(new CallableBlindBit(
104 truthy,
105 injectionModel,
106 this,
107 blindOperator,
108 "bit#truthy"
109 ));
110 }
111
112
113 try {
114 List<Future<CallableBlindBit>> futuresTruthys = taskExecutor.invokeAll(callablesTruthys);
115 this.injectionModel.getMediatorUtils().getThreadUtil().shutdown(taskExecutor);
116 for (Future<CallableBlindBit> futureTruthy: futuresTruthys) {
117 if (this.injectionModel.isStoppedByUser()) {
118 return;
119 }
120 if (this.trueDiffs.isEmpty()) {
121 this.trueDiffs = futureTruthy.get().getDiffsWithReference();
122 } else {
123 this.trueDiffs.retainAll(futureTruthy.get().getDiffsWithReference());
124 }
125 this.falseDiffs.removeAll(futureTruthy.get().getDiffsWithReference());
126 }
127 } catch (ExecutionException e) {
128 LOGGER.log(LogLevelUtil.CONSOLE_JAVA, e, e);
129 } catch (InterruptedException e) {
130 LOGGER.log(LogLevelUtil.IGNORE, e, e);
131 Thread.currentThread().interrupt();
132 }
133 }
134
135 @Override
136 public CallableBlindBit getCallableBitTest(String sqlQuery, int indexChar, int bit) {
137 return new CallableBlindBit(
138 sqlQuery,
139 indexChar,
140 bit,
141 this.injectionModel,
142 this,
143 this.blindOperator,
144 "bit#" + indexChar + "~" + bit
145 );
146 }
147
148 @Override
149 public boolean isInjectable() throws StoppedByUserSlidingException {
150 if (this.injectionModel.isStoppedByUser()) {
151 throw new StoppedByUserSlidingException();
152 }
153 var callable = new CallableBlindBit(
154 this.injectionModel.getMediatorVendor().getVendor().instance().sqlBlindConfirm(),
155 this.injectionModel,
156 this,
157 this.blindOperator,
158 "bit#confirm"
159 );
160 try {
161 callable.call();
162 } catch (Exception e) {
163 LOGGER.log(LogLevelUtil.CONSOLE_JAVA, e, e);
164 }
165 return callable.isTrue()
166
167 && this.trueDiffs.stream().anyMatch(diff -> !DiffMatchPatch.Operation.EQUAL.equals(diff.getOperation()))
168 || this.falseDiffs.stream().anyMatch(diff -> !DiffMatchPatch.Operation.EQUAL.equals(diff.getOperation()));
169 }
170
171 @Override
172 public String getInfoMessage() {
173 return "- Strategy Blind bit: query True when Diffs are matching " + this.falseDiffs + "\n\n";
174 }
175
176
177
178
179 public String getSourceReferencePage() {
180 return this.sourceReferencePage;
181 }
182
183 public List<Diff> getFalseDiffs() {
184 return this.falseDiffs;
185 }
186
187 public List<Diff> getTrueDiffs() {
188 return this.trueDiffs;
189 }
190 }