-
Notifications
You must be signed in to change notification settings - Fork 18
Expand file tree
/
Copy pathwafid.py
More file actions
210 lines (186 loc) · 6.53 KB
/
wafid.py
File metadata and controls
210 lines (186 loc) · 6.53 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
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# waf identify prog
# Author Cryin'@cSecGroup.com
'''
__ __ _____ ___________.__ .___
/ \ / \/ _ \ \_ _____/|__| __| _/
\ \/\/ / /_\ \ | __) | |/ __ |
\ / | \| \ | / /_/ |
\__/\ /\____|__ /\___ / |__\____ |
\/ \/ \/ \/
WAFid - Web Application Firewall identify Tool
By Code Security Group
https://github.com/cSecGroup
'''
from copy import deepcopy
from urlparse import urljoin
from lxml.html import etree
import re
import os
import requests
import optparse
import sys
wafdetectlist = [
'360',
'Safedog',
'NetContinuum',
'Anquanbao',
'Baidu Yunjiasu',
'Knownsec KS-WAF',
'BIG-IP',
'Barracuda',
'BinarySEC',
'BlockDos',
'Cisco ACE',
'CloudFlare',
'NetScaler',
'FortiWeb',
'jiasule',
'Newdefend',
'Palo Alto',
'Safe3WAF',
'Profense',
'West263CDN',
'WebKnight',
'Wallarm',
'USP Secure Entry Server',
'Sucuri WAF',
'Radware AppWall',
'PowerCDN',
'Naxsi',
'Mission Control Application Shield',
'IBM WebSphere DataPower',
'Edgecast',
'Applicure dotDefender',
'Comodo WAF',
'ChinaCache-CDN',
'NSFocus'
]
WAF_ATTACK_VECTORS = (
"", # NULL
"search=<script>alert(/csecgroup/)</script>",
"file=../../../../../../etc/passwd",
"id=1 AND 1=1 UNION ALL SELECT 1,2,3,table_name FROM information_schema.tables WHERE 2>1--"
)
WAF_KEYWORD_VECTORS = (
"<a href=\"http://bbs.jiasule.com/thread-124-1-1.html",
"This error was generated by Mod_Security",
"has been blocked in accordance with company policy"
)
WAF_PRODUCT_NAME = (
"Knownsec jiasule Web Application Firewall",
"ModSecurity: Open Source Web Application Firewall",
"Palo Alto Firewall"
)
banner = r'''
__ __ _____ ___________.__ .___
/ \ / \/ _ \ \_ _____/|__| __| _/
\ \/\/ / /_\ \ | __) | |/ __ |
\ / | \| \ | / /_/ |
\__/\ /\____|__ /\___ / |__\____ |
\/ \/ \/ \/
WAFid - Web Application Firewall identify Tool
By Code Security Group
'''
class wafid(object):
def __init__(self,url):
self._finger = ''
self._nowaf = ''
self._url = url
def _run(self):
try:
self.scan_site()
except:
print "[+]【Wafid】please check site url : " +self._url
raise
def report_waf(self):
print "[+]【Wafid】identify website waf type is : "+self._finger +"\r\n"
def scan_site(self):
if "http" not in self._url:
print "[+]【Wafid】please check site url : " +self._url
return False
for vector in range(0,len(WAF_ATTACK_VECTORS)):
turl= ''
turl = deepcopy(self._url)
add_url = WAF_ATTACK_VECTORS[vector]
turl = urljoin(turl, add_url)
resp = requests.get(turl)
if self.check_waf(resp):
self.report_waf()
return True
else:
self._nowaf="This website has no waf or identify false!!!"
print "[+]【Wafid】identify waf finger false : "+self._nowaf+"\r\n"
return False
return True
def regexp_header(self,rule_dom,waf_dom,head_type,resp):
if head_type in resp.headers:
regmatch_dom = rule_dom[0].xpath("regmatch")
regexp_doms = regmatch_dom[0].xpath("regexp") if regmatch_dom != None else []
for regexp_dom in regexp_doms:
exp_pattern = re.compile(regexp_dom.text)
if exp_pattern.search(resp.headers[head_type]):
self._finger=waf_dom.get("name")
# print "identify website waf type is : "+self._finger
return True
else:
continue
#print "regmatch head_type regexp false!"
if not self._finger:
return False
else:
return False
return False
def check_resp(self,resp):
content=''
if len(resp.content) != 0:
content = resp.content.strip()
for waf_keyword in range(0,len(WAF_KEYWORD_VECTORS)):
if WAF_KEYWORD_VECTORS[waf_keyword] in content:
self._finger=WAF_PRODUCT_NAME[waf_keyword]
# print "identify website waf type with respcontent is : "+self._finger
return True
else:
self._nowaf="This website has no waf or identify false!!!"
#print "get waf finger false:"+self._nowaf
#return False
return False
def check_waf(self, resp):
if not resp.content:
return
self._xmlstr_dom = etree.parse('finger.xml')
waf_doms = self._xmlstr_dom.xpath("waf")
for waf_dom in waf_doms:
finger_dom = waf_dom.xpath("finger")
rule_dom = finger_dom[0].xpath("rule")
head_type =rule_dom[0].get("header").lower()
if head_type in resp.headers:
if self.regexp_header(rule_dom,waf_dom,head_type,resp):
return True
else:
self._nowaf="This website has no waf or identify false!!!"
#print "[+]【Wafid】get waf finger false: "+self._nowaf
else:
continue
#print "head type search ..."
if self.check_resp(resp):
return True
return False
if __name__ == '__main__':
print(banner)
parser = optparse.OptionParser('usage: python %prog [options](eg: python %prog http://www.csecgroup.com/)')
parser.add_option('-u', '--url', dest = 'url', type = 'string', help = 'target url')
parser.add_option('-l', '--list', dest = 'list', default=False, action="store_true", help='List all WAFs that we are able to detect')
(options, args) = parser.parse_args()
if options.list== True:
print "[+]【Wafid】WAFid can identify these WAFs:"
for waf in wafdetectlist:
print " "+waf
sys.exit()
if options.url == None or options.url == "":
parser.print_help()
sys.exit()
url =options.url
wafidentify = wafid(url)
wafidentify._run()