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