1 package com.jsql.model.injection.engine;
2
3 import com.jsql.model.InjectionModel;
4 import com.jsql.view.subscriber.Seal;
5 import com.jsql.model.injection.engine.model.Engine;
6 import com.jsql.model.injection.engine.model.EngineYaml;
7 import com.jsql.util.I18nUtil;
8 import com.jsql.util.LogLevelUtil;
9 import com.jsql.util.StringUtil;
10 import org.apache.commons.lang3.StringUtils;
11 import org.apache.commons.lang3.SystemUtils;
12 import org.apache.logging.log4j.LogManager;
13 import org.apache.logging.log4j.Logger;
14
15 import java.net.URLEncoder;
16 import java.nio.charset.StandardCharsets;
17 import java.time.LocalDate;
18 import java.time.format.DateTimeFormatter;
19 import java.util.Arrays;
20 import java.util.List;
21
22 public class MediatorEngine {
23
24 private static final Logger LOGGER = LogManager.getRootLogger();
25
26 private static final String LOG_ENGINE = "{} [{}]";
27
28
29
30
31
32 private Engine engine;
33
34
35
36
37
38 private Engine engineByUser;
39
40
41 private final Engine auto;
42 private final Engine access;
43 private final Engine altibase;
44 private final Engine clickhouse;
45 private final Engine cubrid;
46 private final Engine db2;
47 private final Engine derby;
48 private final Engine exasol;
49 private final Engine firebird;
50 private final Engine h2;
51 private final Engine hana;
52 private final Engine hsqldb;
53 private final Engine informix;
54 private final Engine mckoi;
55 private final Engine mimer;
56 private final Engine monetdb;
57 private final Engine mysql;
58 private final Engine neo4j;
59 private final Engine oracle;
60 private final Engine postgres;
61 private final Engine presto;
62 private final Engine sqlite;
63 private final Engine sqlserver;
64 private final Engine sybase;
65 private final Engine vertica;
66 private final Engine virtuoso;
67
68 private final List<Engine> engines;
69 private final List<Engine> enginesForFingerprint;
70
71 private final InjectionModel injectionModel;
72
73 public MediatorEngine(InjectionModel injectionModel) {
74 this.injectionModel = injectionModel;
75
76 Engine ctreeace = new Engine(new EngineYaml("ctreeace.yml", injectionModel));
77 Engine frontbase = new Engine(new EngineYaml("frontbase.yml", injectionModel));
78 Engine ingres = new Engine(new EngineYaml("ingres.yml", injectionModel));
79 Engine iris = new Engine(new EngineYaml("iris.yml", injectionModel));
80 Engine maxdb = new Engine(new EngineYaml("maxdb.yml", injectionModel));
81 Engine netezza = new Engine(new EngineYaml("netezza.yml", injectionModel));
82 Engine nuodb = new Engine(new EngineYaml("nuodb.yml", injectionModel));
83 Engine teradata = new Engine(new EngineYaml("teradata.yml", injectionModel));
84
85 this.auto = new Engine();
86 this.access = new Engine(new EngineYaml("access.yml", injectionModel));
87 this.altibase = new Engine(new EngineYaml("altibase.yml", injectionModel));
88 this.cubrid = new Engine(new EngineYaml("cubrid.yml", injectionModel));
89 this.clickhouse = new Engine(new EngineYaml("clickhouse.yml", injectionModel));
90 this.db2 = new Engine(new EngineYaml("db2.yml", injectionModel));
91 this.derby = new Engine(new EngineYaml("derby.yml", injectionModel));
92 this.exasol = new Engine(new EngineYaml("exasol.yml", injectionModel));
93 this.firebird = new Engine(new EngineYaml("firebird.yml", injectionModel));
94 this.h2 = new Engine(new EngineYaml("h2.yml", injectionModel));
95 this.hana = new Engine(new EngineYaml("hana.yml", injectionModel));
96 this.hsqldb = new Engine(new EngineYaml("hsqldb.yml", injectionModel));
97 this.informix = new Engine(new EngineYaml("informix.yml", injectionModel));
98 this.mckoi = new Engine(new EngineYaml("mckoi.yml", injectionModel));
99 this.mimer = new Engine(new EngineYaml("mimersql.yml", injectionModel));
100 this.monetdb = new Engine(new EngineYaml("monetdb.yml", injectionModel));
101 this.mysql = new Engine(new EngineYaml("mysql.yml", injectionModel));
102 this.neo4j = new Engine(new EngineYaml("neo4j.yml", injectionModel));
103 this.oracle = new Engine(new EngineYaml("oracle.yml", injectionModel));
104 this.postgres = new Engine(new EngineYaml("postgres.yml", injectionModel));
105 this.presto = new Engine(new EngineYaml("presto.yml", injectionModel));
106 this.sqlite = new Engine(new EngineYaml("sqlite.yml", injectionModel)) {
107 @Override
108 public String transformSqlite(String resultToParse) {
109 var resultSqlite = new StringBuilder();
110
111 String resultTmp = resultToParse
112 .replaceFirst("[^(]+\\(", StringUtils.EMPTY)
113 .trim()
114 .replaceAll("\\)$", StringUtils.EMPTY);
115 resultTmp = resultTmp.replaceAll("\\([^)]+\\)", StringUtils.EMPTY);
116
117 for (String columnNameAndType: resultTmp.split(",")) {
118 if (columnNameAndType.trim().startsWith("primary key")) {
119 continue;
120 }
121
122 String columnName = columnNameAndType.trim().split("\\s")[0];
123
124 columnName = StringUtils.strip(columnName, "`");
125 if (
126 !"CONSTRAINT".equals(columnName)
127 && !"UNIQUE".equals(columnName)
128 ) {
129
130 resultSqlite.append((char) 4).append(columnName).append((char) 5).append("0").append((char) 4).append((char) 6);
131 }
132 }
133 return resultSqlite.toString();
134 }
135 };
136 this.sqlserver = new Engine(new EngineYaml("sqlserver.yml", injectionModel));
137 this.sybase = new Engine(new EngineYaml("sybase.yml", injectionModel));
138 this.vertica = new Engine(new EngineYaml("vertica.yml", injectionModel));
139 this.virtuoso = new Engine(new EngineYaml("virtuoso.yml", injectionModel));
140
141 this.engines = Arrays.asList(
142 this.auto, access, this.altibase, this.clickhouse, ctreeace, this.cubrid, this.db2, this.derby, this.exasol, this.firebird,
143 frontbase, this.h2, this.hana, this.hsqldb, this.informix, ingres, iris, maxdb, this.mckoi, this.mimer, this.monetdb,
144 this.mysql, this.neo4j, netezza, nuodb, this.oracle, this.postgres, this.presto, this.sqlite, this.sqlserver, this.sybase,
145 teradata, this.vertica, this.virtuoso
146 );
147 this.enginesForFingerprint = Arrays.asList(
148 this.mysql, this.postgres, this.sqlite, this.h2, this.hsqldb, this.oracle, this.sqlserver, access, this.altibase, ctreeace,
149 this.cubrid, this.db2, this.derby, this.exasol, this.firebird, frontbase, this.hana, this.informix, ingres, iris, maxdb, this.mckoi,
150 this.mimer, this.monetdb, this.neo4j, netezza, nuodb, this.presto, this.sybase, teradata, this.vertica, this.virtuoso, this.clickhouse
151 );
152
153 this.engine = this.mysql;
154 this.engineByUser = this.auto;
155 }
156
157 public boolean isSqlite() {
158 return this.getEngine() == this.getSqlite();
159 }
160
161 public Engine fingerprintEngine() {
162 Engine engineFound = null;
163 if (this.injectionModel.getMediatorEngine().getEngineByUser() != this.injectionModel.getMediatorEngine().getAuto()) {
164 engineFound = this.injectionModel.getMediatorEngine().getEngineByUser();
165 LOGGER.log(
166 LogLevelUtil.CONSOLE_INFORM,
167 MediatorEngine.LOG_ENGINE,
168 () -> I18nUtil.valueByKey("LOG_DATABASE_TYPE_FORCED_BY_USER"),
169 () -> this.injectionModel.getMediatorEngine().getEngineByUser()
170 );
171 } else {
172 LOGGER.log(LogLevelUtil.CONSOLE_DEFAULT, "[Step 1] Fingerprinting database...");
173 var insertionCharacter = URLEncoder.encode("'\"#-)'\"*", StandardCharsets.UTF_8);
174 String pageSource = this.injectionModel.injectWithoutIndex(insertionCharacter, "test#engine");
175
176 var mediatorEngine = this.injectionModel.getMediatorEngine();
177 Engine[] enginesWithoutAuto = mediatorEngine.getEngines()
178 .stream()
179 .filter(v -> v != mediatorEngine.getAuto())
180 .toArray(Engine[]::new);
181
182
183 for (Engine engineTest : enginesWithoutAuto) {
184 if (pageSource.matches(engineTest.instance().fingerprintErrorsAsRegex())) {
185 engineFound = engineTest;
186 LOGGER.log(
187 LogLevelUtil.CONSOLE_SUCCESS,
188 "Found [{}] using raw fingerprinting",
189 () -> engineTest
190 );
191 break;
192 }
193 }
194 if (engineFound == null) {
195 engineFound = this.injectionModel.getMediatorEngine().getMysql();
196 LOGGER.log(
197 LogLevelUtil.CONSOLE_INFORM,
198 MediatorEngine.LOG_ENGINE,
199 () -> I18nUtil.valueByKey("LOG_DATABASE_TYPE_NOT_FOUND"),
200 () -> this.injectionModel.getMediatorEngine().getMysql()
201 );
202 }
203 }
204
205 var urlGitHub = this.injectionModel.getMediatorUtils().propertiesUtil().getProperty("github.url");
206 this.injectionModel.appendAnalysisReport(
207 String.join(
208 StringUtils.EMPTY,
209 "# Date: ", LocalDate.now().format(DateTimeFormatter.ISO_LOCAL_DATE),
210 "<br> # Tested on: ", SystemUtils.OS_NAME, " (", SystemUtils.OS_VERSION, ")",
211 "<br> # Tool: ", StringUtil.APP_NAME, " v", this.injectionModel.getPropertiesUtil().getVersionJsql(),
212 " (<a href=", urlGitHub, ">", urlGitHub, "</a>)",
213 "<br> # Database: ", engineFound.toString(),
214 "<br> <br> ## Vulnerability summary</span>"
215 ),
216 true
217 );
218
219 this.injectionModel.sendToViews(new Seal.ActivateEngine(engineFound));
220 return engineFound;
221 }
222
223
224
225
226 public Engine getEngine() {
227 return this.engine;
228 }
229
230 public void setEngine(Engine engine) {
231 this.engine = engine;
232 }
233
234 public Engine getEngineByUser() {
235 return this.engineByUser;
236 }
237
238 public void setEngineByUser(Engine engineByUser) {
239 this.engineByUser = engineByUser;
240 }
241
242 public List<Engine> getEngines() {
243 return this.engines;
244 }
245
246 public List<Engine> getEnginesForFingerprint() {
247 return this.enginesForFingerprint;
248 }
249
250
251
252
253 public Engine getAuto() {
254 return this.auto;
255 }
256
257 public Engine getAccess() {
258 return this.access;
259 }
260
261 public Engine getAltibase() {
262 return this.altibase;
263 }
264
265 public Engine getClickhouse() {
266 return this.clickhouse;
267 }
268
269 public Engine getCubrid() {
270 return this.cubrid;
271 }
272
273 public Engine getDb2() {
274 return this.db2;
275 }
276
277 public Engine getDerby() {
278 return this.derby;
279 }
280
281 public Engine getExasol() {
282 return this.exasol;
283 }
284
285 public Engine getFirebird() {
286 return this.firebird;
287 }
288
289 public Engine getH2() {
290 return this.h2;
291 }
292
293 public Engine getHana() {
294 return this.hana;
295 }
296
297 public Engine getHsqldb() {
298 return this.hsqldb;
299 }
300
301 public Engine getInformix() {
302 return this.informix;
303 }
304
305 public Engine getMckoi() {
306 return this.mckoi;
307 }
308
309 public Engine getMimer() {
310 return this.mimer;
311 }
312
313 public Engine getMonetdb() {
314 return this.monetdb;
315 }
316
317 public Engine getMysql() {
318 return this.mysql;
319 }
320
321 public Engine getNeo4j() {
322 return this.neo4j;
323 }
324
325 public Engine getOracle() {
326 return this.oracle;
327 }
328
329 public Engine getPostgres() {
330 return this.postgres;
331 }
332
333 public Engine getPresto() {
334 return this.presto;
335 }
336
337 public Engine getSqlite() {
338 return this.sqlite;
339 }
340
341 public Engine getSqlserver() {
342 return this.sqlserver;
343 }
344
345 public Engine getSybase() {
346 return this.sybase;
347 }
348
349 public Engine getVertica() {
350 return this.vertica;
351 }
352
353 public Engine getVirtuoso() {
354 return this.virtuoso;
355 }
356 }