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