1
2
3
4
5
6
7
8
9
10
11 package com.jsql.view.swing.manager;
12
13 import com.jsql.model.accessible.ExploitMode;
14 import com.jsql.model.exception.JSqlException;
15 import com.jsql.model.injection.vendor.model.Vendor;
16 import com.jsql.util.I18nUtil;
17 import com.jsql.util.LogLevelUtil;
18 import com.jsql.view.swing.manager.util.*;
19 import com.jsql.view.swing.text.JPasswordFieldPlaceholder;
20 import com.jsql.view.swing.text.JPopupTextField;
21 import com.jsql.view.swing.text.JTextFieldPlaceholder;
22 import com.jsql.view.swing.text.JToolTipI18n;
23 import com.jsql.view.swing.util.I18nViewUtil;
24 import com.jsql.view.swing.util.MediatorHelper;
25 import org.apache.commons.lang3.StringUtils;
26 import org.apache.logging.log4j.LogManager;
27 import org.apache.logging.log4j.Logger;
28
29 import javax.swing.*;
30 import java.awt.*;
31 import java.awt.event.ActionEvent;
32 import java.awt.event.ActionListener;
33 import java.awt.event.ItemEvent;
34 import java.awt.event.ItemListener;
35 import java.io.File;
36 import java.net.URI;
37 import java.net.URISyntaxException;
38 import java.util.Arrays;
39 import java.util.List;
40 import java.util.Objects;
41 import java.util.concurrent.atomic.AtomicReference;
42
43
44
45
46 public class ManagerExploit extends AbstractManagerList {
47
48 private static final Logger LOGGER = LogManager.getRootLogger();
49 public static final String SHELL_URL_TOOLTIP = "SHELL_URL_TOOLTIP";
50
51 private final AtomicReference<JTextField> username = new AtomicReference<>();
52 private final AtomicReference<JTextField> password = new AtomicReference<>();
53 private final AtomicReference<JTextField> netshare = new AtomicReference<>();
54 protected final JTextField textfieldUrlShell;
55
56 public static final String EXPLOIT_UDF = "EXPLOIT_UDF";
57 public static final String EXPLOIT_WEB = "EXPLOIT_WEB";
58 public static final String EXPLOIT_SQL = "EXPLOIT_SQL";
59 public static final String EXPLOIT_UPLOAD = "EXPLOIT_UPLOAD";
60
61 private final JComboBox<Object> comboBoxExploitTypes = new JComboBox<>(new Object[]{
62 new ModelItemType(ManagerExploit.EXPLOIT_UDF, "EXPLOIT_UDF_TOOLTIP"),
63 ComboBoxMethodRenderer.SEPARATOR,
64 new ModelItemType(ManagerExploit.EXPLOIT_WEB, "EXPLOIT_WEB_TOOLTIP"),
65 new ModelItemType(ManagerExploit.EXPLOIT_SQL, "EXPLOIT_SQL_TOOLTIP"),
66 new ModelItemType(ManagerExploit.EXPLOIT_UPLOAD, "EXPLOIT_UPLOAD_TOOLTIP"),
67 });
68
69 private final JComboBox<Object> comboBoxExploitModes = new JComboBox<>(new Object[]{
70 ExploitMode.AUTO,
71 ComboBoxMethodRenderer.SEPARATOR,
72 ExploitMode.QUERY_BODY,
73 ExploitMode.TEMP_TABLE,
74 ComboBoxMethodRenderer.SEPARATOR,
75 ExploitMode.NETSHARE
76 });
77
78 public ManagerExploit() {
79 super("swing/list/payload.txt");
80
81 var tooltipShellUrl = new AtomicReference<>(new JToolTipI18n(I18nUtil.valueByKey(ManagerExploit.SHELL_URL_TOOLTIP)));
82 var placeholderResult = new JTextFieldPlaceholder(I18nUtil.valueByKey("SHELL_URL_LABEL")) {
83 @Override
84 public JToolTip createToolTip() {
85 return tooltipShellUrl.get();
86 }
87 };
88 this.textfieldUrlShell = new JPopupTextField(placeholderResult).getProxy();
89 I18nViewUtil.addComponentForKey("SHELL_URL_LABEL", this.textfieldUrlShell);
90 I18nViewUtil.addComponentForKey(ManagerExploit.SHELL_URL_TOOLTIP, tooltipShellUrl.get());
91 this.textfieldUrlShell.setToolTipText(I18nUtil.valueByKey(ManagerExploit.SHELL_URL_TOOLTIP));
92
93 this.buildRunButton("SHELL_RUN_BUTTON_LABEL", "SHELL_RUN_BUTTON_TOOLTIP");
94 this.run.setEnabled(false);
95 this.buildPrivilege();
96
97 var southPanel = new JPanel();
98 southPanel.setLayout(new BoxLayout(southPanel, BoxLayout.Y_AXIS));
99 southPanel.add(this.textfieldUrlShell);
100 southPanel.add(this.lastLine);
101 this.add(southPanel, BorderLayout.SOUTH);
102
103 var userPassPanel = new JPanel();
104 var groupLayout = new GroupLayout(userPassPanel);
105 userPassPanel.setLayout(groupLayout);
106
107 this.run.addActionListener(new ActionExploit(this.comboBoxExploitTypes));
108
109 Arrays.asList(
110 new ModelExploit(this.netshare, "EXPLOIT_NETSHARE_LABEL", "EXPLOIT_NETSHARE_TOOLTIP"),
111 new ModelExploit(this.username, "SQL_SHELL_USERNAME_LABEL", "SQL_SHELL_USERNAME_TOOLTIP"),
112 new ModelExploit(this.password, "SQL_SHELL_PASSWORD_LABEL", "SQL_SHELL_PASSWORD_TOOLTIP", true)
113 ).forEach(model -> {
114 var tooltip = new AtomicReference<>(new JToolTipI18n(I18nUtil.valueByKey(model.tooltipI18n)));
115 if (model.isPassword) {
116 model.textfield.set(new JPopupTextField(new JPasswordFieldPlaceholder(I18nUtil.valueByKey(model.labelI18n)) {
117 @Override
118 public JToolTip createToolTip() {
119 return tooltip.get();
120 }
121 }).getProxy());
122 } else {
123 model.textfield.set(new JPopupTextField(new JTextFieldPlaceholder(I18nUtil.valueByKey(model.labelI18n)) {
124 @Override
125 public JToolTip createToolTip() {
126 return tooltip.get();
127 }
128 }).getProxy());
129 }
130 I18nViewUtil.addComponentForKey(model.labelI18n, model.textfield.get());
131 I18nViewUtil.addComponentForKey(model.tooltipI18n, tooltip.get());
132 model.textfield.get().setToolTipText(I18nUtil.valueByKey(model.tooltipI18n));
133 });
134
135 Arrays.asList(this.username.get(), this.password.get(), this.scrollListPaths, this.textfieldUrlShell, this.netshare.get())
136 .forEach(component -> component.setVisible(false));
137
138 this.comboBoxExploitTypes.setRenderer(new ComboBoxTypeRenderer());
139 this.comboBoxExploitTypes.addActionListener(new SeparatorListener(this.comboBoxExploitTypes));
140 this.comboBoxExploitTypes.addItemListener(this.getTypesItemListener());
141 this.comboBoxExploitModes.addItemListener(this.getModesItemListener());
142
143 this.comboBoxExploitModes.setRenderer(new ComboBoxMethodRenderer());
144 this.comboBoxExploitModes.addActionListener(new SeparatorListener(this.comboBoxExploitModes));
145 var labelUsing = new JLabel("via");
146 labelUsing.setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 0));
147 groupLayout.setHorizontalGroup(
148 groupLayout
149 .createParallelGroup()
150 .addGroup(
151 groupLayout
152 .createSequentialGroup()
153 .addComponent(this.comboBoxExploitTypes)
154 .addComponent(labelUsing, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE)
155 .addComponent(this.comboBoxExploitModes, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE)
156 )
157 .addGroup(
158 groupLayout.createParallelGroup()
159 .addComponent(this.netshare.get())
160 .addComponent(this.username.get())
161 .addComponent(this.password.get())
162 )
163 );
164
165 groupLayout.setVerticalGroup(
166 groupLayout
167 .createSequentialGroup()
168 .addGroup(
169 groupLayout
170 .createParallelGroup(GroupLayout.Alignment.BASELINE)
171 .addComponent(this.comboBoxExploitTypes)
172 .addComponent(labelUsing)
173 .addComponent(this.comboBoxExploitModes)
174 )
175 .addGroup(
176 groupLayout
177 .createParallelGroup()
178 .addComponent(this.netshare.get())
179 )
180 .addGroup(
181 groupLayout
182 .createParallelGroup()
183 .addComponent(this.username.get())
184 )
185 .addGroup(
186 groupLayout
187 .createParallelGroup()
188 .addComponent(this.password.get())
189 )
190 );
191
192 this.add(userPassPanel, BorderLayout.NORTH);
193 }
194
195 private ItemListener getModesItemListener() {
196 return itemEvent -> {
197 if (itemEvent.getStateChange() == ItemEvent.SELECTED && itemEvent.getItem() instanceof ExploitMode) {
198 ExploitMode selectedItem = (ExploitMode) itemEvent.getItem();
199 this.netshare.get().setVisible(false);
200 if (selectedItem.equals(ExploitMode.NETSHARE)) {
201 this.netshare.get().setVisible(true);
202 }
203 this.updateUI();
204 }
205 };
206 }
207
208 private ItemListener getTypesItemListener() {
209 return itemEvent -> {
210 if (itemEvent.getStateChange() != ItemEvent.SELECTED || itemEvent.getItem() == ComboBoxMethodRenderer.SEPARATOR) {
211 return;
212 }
213 Arrays.asList(
214 this.username.get(), this.password.get(), this.scrollListPaths, this.textfieldUrlShell
215 ).forEach(component -> component.setVisible(false));
216 ModelItemType selectedItem = (ModelItemType) itemEvent.getItem();
217 if (!ManagerExploit.EXPLOIT_UDF.equals(selectedItem.getKeyLabel())) {
218 this.scrollListPaths.setVisible(true);
219 this.textfieldUrlShell.setVisible(true);
220 if (ManagerExploit.EXPLOIT_SQL.equals(selectedItem.getKeyLabel())) {
221 this.username.get().setVisible(true);
222 this.password.get().setVisible(true);
223 }
224 }
225 this.updateUI();
226 };
227 }
228
229 protected class ActionExploit implements ActionListener {
230 private final JComboBox<Object> comboBoxExploitTypes;
231
232 public ActionExploit(JComboBox<Object> comboBoxExploitTypes) {
233 this.comboBoxExploitTypes = comboBoxExploitTypes;
234 }
235
236 @Override
237 public void actionPerformed(ActionEvent evt) {
238 var modelSelectItem = (ModelItemType) this.comboBoxExploitTypes.getSelectedItem();
239 var labelSelectItem = Objects.requireNonNull(modelSelectItem).getKeyLabel();
240 if (!ManagerExploit.isValid(labelSelectItem)) {
241 LOGGER.log(LogLevelUtil.CONSOLE_ERROR, "Currently unsupported for [{}], contribute and share exploit method on GitHub to improve the app", MediatorHelper.model().getMediatorVendor().getVendor());
242 return;
243 }
244 if (ManagerExploit.EXPLOIT_UDF.equals(labelSelectItem)) {
245 new SwingWorker<>() {
246 @Override
247 protected Object doInBackground() { Thread.currentThread().setName("SwingWorkerExploit");
248 ActionExploit.this.start(null, null, null);
249 return null;
250 }
251 }.execute();
252 return;
253 }
254 if (
255 ManagerExploit.EXPLOIT_SQL.equals(labelSelectItem)
256 && (ManagerExploit.this.password.get().getText().isEmpty() || ManagerExploit.this.username.get().getText().isEmpty())
257 ) {
258 LOGGER.log(LogLevelUtil.CONSOLE_ERROR, "Missing credentials (tips: search and read file containing hardcoded credentials)");
259 return;
260 }
261 if (ManagerExploit.this.listPaths.getSelectedValuesList().isEmpty()) {
262 LOGGER.log(LogLevelUtil.CONSOLE_ERROR, "Select at least one directory in the list");
263 return;
264 }
265
266 String urlShell = this.validateAndNormalizeUrlShell();
267 if (urlShell == null) {
268 return;
269 }
270 AtomicReference<File> fileToUpload = new AtomicReference<>();
271 if (this.validateFileSelection(labelSelectItem, fileToUpload)) {
272 return;
273 }
274
275 new SwingWorker<>() {
276 @Override
277 protected Object doInBackground() { Thread.currentThread().setName("SwingWorkerExploitNonUdf");
278 ManagerExploit.this.horizontalGlue.setVisible(false);
279 ManagerExploit.this.progressBar.setVisible(true);
280 ManagerExploit.this.listPaths.getSelectedValuesList().forEach(pathExploit -> {
281 LOGGER.log(LogLevelUtil.CONSOLE_DEFAULT, String.format("Checking path [%s]...", pathExploit));
282 ActionExploit.this.start(pathExploit.toString(), urlShell, fileToUpload.get());
283 });
284 ManagerExploit.this.endProcess();
285 return null;
286 }
287 }.execute();
288 }
289
290 private boolean validateFileSelection(String labelSelectItem, AtomicReference<File> fileToUpload) {
291 if (ManagerExploit.EXPLOIT_UPLOAD.equals(labelSelectItem)) {
292 fileToUpload.set(ManagerExploit.chooseFile());
293 if (fileToUpload.get() == null) {
294 LOGGER.log(LogLevelUtil.CONSOLE_ERROR, "Missing file, please select a file");
295 return true;
296 }
297 }
298 return false;
299 }
300
301 private String validateAndNormalizeUrlShell() {
302 String urlShell = ManagerExploit.this.textfieldUrlShell.getText();
303 if (!urlShell.isEmpty() && !urlShell.matches("(?i)^https?://.*")) {
304 if (!urlShell.matches("(?i)^\\w+://.*")) {
305 LOGGER.log(LogLevelUtil.CONSOLE_INFORM, "Undefined shell URL protocol, forcing to [https://]");
306 urlShell = "https://"+ urlShell;
307 } else {
308 LOGGER.log(LogLevelUtil.CONSOLE_ERROR, "Unknown URL protocol");
309 return null;
310 }
311 }
312 if (StringUtils.isNotEmpty(urlShell)) {
313 try {
314 new URI(urlShell);
315 } catch (URISyntaxException e) {
316 LOGGER.log(LogLevelUtil.CONSOLE_ERROR, String.format("Incorrect URL: %s", e.getMessage()));
317 return null;
318 }
319 }
320 return urlShell;
321 }
322
323 private void start(String pathExploit, String urlShellFinal, File fileToUpload) {
324 try {
325 ManagerExploit.this.createPayload(pathExploit, urlShellFinal, fileToUpload);
326 } catch (JSqlException | IllegalArgumentException e) {
327 LOGGER.log(LogLevelUtil.CONSOLE_ERROR, String.format("Payload creation failure: %s", e.getMessage()));
328 }
329 }
330 }
331
332 private static boolean isValid(String labelSelectItem) {
333 return
334 ManagerExploit.EXPLOIT_UDF.equals(labelSelectItem) && Arrays.asList(
335 MediatorHelper.model().getMediatorVendor().getSqlite(),
336 MediatorHelper.model().getMediatorVendor().getMysql(),
337 MediatorHelper.model().getMediatorVendor().getPostgres(),
338 MediatorHelper.model().getMediatorVendor().getH2()
339 ).contains(MediatorHelper.model().getMediatorVendor().getVendor())
340 || Arrays.asList(ManagerExploit.EXPLOIT_WEB, ManagerExploit.EXPLOIT_UPLOAD).contains(labelSelectItem) && Arrays.asList(
341 MediatorHelper.model().getMediatorVendor().getDerby(),
342 MediatorHelper.model().getMediatorVendor().getHsqldb(),
343 MediatorHelper.model().getMediatorVendor().getH2(),
344 MediatorHelper.model().getMediatorVendor().getSqlite(),
345 MediatorHelper.model().getMediatorVendor().getMysql(),
346 MediatorHelper.model().getMediatorVendor().getPostgres()
347 ).contains(MediatorHelper.model().getMediatorVendor().getVendor())
348 || List.of(ManagerExploit.EXPLOIT_SQL).contains(labelSelectItem) && Arrays.asList(
349 MediatorHelper.model().getMediatorVendor().getMysql(),
350 MediatorHelper.model().getMediatorVendor().getPostgres()
351 ).contains(MediatorHelper.model().getMediatorVendor().getVendor());
352 }
353
354 private static File chooseFile() {
355 var filechooser = new JFileChooser(MediatorHelper.model().getMediatorUtils().getPreferencesUtil().getPathFile());
356 filechooser.setDialogTitle(I18nUtil.valueByKey("UPLOAD_DIALOG_TEXT"));
357 int returnVal = filechooser.showOpenDialog(MediatorHelper.frame());
358 if (returnVal == JFileChooser.APPROVE_OPTION) {
359 return filechooser.getSelectedFile();
360 }
361 return null;
362 }
363
364 protected void createPayload(String pathExploit, String urlShell, File fileToUpload) throws JSqlException {
365 var exploitMethod = ExploitMode.forName(
366 Objects.requireNonNull(this.comboBoxExploitModes.getSelectedItem()).toString()
367 ).orElse(ExploitMode.AUTO);
368
369 String pathExploitFixed = pathExploit;
370 if (pathExploitFixed != null && !pathExploitFixed.endsWith("/")) {
371 pathExploitFixed += "/";
372 }
373 String pathNetshare = this.netshare.get().getText();
374 if (exploitMethod == ExploitMode.NETSHARE && !pathNetshare.endsWith("\\")) {
375 pathNetshare += "\\";
376 }
377
378 var modelItemType = (ModelItemType) Objects.requireNonNull(this.comboBoxExploitTypes.getSelectedItem());
379 var keyLabel = modelItemType.getKeyLabel();
380 var vendor = MediatorHelper.model().getMediatorVendor().getVendor();
381
382 if (ManagerExploit.EXPLOIT_UDF.equals(keyLabel)) {
383 ManagerExploit.handleUdfExploit(vendor, pathNetshare, exploitMethod);
384 } else if (ManagerExploit.EXPLOIT_WEB.equals(keyLabel)) {
385 ManagerExploit.handleWebExploit(pathExploitFixed, urlShell, vendor, pathNetshare, exploitMethod);
386 } else if (ManagerExploit.EXPLOIT_SQL.equals(keyLabel)) {
387 this.handleSqlExploit(pathExploitFixed, urlShell, vendor, pathNetshare, exploitMethod);
388 } else if (ManagerExploit.EXPLOIT_UPLOAD.equals(keyLabel)) {
389 ManagerExploit.handleUploadExploit(pathExploitFixed, urlShell, fileToUpload, vendor, pathNetshare, exploitMethod);
390 }
391 }
392
393 private static void handleUdfExploit(Vendor vendor, String pathNetshare, ExploitMode exploitMethod) throws JSqlException {
394 if (vendor == MediatorHelper.model().getMediatorVendor().getMysql()) {
395 MediatorHelper.model().getResourceAccess().getExploitMysql().createUdf(pathNetshare, exploitMethod);
396 } else if (vendor == MediatorHelper.model().getMediatorVendor().getPostgres()) {
397 MediatorHelper.model().getResourceAccess().getExploitPostgres().createUdf(null);
398 } else if (vendor == MediatorHelper.model().getMediatorVendor().getSqlite()) {
399 MediatorHelper.model().getResourceAccess().getExploitSqlite().createUdf();
400 } else if (vendor == MediatorHelper.model().getMediatorVendor().getH2()) {
401 MediatorHelper.model().getResourceAccess().getExploitH2().createUdf();
402 }
403 }
404
405 private static void handleWebExploit(String pathExploit, String urlShell, Vendor vendor, String pathNetshare, ExploitMode exploitMethod) throws JSqlException {
406 if (vendor == MediatorHelper.model().getMediatorVendor().getMysql()) {
407 MediatorHelper.model().getResourceAccess().getExploitMysql().createWeb(pathExploit, urlShell, pathNetshare, exploitMethod);
408 } else if (vendor == MediatorHelper.model().getMediatorVendor().getPostgres()) {
409 MediatorHelper.model().getResourceAccess().getExploitPostgres().createWeb(pathExploit, urlShell);
410 } else if (vendor == MediatorHelper.model().getMediatorVendor().getSqlite()) {
411 MediatorHelper.model().getResourceAccess().getExploitSqlite().createWeb(pathExploit, urlShell);
412 } else if (vendor == MediatorHelper.model().getMediatorVendor().getHsqldb()) {
413 MediatorHelper.model().getResourceAccess().getExploitHsqldb().createWeb(pathExploit, urlShell);
414 } else if (vendor == MediatorHelper.model().getMediatorVendor().getH2()) {
415 MediatorHelper.model().getResourceAccess().getExploitH2().createWeb(pathExploit, urlShell);
416 } else if (vendor == MediatorHelper.model().getMediatorVendor().getDerby()) {
417 MediatorHelper.model().getResourceAccess().getExploitDerby().createWeb(pathExploit, urlShell);
418 }
419 }
420
421 private void handleSqlExploit(String pathExploit, String urlShell, Vendor vendor, String pathNetshare, ExploitMode exploitMethod) throws JSqlException {
422 String login = this.username.get().getText();
423 String pass = this.password.get().getText();
424 if (vendor == MediatorHelper.model().getMediatorVendor().getMysql()) {
425 MediatorHelper.model().getResourceAccess().getExploitMysql().createSql(pathExploit, urlShell, pathNetshare, exploitMethod, login, pass);
426 } else if (vendor == MediatorHelper.model().getMediatorVendor().getPostgres()) {
427 MediatorHelper.model().getResourceAccess().getExploitPostgres().createSql(pathExploit, urlShell, login, pass);
428 }
429 }
430
431 private static void handleUploadExploit(String pathExploit, String urlShell, File fileToUpload, Vendor vendor, String pathNetshare, ExploitMode exploitMethod) throws JSqlException {
432 if (vendor == MediatorHelper.model().getMediatorVendor().getMysql()) {
433 MediatorHelper.model().getResourceAccess().getExploitMysql().createUpload(pathExploit, urlShell, pathNetshare, exploitMethod, fileToUpload);
434 } else if (vendor == MediatorHelper.model().getMediatorVendor().getPostgres()) {
435 MediatorHelper.model().getResourceAccess().getExploitPostgres().createUpload(pathExploit, urlShell, fileToUpload);
436 } else if (vendor == MediatorHelper.model().getMediatorVendor().getSqlite()) {
437 MediatorHelper.model().getResourceAccess().getExploitSqlite().createUpload(pathExploit, urlShell, fileToUpload);
438 } else if (vendor == MediatorHelper.model().getMediatorVendor().getHsqldb()) {
439 MediatorHelper.model().getResourceAccess().getExploitHsqldb().createUpload(pathExploit, urlShell, fileToUpload);
440 } else if (vendor == MediatorHelper.model().getMediatorVendor().getH2()) {
441 MediatorHelper.model().getResourceAccess().getExploitH2().createUpload(pathExploit, urlShell, fileToUpload);
442 } else if (vendor == MediatorHelper.model().getMediatorVendor().getDerby()) {
443 MediatorHelper.model().getResourceAccess().getExploitDerby().createUpload(pathExploit, urlShell, fileToUpload);
444 }
445 }
446 }