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