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.setEngine(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, "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 MediatorEngine.LOG_ENGINE,
189 () -> "Basic fingerprint matching engine",
190 () -> engineTest
191 );
192 break;
193 }
194 }
195 engineFound = this.initEngine(engineFound);
196 }
197
198 var urlGitHub = this.injectionModel.getMediatorUtils().propertiesUtil().getProperty("github.url");
199 this.injectionModel.appendAnalysisReport(
200 String.join(
201 StringUtils.EMPTY,
202 "# Date: ", LocalDate.now().format(DateTimeFormatter.ISO_LOCAL_DATE),
203 "<br> # Tested on: ", SystemUtils.OS_NAME, " (", SystemUtils.OS_VERSION, ")",
204 "<br> # Tool: ", StringUtil.APP_NAME, " v", this.injectionModel.getPropertiesUtil().getVersionJsql(),
205 " (<a href=", urlGitHub, ">", urlGitHub, "</a>)",
206 "<br> # Database: ", engineFound.toString(),
207 "<br> <br> ## Vulnerability summary</span>"
208 ),
209 true
210 );
211
212 this.injectionModel.sendToViews(new Seal.ActivateEngine(engineFound));
213 return engineFound;
214 }
215
216 public Engine initEngine(Engine engine) {
217 var engineFixed = engine;
218 if (engineFixed == null) {
219 engineFixed = this.injectionModel.getMediatorEngine().getMysql();
220 LOGGER.log(
221 LogLevelUtil.CONSOLE_INFORM,
222 MediatorEngine.LOG_ENGINE,
223 () -> I18nUtil.valueByKey("LOG_DATABASE_TYPE_NOT_FOUND"),
224 () -> this.injectionModel.getMediatorEngine().getMysql()
225 );
226 } else {
227 LOGGER.log(
228 LogLevelUtil.CONSOLE_INFORM,
229 MediatorEngine.LOG_ENGINE,
230 () -> I18nUtil.valueByKey("LOG_USING_DATABASE_TYPE"),
231 () -> engine
232 );
233 this.injectionModel.sendToViews(new Seal.MarkEngineFound(engineFixed));
234 }
235 return engineFixed;
236 }
237
238
239
240
241 public Engine getEngine() {
242 return this.engine;
243 }
244
245 public void setEngine(Engine engine) {
246 this.engine = engine;
247 }
248
249 public Engine getEngineByUser() {
250 return this.engineByUser;
251 }
252
253 public void setEngineByUser(Engine engineByUser) {
254 this.engineByUser = engineByUser;
255 }
256
257 public List<Engine> getEngines() {
258 return this.engines;
259 }
260
261 public List<Engine> getEnginesForFingerprint() {
262 return this.enginesForFingerprint;
263 }
264
265
266
267
268 public Engine getAuto() {
269 return this.auto;
270 }
271
272 public Engine getAccess() {
273 return this.access;
274 }
275
276 public Engine getAltibase() {
277 return this.altibase;
278 }
279
280 public Engine getClickhouse() {
281 return this.clickhouse;
282 }
283
284 public Engine getCubrid() {
285 return this.cubrid;
286 }
287
288 public Engine getDb2() {
289 return this.db2;
290 }
291
292 public Engine getDerby() {
293 return this.derby;
294 }
295
296 public Engine getExasol() {
297 return this.exasol;
298 }
299
300 public Engine getFirebird() {
301 return this.firebird;
302 }
303
304 public Engine getH2() {
305 return this.h2;
306 }
307
308 public Engine getHana() {
309 return this.hana;
310 }
311
312 public Engine getHsqldb() {
313 return this.hsqldb;
314 }
315
316 public Engine getInformix() {
317 return this.informix;
318 }
319
320 public Engine getMckoi() {
321 return this.mckoi;
322 }
323
324 public Engine getMimer() {
325 return this.mimer;
326 }
327
328 public Engine getMonetdb() {
329 return this.monetdb;
330 }
331
332 public Engine getMysql() {
333 return this.mysql;
334 }
335
336 public Engine getNeo4j() {
337 return this.neo4j;
338 }
339
340 public Engine getOracle() {
341 return this.oracle;
342 }
343
344 public Engine getPostgres() {
345 return this.postgres;
346 }
347
348 public Engine getPresto() {
349 return this.presto;
350 }
351
352 public Engine getSqlite() {
353 return this.sqlite;
354 }
355
356 public Engine getSqlserver() {
357 return this.sqlserver;
358 }
359
360 public Engine getSybase() {
361 return this.sybase;
362 }
363
364 public Engine getVertica() {
365 return this.vertica;
366 }
367
368 public Engine getVirtuoso() {
369 return this.virtuoso;
370 }
371 }