1
2
3
4
5
6
7
8
9
10
11 package com.jsql.view.swing.manager;
12
13 import com.formdev.flatlaf.util.SystemFileChooser;
14 import com.jsql.model.accessible.ExploitMode;
15 import com.jsql.model.exception.JSqlException;
16 import com.jsql.model.injection.engine.model.Engine;
17 import com.jsql.util.I18nUtil;
18 import com.jsql.util.LogLevelUtil;
19 import com.jsql.view.swing.manager.util.*;
20 import com.jsql.view.swing.text.JPasswordFieldPlaceholder;
21 import com.jsql.view.swing.text.JPopupTextField;
22 import com.jsql.view.swing.text.JTextFieldPlaceholder;
23 import com.jsql.view.swing.text.JToolTipI18n;
24 import com.jsql.view.swing.util.I18nViewUtil;
25 import com.jsql.view.swing.util.MediatorHelper;
26 import org.apache.commons.lang3.StringUtils;
27 import org.apache.logging.log4j.LogManager;
28 import org.apache.logging.log4j.Logger;
29
30 import javax.swing.*;
31 import java.awt.*;
32 import java.awt.event.ActionEvent;
33 import java.awt.event.ActionListener;
34 import java.awt.event.ItemEvent;
35 import java.awt.event.ItemListener;
36 import java.io.File;
37 import java.net.URI;
38 import java.net.URISyntaxException;
39 import java.util.Arrays;
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 selectedItem) {
198 this.netshare.get().setVisible(false);
199 if (selectedItem.equals(ExploitMode.NETSHARE)) {
200 this.netshare.get().setVisible(true);
201 }
202 this.updateUI();
203 }
204 };
205 }
206
207 private ItemListener getTypesItemListener() {
208 return itemEvent -> {
209 if (itemEvent.getStateChange() != ItemEvent.SELECTED || itemEvent.getItem() == ComboBoxMethodRenderer.SEPARATOR) {
210 return;
211 }
212 Arrays.asList(
213 this.username.get(), this.password.get(), this.scrollListPaths, this.textfieldUrlShell
214 ).forEach(component -> component.setVisible(false));
215 ModelItemType selectedItem = (ModelItemType) itemEvent.getItem();
216 if (!ManagerExploit.EXPLOIT_UDF.equals(selectedItem.keyLabel())) {
217 this.scrollListPaths.setVisible(true);
218 this.textfieldUrlShell.setVisible(true);
219 if (ManagerExploit.EXPLOIT_SQL.equals(selectedItem.keyLabel())) {
220 this.username.get().setVisible(true);
221 this.password.get().setVisible(true);
222 }
223 }
224 this.updateUI();
225 };
226 }
227
228 protected class ActionExploit implements ActionListener {
229 private final JComboBox<Object> comboBoxExploitTypes;
230
231 public ActionExploit(JComboBox<Object> comboBoxExploitTypes) {
232 this.comboBoxExploitTypes = comboBoxExploitTypes;
233 }
234
235 @Override
236 public void actionPerformed(ActionEvent evt) {
237 var modelSelectItem = (ModelItemType) this.comboBoxExploitTypes.getSelectedItem();
238 var labelSelectItem = Objects.requireNonNull(modelSelectItem).keyLabel();
239 if (!ManagerExploit.isValid(labelSelectItem)) {
240 LOGGER.log(LogLevelUtil.CONSOLE_ERROR, "Currently unsupported for [{}], contribute and share exploit method on GitHub to improve the app", MediatorHelper.model().getMediatorEngine().getEngine());
241 return;
242 }
243 if (ManagerExploit.EXPLOIT_UDF.equals(labelSelectItem)) {
244 new SwingWorker<>() {
245 @Override
246 protected Object doInBackground() { Thread.currentThread().setName("SwingWorkerExploit");
247 ActionExploit.this.start(null, null, null);
248 return null;
249 }
250 }.execute();
251 return;
252 }
253 if (
254 ManagerExploit.EXPLOIT_SQL.equals(labelSelectItem)
255 && (ManagerExploit.this.password.get().getText().isEmpty() || ManagerExploit.this.username.get().getText().isEmpty())
256 ) {
257 LOGGER.log(LogLevelUtil.CONSOLE_ERROR, "Missing credentials (tips: search and read file containing hardcoded credentials)");
258 return;
259 }
260 if (ManagerExploit.this.listPaths.getSelectedValuesList().isEmpty()) {
261 LOGGER.log(LogLevelUtil.CONSOLE_ERROR, "Select at least one directory in the list");
262 return;
263 }
264
265 String urlShell = this.validateAndNormalizeUrlShell();
266 if (urlShell == null) {
267 return;
268 }
269 AtomicReference<File> fileToUpload = new AtomicReference<>();
270 if (this.validateFileSelection(labelSelectItem, fileToUpload)) {
271 return;
272 }
273
274 new SwingWorker<>() {
275 @Override
276 protected Object doInBackground() { Thread.currentThread().setName("SwingWorkerExploitNonUdf");
277 ManagerExploit.this.horizontalGlue.setVisible(false);
278 ManagerExploit.this.progressBar.setVisible(true);
279 ManagerExploit.this.listPaths.getSelectedValuesList().forEach(pathExploit -> {
280 LOGGER.log(LogLevelUtil.CONSOLE_DEFAULT, String.format("Checking path [%s]...", pathExploit));
281 ActionExploit.this.start(pathExploit.toString(), urlShell, fileToUpload.get());
282 });
283 ManagerExploit.this.endProcess();
284 return null;
285 }
286 }.execute();
287 }
288
289 private boolean validateFileSelection(String labelSelectItem, AtomicReference<File> fileToUpload) {
290 if (ManagerExploit.EXPLOIT_UPLOAD.equals(labelSelectItem)) {
291 fileToUpload.set(ManagerExploit.chooseFile());
292 if (fileToUpload.get() == null) {
293 LOGGER.log(LogLevelUtil.CONSOLE_ERROR, "Missing file, upload cancelled");
294 return true;
295 }
296 }
297 return false;
298 }
299
300 private String validateAndNormalizeUrlShell() {
301 String urlShell = ManagerExploit.this.textfieldUrlShell.getText();
302 if (!urlShell.isEmpty() && !urlShell.matches("(?i)^https?://.*")) {
303 if (!urlShell.matches("(?i)^\\w+://.*")) {
304 LOGGER.log(LogLevelUtil.CONSOLE_INFORM, "Undefined shell URL protocol, forcing to [https://]");
305 urlShell = "https://"+ urlShell;
306 } else {
307 LOGGER.log(LogLevelUtil.CONSOLE_ERROR, "Unknown URL protocol");
308 return null;
309 }
310 }
311 if (StringUtils.isNotEmpty(urlShell)) {
312 try {
313 new URI(urlShell);
314 } catch (URISyntaxException e) {
315 LOGGER.log(LogLevelUtil.CONSOLE_ERROR, String.format("Incorrect URL: %s", e.getMessage()));
316 return null;
317 }
318 }
319 return urlShell;
320 }
321
322 private void start(String pathExploit, String urlShellFinal, File fileToUpload) {
323 try {
324 ManagerExploit.this.createPayload(pathExploit, urlShellFinal, fileToUpload);
325 } catch (JSqlException | IllegalArgumentException e) {
326 LOGGER.log(LogLevelUtil.CONSOLE_ERROR, String.format("Payload creation failure: %s", e.getMessage()));
327 }
328 }
329 }
330
331 private static boolean isValid(String labelSelectItem) {
332 return
333 ManagerExploit.EXPLOIT_UDF.equals(labelSelectItem) && Arrays.asList(
334 MediatorHelper.model().getMediatorEngine().getSqlite(),
335 MediatorHelper.model().getMediatorEngine().getMysql(),
336 MediatorHelper.model().getMediatorEngine().getPostgres(),
337 MediatorHelper.model().getMediatorEngine().getH2()
338 ).contains(MediatorHelper.model().getMediatorEngine().getEngine())
339 || Arrays.asList(ManagerExploit.EXPLOIT_WEB, ManagerExploit.EXPLOIT_UPLOAD).contains(labelSelectItem) && Arrays.asList(
340 MediatorHelper.model().getMediatorEngine().getDerby(),
341 MediatorHelper.model().getMediatorEngine().getHsqldb(),
342 MediatorHelper.model().getMediatorEngine().getH2(),
343 MediatorHelper.model().getMediatorEngine().getSqlite(),
344 MediatorHelper.model().getMediatorEngine().getMysql(),
345 MediatorHelper.model().getMediatorEngine().getPostgres()
346 ).contains(MediatorHelper.model().getMediatorEngine().getEngine())
347 || Objects.equals(ManagerExploit.EXPLOIT_SQL, labelSelectItem) && Arrays.asList(
348 MediatorHelper.model().getMediatorEngine().getMysql(),
349 MediatorHelper.model().getMediatorEngine().getPostgres()
350 ).contains(MediatorHelper.model().getMediatorEngine().getEngine());
351 }
352
353 private static File chooseFile() {
354 var filechooser = new SystemFileChooser(MediatorHelper.model().getMediatorUtils().preferencesUtil().getPathFile());
355 filechooser.setDialogTitle(I18nUtil.valueByKey("UPLOAD_DIALOG_TEXT"));
356 int returnVal = filechooser.showOpenDialog(MediatorHelper.frame());
357 if (returnVal == JFileChooser.APPROVE_OPTION) {
358 return filechooser.getSelectedFile();
359 }
360 return null;
361 }
362
363 protected void createPayload(String pathExploit, String urlShell, File fileToUpload) throws JSqlException {
364 var exploitMethod = ExploitMode.forName(
365 Objects.requireNonNull(this.comboBoxExploitModes.getSelectedItem()).toString()
366 ).orElse(ExploitMode.AUTO);
367
368 String pathExploitFixed = pathExploit;
369 if (pathExploitFixed != null && !pathExploitFixed.endsWith("/")) {
370 pathExploitFixed += "/";
371 }
372 String pathNetshare = this.netshare.get().getText();
373 if (exploitMethod == ExploitMode.NETSHARE && !pathNetshare.endsWith("\\")) {
374 pathNetshare += "\\";
375 }
376
377 var modelItemType = (ModelItemType) Objects.requireNonNull(this.comboBoxExploitTypes.getSelectedItem());
378 var keyLabel = modelItemType.keyLabel();
379 var engine = MediatorHelper.model().getMediatorEngine().getEngine();
380
381 if (ManagerExploit.EXPLOIT_UDF.equals(keyLabel)) {
382 ManagerExploit.handleUdfExploit(engine, pathNetshare, exploitMethod);
383 } else if (ManagerExploit.EXPLOIT_WEB.equals(keyLabel)) {
384 ManagerExploit.handleWebExploit(pathExploitFixed, urlShell, engine, pathNetshare, exploitMethod);
385 } else if (ManagerExploit.EXPLOIT_SQL.equals(keyLabel)) {
386 this.handleSqlExploit(pathExploitFixed, urlShell, engine, pathNetshare, exploitMethod);
387 } else if (ManagerExploit.EXPLOIT_UPLOAD.equals(keyLabel)) {
388 ManagerExploit.handleUploadExploit(pathExploitFixed, urlShell, fileToUpload, engine, pathNetshare, exploitMethod);
389 }
390 }
391
392 private static void handleUdfExploit(Engine engine, String pathNetshare, ExploitMode exploitMethod) throws JSqlException {
393 if (engine == MediatorHelper.model().getMediatorEngine().getMysql()) {
394 MediatorHelper.model().getResourceAccess().getExploitMysql().createUdf(pathNetshare, exploitMethod);
395 } else if (engine == MediatorHelper.model().getMediatorEngine().getPostgres()) {
396 MediatorHelper.model().getResourceAccess().getExploitPostgres().createUdf(null);
397 } else if (engine == MediatorHelper.model().getMediatorEngine().getSqlite()) {
398 MediatorHelper.model().getResourceAccess().getExploitSqlite().createUdf();
399 } else if (engine == MediatorHelper.model().getMediatorEngine().getH2()) {
400 MediatorHelper.model().getResourceAccess().getExploitH2().createUdf();
401 }
402 }
403
404 private static void handleWebExploit(String pathExploit, String urlShell, Engine engine, String pathNetshare, ExploitMode exploitMethod) throws JSqlException {
405 if (engine == MediatorHelper.model().getMediatorEngine().getMysql()) {
406 MediatorHelper.model().getResourceAccess().getExploitMysql().createWeb(pathExploit, urlShell, pathNetshare, exploitMethod);
407 } else if (engine == MediatorHelper.model().getMediatorEngine().getPostgres()) {
408 MediatorHelper.model().getResourceAccess().getExploitPostgres().createWeb(pathExploit, urlShell);
409 } else if (engine == MediatorHelper.model().getMediatorEngine().getSqlite()) {
410 MediatorHelper.model().getResourceAccess().getExploitSqlite().createWeb(pathExploit, urlShell);
411 } else if (engine == MediatorHelper.model().getMediatorEngine().getHsqldb()) {
412 MediatorHelper.model().getResourceAccess().getExploitHsqldb().createWeb(pathExploit, urlShell);
413 } else if (engine == MediatorHelper.model().getMediatorEngine().getH2()) {
414 MediatorHelper.model().getResourceAccess().getExploitH2().createWeb(pathExploit, urlShell);
415 } else if (engine == MediatorHelper.model().getMediatorEngine().getDerby()) {
416 MediatorHelper.model().getResourceAccess().getExploitDerby().createWeb(pathExploit, urlShell);
417 }
418 }
419
420 private void handleSqlExploit(String pathExploit, String urlShell, Engine engine, String pathNetshare, ExploitMode exploitMethod) throws JSqlException {
421 String login = this.username.get().getText();
422 String pass = this.password.get().getText();
423 if (engine == MediatorHelper.model().getMediatorEngine().getMysql()) {
424 MediatorHelper.model().getResourceAccess().getExploitMysql().createSql(pathExploit, urlShell, pathNetshare, exploitMethod, login, pass);
425 } else if (engine == MediatorHelper.model().getMediatorEngine().getPostgres()) {
426 MediatorHelper.model().getResourceAccess().getExploitPostgres().createSql(pathExploit, urlShell, login, pass);
427 }
428 }
429
430 private static void handleUploadExploit(String pathExploit, String urlShell, File fileToUpload, Engine engine, String pathNetshare, ExploitMode exploitMethod) throws JSqlException {
431 if (engine == MediatorHelper.model().getMediatorEngine().getMysql()) {
432 MediatorHelper.model().getResourceAccess().getExploitMysql().createUpload(pathExploit, urlShell, pathNetshare, exploitMethod, fileToUpload);
433 } else if (engine == MediatorHelper.model().getMediatorEngine().getPostgres()) {
434 MediatorHelper.model().getResourceAccess().getExploitPostgres().createUpload(pathExploit, urlShell, fileToUpload);
435 } else if (engine == MediatorHelper.model().getMediatorEngine().getSqlite()) {
436 MediatorHelper.model().getResourceAccess().getExploitSqlite().createUpload(pathExploit, urlShell, fileToUpload);
437 } else if (engine == MediatorHelper.model().getMediatorEngine().getHsqldb()) {
438 MediatorHelper.model().getResourceAccess().getExploitHsqldb().createUpload(pathExploit, urlShell, fileToUpload);
439 } else if (engine == MediatorHelper.model().getMediatorEngine().getH2()) {
440 MediatorHelper.model().getResourceAccess().getExploitH2().createUpload(pathExploit, urlShell, fileToUpload);
441 } else if (engine == MediatorHelper.model().getMediatorEngine().getDerby()) {
442 MediatorHelper.model().getResourceAccess().getExploitDerby().createUpload(pathExploit, urlShell, fileToUpload);
443 }
444 }
445 }