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