forked from smxiazi/xia_sql
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathBurpExtender.java
More file actions
1362 lines (1163 loc) · 59.3 KB
/
BurpExtender.java
File metadata and controls
1362 lines (1163 loc) · 59.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
package burp;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableModel;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import java.awt.*;
import java.awt.event.ItemListener;
import javax.swing.JMenuItem;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.table.TableRowSorter;
import java.util.Comparator;
public class BurpExtender extends AbstractTableModel implements IBurpExtender, ITab, IHttpListener,IScannerCheck, IMessageEditorController,IContextMenuFactory
{
private IBurpExtenderCallbacks callbacks;
private IExtensionHelpers helpers;
private JSplitPane splitPane;
private IMessageEditor requestViewer;
private IMessageEditor responseViewer;
private final List<LogEntry> log = new ArrayList<LogEntry>();//record original traffic
private final List<LogEntry> log2 = new ArrayList<LogEntry>();//record attack traffic
private final List<LogEntry> log3 = new ArrayList<LogEntry>();//for display
private final List<Request_md5> log4_md5 = new ArrayList<Request_md5>();//for storing md5 of packets
private IHttpRequestResponse currentlyDisplayedItem;
public PrintWriter stdout;
int switchs = 1; //switch 0=off 1=on
int clicks_Repeater=0;//64=listening 0=closed
int clicks_Proxy=0;//4=listening 0=closed
int conut = 0; //record count
String data_md5_id; //used to determine currently selected packet
public AbstractTableModel model = new MyModel();
int original_data_len;//record original packet length
int is_int = 1; //switch 0=off 1=on;//whether pure numbers perform -1,-0
String temp_data; //used to save temporary content
int JTextArea_int = 0;//custom payload switch 0=off 1=on
String JTextArea_data_1 = "";//text area content
int diy_payload_1 = 1;//custom payload space encoding switch 0=off 1=on
int diy_payload_2 = 0;//custom payload value empty switch 0=off 1=on
int select_row = 0;//selected table row number
Table logTable; //first table frame
int is_cookie = -1;//whether cookie should be injected, -1=closed 2=enabled.
String white_URL = "";
int white_switchs = 0;//whitelist switch
//
// implement IBurpExtender
//
@Override
public void registerExtenderCallbacks(final IBurpExtenderCallbacks callbacks)
{
//output
this.stdout = new PrintWriter(callbacks.getStdout(), true);
this.stdout.println("hello xia sql!");
this.stdout.println("Hello, welcome to use xia SQL!");
this.stdout.println("version:2.9");
// keep a reference to our callbacks object
this.callbacks = callbacks;
// obtain an extension helpers object
helpers = callbacks.getHelpers();
// set our extension name
callbacks.setExtensionName("xia SQL V2.9");
// create our UI
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
// main split pane
splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
JSplitPane splitPanes = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
JSplitPane splitPanes_2 = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
// table of log entries
logTable = new Table(BurpExtender.this);
logTable.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN); // Last column fills space
// Enable sorting with custom comparators
TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(BurpExtender.this);
logTable.setRowSorter(sorter);
// Custom comparator for # column (treat as number)
sorter.setComparator(0, new Comparator<Object>() {
@Override
public int compare(Object o1, Object o2) {
try {
int i1 = (o1 instanceof Integer) ? (Integer)o1 : Integer.parseInt(o1.toString());
int i2 = (o2 instanceof Integer) ? (Integer)o2 : Integer.parseInt(o2.toString());
return Integer.compare(i1, i2);
} catch (Exception e) {
return o1.toString().compareTo(o2.toString());
}
}
});
// Custom comparator for Response Length column (extract numbers)
sorter.setComparator(3, new Comparator<Object>() {
@Override
public int compare(Object o1, Object o2) {
try {
String s1 = o1.toString().replaceAll("[^0-9]", "");
String s2 = o2.toString().replaceAll("[^0-9]", "");
if (s1.isEmpty()) s1 = "0";
if (s2.isEmpty()) s2 = "0";
return Integer.compare(Integer.parseInt(s1), Integer.parseInt(s2));
} catch (Exception e) {
return o1.toString().compareTo(o2.toString());
}
}
});
// Set preferred column widths for main table (compact & responsive)
logTable.getColumnModel().getColumn(0).setPreferredWidth(40); // #
logTable.getColumnModel().getColumn(0).setMinWidth(30);
logTable.getColumnModel().getColumn(0).setMaxWidth(60);
logTable.getColumnModel().getColumn(1).setPreferredWidth(70); // Source
logTable.getColumnModel().getColumn(1).setMinWidth(50);
logTable.getColumnModel().getColumn(1).setMaxWidth(100);
logTable.getColumnModel().getColumn(2).setPreferredWidth(300); // URL
logTable.getColumnModel().getColumn(2).setMinWidth(150);
logTable.getColumnModel().getColumn(3).setPreferredWidth(90); // Response Length
logTable.getColumnModel().getColumn(3).setMinWidth(70);
logTable.getColumnModel().getColumn(3).setMaxWidth(120);
logTable.getColumnModel().getColumn(4).setPreferredWidth(50); // Status (auto-fills)
logTable.getColumnModel().getColumn(4).setMinWidth(40);
JScrollPane scrollPane = new JScrollPane(logTable); //add scroll bar to list
// Result table
Table_log2 table=new Table_log2(model);
table.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN); // Last column fills space
// Set preferred column widths for result table (compact & responsive)
table.getColumnModel().getColumn(0).setPreferredWidth(80); // Parameter
table.getColumnModel().getColumn(0).setMinWidth(60);
table.getColumnModel().getColumn(1).setPreferredWidth(120); // Payload
table.getColumnModel().getColumn(1).setMinWidth(80);
table.getColumnModel().getColumn(2).setPreferredWidth(90); // Response Length
table.getColumnModel().getColumn(2).setMinWidth(70);
table.getColumnModel().getColumn(2).setMaxWidth(120);
table.getColumnModel().getColumn(3).setPreferredWidth(150); // Change
table.getColumnModel().getColumn(3).setMinWidth(100);
table.getColumnModel().getColumn(4).setPreferredWidth(60); // Time
table.getColumnModel().getColumn(4).setMinWidth(50);
table.getColumnModel().getColumn(4).setMaxWidth(80);
table.getColumnModel().getColumn(5).setPreferredWidth(70); // Status Code (auto-fills)
table.getColumnModel().getColumn(5).setMinWidth(50);
JScrollPane pane=new JScrollPane(table);//add scroll bar to list
// Split pane for the two tables (horizontal split - side by side)
JSplitPane tablesSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
tablesSplitPane.setLeftComponent(scrollPane);
tablesSplitPane.setRightComponent(pane);
tablesSplitPane.setResizeWeight(0.5); // Equal distribution
tablesSplitPane.setDividerLocation(0.5); // 50% split
//side checkboxes
JPanel jps=new JPanel();
jps.setLayout(new GridLayout(18, 1)); //18 rows 1 column
JLabel jls=new JLabel("Plugin Name: xia SQL author: suanmingxianzi"); //create a label
JLabel jls_1=new JLabel("blog:www.nmd5.com"); //create a label
JLabel jls_2=new JLabel("Version: xia SQL V2.9"); //create a label
JLabel jls_3=new JLabel("Thanks to: Moonlit, amao agou, Shincehor"); //create a label
JCheckBox chkbox1=new JCheckBox("Start Plugin", true); //create checkbox with specified text and state
JCheckBox chkbox2=new JCheckBox("Monitor Repeater"); //create checkbox with specified text
JCheckBox chkbox3=new JCheckBox("Monitor Proxy"); //create checkbox with specified text
JCheckBox chkbox4=new JCheckBox("If value is number then -1, -0",true); //create checkbox with specified text
JLabel jls_4=new JLabel("Remember to click load after modifying payload"); //create a label
JCheckBox chkbox5=new JCheckBox("Custom payload"); //create checkbox with specified text
JCheckBox chkbox6=new JCheckBox("URL encode spaces in custom payload",true); //create checkbox with specified text
JCheckBox chkbox7=new JCheckBox("Empty parameter value in custom payload"); //create checkbox with specified text
JCheckBox chkbox8=new JCheckBox("Test Cookie"); //create checkbox with specified text
JLabel jls_5=new JLabel("If multiple domains need whitelist, separate with ,"); //create a label
JTextField textField = new JTextField("Enter whitelist domain");//whitelist text field
//chkbox4.setEnabled(false);//set to unselectable
JButton btn1=new JButton("Clear List"); //create JButton object
JButton btn2=new JButton("Load/Reload payload"); //create JButton object
JButton btn3=new JButton("Enable Whitelist"); //handle whitelist
//custom payload area
JPanel jps_2=new JPanel();
jps_2.setLayout(new GridLayout(1, 1)); //1 row 1 column
JTextArea jta=new JTextArea("%df' and sleep(3)%23\n'and '1'='1",18,16);
//read ini config file
try {
BufferedReader in = new BufferedReader(new FileReader("xia_SQL_diy_payload.ini"));
String str,str_data="";
while ((str = in.readLine()) != null) {
str_data += str+"\n";
}
jta.setText(str_data);
} catch (IOException e) {
}
//jta.setLineWrap(true); //set text in text area to auto wrap
jta.setForeground(Color.BLACK); //set component background color
jta.setFont(new Font("KaiTi",Font.BOLD,16)); //modify font style
jta.setBackground(Color.LIGHT_GRAY); //set background color
jta.setEditable(false);//non-editable state
JScrollPane jsp=new JScrollPane(jta); //put text area into scroll window
jps_2.add(jsp); //add JScrollPane to JPanel container
//add checkbox listener events
chkbox1.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
if(chkbox1.isSelected()){
stdout.println("Plugin xia SQL started");
switchs = 1;
}else {
stdout.println("Plugin xia SQL closed");
switchs = 0;
}
}
});
chkbox2.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
if (chkbox2.isSelected()){
stdout.println("Start monitoring Repeater");
clicks_Repeater = 64;
}else {
stdout.println("Stop monitoring Repeater");
clicks_Repeater = 0;
}
}
});
chkbox3.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
if(chkbox3.isSelected()) {
stdout.println("Start monitoring Proxy");
clicks_Proxy = 4;
}else {
stdout.println("Stop monitoring Proxy");
clicks_Proxy = 0;
}
}
});
chkbox4.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
if(chkbox4.isSelected()) {
stdout.println("Start if value is number then -1, -0");
is_int = 1;
}else {
stdout.println("Stop if value is number then -1, -0");
is_int = 0;
}
}
});
chkbox5.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
if(chkbox5.isSelected()) {
stdout.println("Start custom payload");
jta.setEditable(true);
jta.setBackground(Color.WHITE); //set background color
JTextArea_int = 1;
if (diy_payload_1 == 1){
String temp_data = jta.getText();
temp_data = temp_data.replaceAll(" ","%20");
JTextArea_data_1 = temp_data;
}else {
JTextArea_data_1 = jta.getText();
}
}else {
stdout.println("Stop custom payload");
jta.setEditable(false);
jta.setBackground(Color.LIGHT_GRAY); //set background color
JTextArea_int = 0;
}
}
});
chkbox6.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
if(chkbox6.isSelected()) {
stdout.println("Start space URL encoding");
diy_payload_1 = 1;
//space URL encoding
String temp_data = jta.getText();
temp_data = temp_data.replaceAll(" ","%20");
JTextArea_data_1 = temp_data;
}else {
stdout.println("Stop space URL encoding");
diy_payload_1 = 0;
JTextArea_data_1 = jta.getText();
}
}
});
chkbox7.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
if(chkbox7.isSelected()) {
stdout.println("Start custom payload empty parameter value");
diy_payload_2 = 1;
}else {
stdout.println("Stop custom payload empty parameter value");
diy_payload_2 = 0;
}
}
});
chkbox8.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
if(chkbox8.isSelected()) {
stdout.println("Start test Cookie");
is_cookie = 2;
}else {
stdout.println("Stop test Cookie");
is_cookie = -1;
}
}
});
btn1.addActionListener(new ActionListener() {//clear list
@Override
public void actionPerformed(ActionEvent e) {
log.clear();//clear log content
log2.clear();//clear log2 content
log3.clear();//clear log3 content
log4_md5.clear();//clear log4 content
conut = 0;
// Clear selection BEFORE table update
logTable.clearSelection();
// Reset sorter to prevent sorting errors on empty table
if (logTable.getRowSorter() != null) {
logTable.getRowSorter().setSortKeys(null);
}
// Properly notify tables of data change
fireTableDataChanged();//refresh main table
model.fireTableDataChanged();//refresh result table
}
});
btn2.addActionListener(new ActionListener() {//load custom payload
@Override
public void actionPerformed(ActionEvent e) {
if (diy_payload_1 == 1){
String temp_data = jta.getText();
temp_data = temp_data.replaceAll(" ","%20");
JTextArea_data_1 = temp_data;
}else {
JTextArea_data_1 = jta.getText();
}
//write to ini config file
try {
BufferedWriter out = new BufferedWriter(new FileWriter("xia_SQL_diy_payload.ini"));
out.write(JTextArea_data_1);
out.close();
} catch (IOException exception) {
}
}
});
btn3.addActionListener(new ActionListener() {//handle whitelist
@Override
public void actionPerformed(ActionEvent e) {
if(btn3.getText().equals("Enable Whitelist")){
btn3.setText("Disable Whitelist");
white_URL = textField.getText();
white_switchs = 1;
textField.setEditable(false);
textField.setForeground(Color.GRAY);//set component background color
}else {
btn3.setText("Enable Whitelist");
white_switchs = 0;
textField.setEditable(true);
textField.setForeground(Color.BLACK);
}
}
});
jps.add(jls);
jps.add(jls_1);
jps.add(jls_2);
jps.add(jls_3);
jps.add(chkbox1);
jps.add(chkbox2);
jps.add(chkbox3);
jps.add(chkbox4);
jps.add(chkbox8);
jps.add(btn1);
jps.add(jls_5);
jps.add(textField);
jps.add(btn3);
jps.add(jls_4);
jps.add(chkbox5);
jps.add(chkbox6);
jps.add(chkbox7);
jps.add(btn2);
// tabs with request/response viewers
JTabbedPane tabs = new JTabbedPane();
requestViewer = callbacks.createMessageEditor(BurpExtender.this, false);
responseViewer = callbacks.createMessageEditor(BurpExtender.this, false);
tabs.addTab("Request", requestViewer.getComponent());
tabs.addTab("Response", responseViewer.getComponent());
//jp.add(tabs);
//right side
splitPanes_2.setLeftComponent(jps);//top
splitPanes_2.setRightComponent(jps_2);//bottom
//left side
splitPanes.setLeftComponent(tablesSplitPane);//top - two tables
splitPanes.setRightComponent(tabs);//bottom - request/response viewers
splitPanes.setResizeWeight(0.5); // Equal distribution
splitPanes.setDividerLocation(0.5); // 50% split
//overall layout
splitPane.setLeftComponent(splitPanes);//add on left
splitPane.setRightComponent(splitPanes_2);//add on right
splitPane.setResizeWeight(0.75); // 75% for tables, 25% for controls
splitPane.setDividerLocation(0.75); // 75% split
// customize our UI components
callbacks.customizeUiComponent(splitPane);
callbacks.customizeUiComponent(logTable);
callbacks.customizeUiComponent(scrollPane);
callbacks.customizeUiComponent(table);
callbacks.customizeUiComponent(pane);
callbacks.customizeUiComponent(tablesSplitPane);
callbacks.customizeUiComponent(jps);
callbacks.customizeUiComponent(tabs);
// add the custom tab to Burp's UI
callbacks.addSuiteTab(BurpExtender.this);
// register ourselves as an HTTP listener
callbacks.registerHttpListener(BurpExtender.this);
callbacks.registerScannerCheck(BurpExtender.this);
callbacks.registerContextMenuFactory(BurpExtender.this);
}
});
}
//
// implement ITab
//
@Override
public String getTabCaption()
{
return "xia SQL";
}
@Override
public Component getUiComponent()
{
return splitPane;
}
//
// implement IHttpListener
//
@Override
public void processHttpMessage(int toolFlag, boolean messageIsRequest, IHttpRequestResponse messageInfo)
{
if(switchs == 1){//plugin switch
if(toolFlag == clicks_Repeater || toolFlag == clicks_Proxy){//listen Repeater
// only process responses
if (!messageIsRequest)
{
// create a new log entry with the message details
synchronized(log)
{
//BurpExtender.this.checkVul(messageInfo,toolFlag);
Thread thread = new Thread(new Runnable() {
public void run() {
try {
BurpExtender.this.checkVul(messageInfo,toolFlag);
} catch (Exception ex) {
ex.printStackTrace();
BurpExtender.this.stdout.println(ex);
}
}
});
thread.start();
}
}
}
}
}
@Override
public List<IScanIssue> doPassiveScan(IHttpRequestResponse baseRequestResponse) {
return null;
}
@Override
public List<JMenuItem> createMenuItems(final IContextMenuInvocation invocation) {
//right-click send button functionality
List<JMenuItem> listMenuItems = new ArrayList<JMenuItem>(1);
if(invocation.getToolFlag() == IBurpExtenderCallbacks.TOOL_REPEATER || invocation.getToolFlag() == IBurpExtenderCallbacks.TOOL_PROXY){
//parent menu
IHttpRequestResponse[] responses = invocation.getSelectedMessages();
JMenuItem jMenu = new JMenuItem("Send to xia SQL");
jMenu.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if(switchs == 1) {
//should not make HTTP requests in Swing event dispatch thread, so need to create a Runnable and complete work in run() method, then call new Thread(runnable).start() to start thread
Thread thread = new Thread(new Runnable() {
public void run() {
try {
BurpExtender.this.checkVul(responses[0], 1024);
} catch (Exception ex) {
ex.printStackTrace();
BurpExtender.this.stdout.println(ex);
}
}
});
thread.start();
}else {
BurpExtender.this.stdout.println("Plugin xia SQL is closed!");
}
}
});
listMenuItems.add(jMenu);
}
//BurpExtender.this.checkVul(responses,4);
return listMenuItems;
}
//Helper: Safe HTTP request with null checking
private IHttpRequestResponse safeMakeHttpRequest(IHttpService service, byte[] request, String paramName) {
try {
IHttpRequestResponse response = callbacks.makeHttpRequest(service, request);
if (response == null || response.getResponse() == null) {
stdout.println("WARNING: Null response for parameter: " + paramName);
return null;
}
return response;
} catch (Exception e) {
stdout.println("ERROR: Request failed for " + paramName + ": " + e.getMessage());
return null;
}
}
private void checkVul(IHttpRequestResponse baseRequestResponse, int toolFlag){
int is_add; //used to determine whether to add scan
String change_sign_1 = ""; //used to display the change part of the status in the first list box
//MD5 encrypt current url and parameters, used to determine if this url has been scanned
List<IParameter>paraLists= helpers.analyzeRequest(baseRequestResponse).getParameters();
temp_data = String.valueOf(helpers.analyzeRequest(baseRequestResponse).getUrl());//url
//stdout.println(temp_data);
String[] temp_data_strarray=temp_data.split("\\?");
String temp_data =(String) temp_data_strarray[0];//get string before question mark
//check whitelist
String[] white_URL_list = white_URL.split(",");
int white_swith = 0;
if(white_switchs == 1){
white_swith = 0;
for(int i=0;i<white_URL_list.length;i++){
if(temp_data.contains(white_URL_list[i])){
this.stdout.println("Whitelist URL! "+temp_data);
white_swith = 1;
}
}
if(white_swith == 0) {
this.stdout.println("Not whitelist URL! "+temp_data);
return;
}
}
//used to determine if page suffix is static file
if(toolFlag == 4 || toolFlag ==64){//if traffic is from Repeater or proxy then check its suffix
String[] static_file = {"jpg","png","gif","css","js","pdf","mp3","mp4","avi"};
String[] static_file_1 =temp_data.split("\\.");
String static_file_2 = static_file_1[static_file_1.length-1];//get the last . content
//this.stdout.println(static_file_2);
for(String i:static_file){
if(static_file_2.equals(i)){
this.stdout.println("Current url is static file: "+temp_data+"\n");
return;
}
}
}
//stdout.println(temp_data);
String request_data = null;
String[] request_datas;
is_add = 0;
for (IParameter para : paraLists){// loop to get parameters, determine type, then construct new parameters and merge into new request packet.
if (para.getType() == 0 || para.getType() == 1 || para.getType() == 6 || para.getType() == is_cookie) { //getType() is used to determine where the parameter is located
if(is_add == 0){
is_add = 1;
}
temp_data += "+"+para.getName();
//determine if it is nested json, considering performance consumption, only use regex processing for nested json and json with lists
if(para.getType() == 6 && request_data == null){
try {
//stdout.println(helpers.bytesToString(baseRequestResponse.getRequest()));//view packet content
request_data = helpers.bytesToString(baseRequestResponse.getRequest()).split("\r\n\r\n")[1];
//stdout.println(request_data);
//nested json
request_datas = request_data.split("\\{");
if(request_datas.length >2){
is_add = 2;
}
//json has list
request_datas = request_data.split("\":\\[");
if(request_datas.length >1){
is_add = 2;
}
} catch (Exception e) {
stdout.println(e);
}
}
}
}
//url+parameter encoding
temp_data += "+"+helpers.analyzeRequest(baseRequestResponse).getMethod();
//this.stdout.println(temp_data);
this.stdout.println("\nMD5(\""+temp_data+"\")");
temp_data = MD5(temp_data);
this.stdout.println(temp_data);
for (Request_md5 i : log4_md5){
if(i.md5_data.equals(temp_data)){//determine if md5 values are the same, and right-click sent requests do not undergo md5 verification
if(toolFlag == 1024){
temp_data = String.valueOf(System.currentTimeMillis());
this.stdout.println(temp_data);
temp_data = MD5(temp_data);
this.stdout.println(temp_data);
}else {
return;
}
}
}
//used to determine whether to process this request
if (is_add != 0){
log4_md5.add(new Request_md5(temp_data));//save corresponding md5
stdout.println(is_add);
stdout.println(request_data);
int row = log.size();
try{
original_data_len = callbacks.saveBuffersToTempFiles(baseRequestResponse).getResponse().length;//update original packet length
stdout.println(original_data_len);
if(original_data_len <= 0){
stdout.println("This packet has no response");
return;
}
} catch (Exception ex) {
stdout.println("This packet has no response");
return;
}
log.add(new LogEntry(conut,toolFlag, callbacks.saveBuffersToTempFiles(baseRequestResponse),helpers.analyzeRequest(baseRequestResponse).getUrl(),"","","",temp_data,0,"run……",999));
conut += 1;
fireTableRowsInserted(row, row);
}
//process parameters
List<IParameter>paraList= helpers.analyzeRequest(baseRequestResponse).getParameters();
byte[] new_Request = baseRequestResponse.getRequest();
int json_count = -1;//record json nesting count
//****************************************
// loop to get parameters
//****************************************
String para_name = "";//used to record parameter name from previous loop
for (IParameter para : paraList){// loop to get parameters
int switch_para = 0;//used to determine whether this parameter should be processed 0=process 1=skip
if(para.getType() == 6){
json_count += 1;
}
//payload
ArrayList<String> payloads = new ArrayList<>();
payloads.add("'");
payloads.add("''");
if (para.getType() == 0 || para.getType() == 1 || para.getType() == 6 || para.getType() == is_cookie){ //getType() is used to determine where the parameter is located
String key = para.getName();//get parameter name
String value = para.getValue();//get parameter value
stdout.println("\n\nOriginal data: "+key+":"+value);//output original key-value data
if(is_int == 1){//switch, used to determine whether to enable -1, -0 operation
if (value.matches("[0-9]+")) {//used to determine if parameter value is pure number
payloads.add("-1");
payloads.add("-0");
}
}
//custom payload
if(JTextArea_int == 1){
String[] JTextArea_data = JTextArea_data_1.split("\n");
for(String a:JTextArea_data){
//stdout.println(a);
//stdout.println("------");
payloads.add(a);
}
}
int change = 0; //used to determine if return packet length is consistent, save first request response length
//****************************************
// loop payloads
//****************************************
for (String payload : payloads) {
int time_1 = 0,time_2 = 0;
if(JTextArea_int == 1){
//custom payload //parameter value is empty
if(diy_payload_2 == 1){
if(payload != "'" && payload !="''" && payload != "-1" && payload != "-0"){
value = "";
}
}
}
//stdout.println(key+":"+value+payload);//output key and value with added payload
IHttpService iHttpService = baseRequestResponse.getHttpService();
//new request packet
IHttpRequestResponse requestResponse = null; //used for variables inside if
if(para.getType() == 6){
List<String> headers = helpers.analyzeRequest(baseRequestResponse).getHeaders();
if(is_add ==1) {
//json format
stdout.println("json");
String newBody = "{"; //json body content
for (IParameter paras : paraList) {//loop all parameters, prepare to customize json format body
if (paras.getType() == 6) {//only json format data
if (key == paras.getName() && value == paras.getValue()) {//determine if current key and value are the ones that need payload added
newBody += "\"" + paras.getName() + "\":" + "\"" + paras.getValue() + payload + "\",";//construct json body
} else {
newBody += "\"" + paras.getName() + "\":" + "\"" + paras.getValue() + "\",";//construct json body
}
}
}
newBody = newBody.substring(0, newBody.length() - 1); //remove last comma
newBody += "}";//json body content
byte[] bodyByte = newBody.getBytes();
byte[] new_Requests = helpers.buildHttpMessage(headers, bodyByte); //key method
time_1 = (int) System.currentTimeMillis();
requestResponse = callbacks.makeHttpRequest(iHttpService, new_Requests);//send request
time_2 = (int) System.currentTimeMillis();
}else if (is_add ==2){
//nested json
//stdout.println("nested json");
request_data = request_data.replaceAll("\r","");//burp2.x json auto format beautification processing
request_data = request_data.replaceAll("\n","");//burp2.x json auto format beautification processing
String[] request_data_temp = request_data.split(",\"");//used to temporarily save split post body content
String request_data_body = "";//concatenate string
String request_data_body_temp = "";//modified body and string that needs temporary editing
for(int i=0;i < request_data_temp.length;i++){
if(i==json_count){//determine current parameter being modified
request_data_body_temp = request_data_temp[i];
stdout.println("Value to be modified: "+request_data_body_temp);
while (true){
//empty list like: "test":[] skip processing
if(request_data_body_temp.contains(":[]")) {
stdout.println(request_data_body_temp+" skip");
request_data_body += "\""+request_data_temp[i]+",";//concatenate skipped string
json_count += 1;
i += 1;
request_data_body_temp = request_data_temp[i];
}else {
break;
}
}
//null, true, false etc skip processing
if(request_data_body_temp.toLowerCase().contains(":null") || request_data_body_temp.toLowerCase().contains(":true") || request_data_body_temp.toLowerCase().contains(":false")) {
stdout.println(request_data_body_temp+" skip");
switch_para = 1;
break;
}
if(request_data_body_temp.contains("\":")){
if(para.getName().equals(para_name)){
//handle json nested list, this case only runs once
stdout.println("json nested list, this parameter already processed, skip");
json_count -= 1;
switch_para = 1;
break;
}
//determine if string contains ":, if yes then it is normal json content
Pattern p = Pattern.compile(".*:\\s?\\[?\\s?(.*?$)");
Matcher m = p.matcher(request_data_body_temp);
if(m.find()){
request_data_body_temp = m.group(1);//get content after :
}
if(request_data_body_temp.contains("\"")){//determine if content is string
request_data_body_temp = request_data_temp[i];
//modify content, add payload
request_data_body_temp = request_data_body_temp.replaceAll("^(.*:.*?\")(.*?)(\"[^\"]*)$","$1$2"+payload+"$3");
stdout.println(request_data_body_temp);
request_data_body+= "\""+request_data_body_temp +",";
}else {
request_data_body_temp = request_data_temp[i];
//modify content, add payload pure number
request_data_body_temp = request_data_body_temp.replaceAll("^(.*:.*?)(\\d*)([^\"\\d]*)$","$1\"$2"+payload+"\"$3");
stdout.println(request_data_body_temp);
request_data_body+= "\""+request_data_body_temp +",";
}
}else {
stdout.println("Already processed, no need to process");
switch_para = 1;
if(para.getName().equals(para_name)){
//handle json nested list, this case only runs once
stdout.println("json nested list, already processed first value");
}
break;
/*
//string does not contain ":, means nested list in json format
if(request_data_body_temp.contains("\"")) {//determine if content is string
//modify content, add payload
request_data_body_temp = request_data_body_temp.replaceAll("^(\")(.*?)(\".*?)$","$1$2"+payload+"$3");
request_data_body+= "\""+request_data_body_temp +",";
}else {
//not string, then is pure number
request_data_body_temp = request_data_body_temp.replaceAll("^(\\d*)(.*?)$","\"$1"+payload+"\"$2");
request_data_body+= "\""+request_data_body_temp +",";
}
*/
}
//stdout.println(request_data_body_temp);
}else {
request_data_body += "\""+request_data_temp[i]+",";
}
}
if(switch_para == 1){
//skip this parameter
break;
}
if(para.getName().equals(para_name)){
//handle json nested list, this case only runs once
stdout.println("json nested list, already processed first value!!!!");
}
request_data_body = request_data_body.substring(0, request_data_body.length() - 1); //remove last comma
request_data_body = request_data_body.substring(1,request_data_body.length()); //remove first "
byte[] bodyByte = request_data_body.getBytes();
byte[] new_Requests = helpers.buildHttpMessage(headers, bodyByte); //key method
time_1 = (int) System.currentTimeMillis();
requestResponse = safeMakeHttpRequest(iHttpService, new_Requests, key);//send request
time_2 = (int) System.currentTimeMillis();
if (requestResponse == null) continue; //Skip null response
}
}else {
stdout.println("normal format");
//not json format
IParameter newPara = helpers.buildParameter(key,value + payload, para.getType()); //construct new parameter
byte[] newRequest = helpers.updateParameter(new_Request, newPara);//update request packet parameters
time_1 = (int) System.currentTimeMillis();
requestResponse = safeMakeHttpRequest(iHttpService, newRequest, key);//send request
time_2 = (int) System.currentTimeMillis();
if (requestResponse == null) continue; //Skip null response
}
//determine if data length will change
String change_sign;//change content in second table
if(payload == "'" || payload == "-1" || change == 0){
change = requestResponse.getResponse().length;//save first request response length
change_sign = "";
}else{
if(payload == "''" || payload == "-0" ){
if(change != requestResponse.getResponse().length){//determine if first length is different from current
if(payload == "''" && requestResponse.getResponse().length == original_data_len || payload == "-0" && requestResponse.getResponse().length == original_data_len){//determine if double quote length is different from first and same as original packet length
//original packet length and double quote length are same and different from single quote length
change_sign = "✔ ==> ?";
change_sign_1 = " ✔";
}else{
//first packet and second packet length different
change_sign = "✔ "+ (change-requestResponse.getResponse().length);
change_sign_1 = " ✔";
}
}else {
//first packet and second packet length same
change_sign = "";
}
}else {
//custom payload
if(time_2-time_1 >= 3000){
//response time greater than 3 seconds
change_sign = "time > 3";
change_sign_1 = " ✔";
}else {
change_sign = "diy payload";
}
}
}