Skip to content

Commit

Permalink
Added trigger URL in response (#182)
Browse files Browse the repository at this point in the history
* added url in return value

* keep same format

* added sort_keys
  • Loading branch information
0xInfection authored Jun 4, 2023
1 parent f636c9e commit ae6a67f
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 24 deletions.
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ coverage.xml
# Sphinx documentation
docs/_build/


*.csv
*.json
.idea/*

.vscode/*
4 changes: 2 additions & 2 deletions wafw00f/lib/evillib.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@
import requests
import urllib3
try:
from urlparse import urlparse, urlunparse
from urlparse import urlparse
except ImportError:
from urllib.parse import urlparse, urlunparse
from urllib.parse import urlparse

# For requests < 2.16, this should be used.
# requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
Expand Down
44 changes: 24 additions & 20 deletions wafw00f/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ def performCheck(self, request_method):
r = request_method()
if r is None:
raise RequestBlocked()
return r
return r, r.url

# Most common attacks used to detect WAFs
attcom = [xssAttack, sqliAttack, lfiAttack]
Expand All @@ -123,7 +123,7 @@ def genericdetect(self):
]
try:
# Testing for no user-agent response. Detects almost all WAFs out there.
resp1 = self.performCheck(self.normalRequest)
resp1, _ = self.performCheck(self.normalRequest)
if 'User-Agent' in self.headers:
self.headers.pop('User-Agent') # Deleting the user-agent key from object not dict.
resp3 = self.customRequest(headers=self.headers)
Expand All @@ -139,7 +139,7 @@ def genericdetect(self):
return True

# Testing the status code upon sending a xss attack
resp2 = self.performCheck(self.xssAttack)
resp2, xss_url = self.performCheck(self.xssAttack)
if resp1.status_code != resp2.status_code:
self.log.info('Server returned a different response when a XSS attack vector was tried.')
reason = reasons[2]
Expand All @@ -148,10 +148,10 @@ def genericdetect(self):
reason += ' while the response code to cross-site scripting attack is "%s"' % resp2.status_code
self.knowledge['generic']['reason'] = reason
self.knowledge['generic']['found'] = True
return True
return xss_url

# Testing the status code upon sending a lfi attack
resp2 = self.performCheck(self.lfiAttack)
resp2, lfi_url = self.performCheck(self.lfiAttack)
if resp1.status_code != resp2.status_code:
self.log.info('Server returned a different response when a directory traversal was attempted.')
reason = reasons[2]
Expand All @@ -160,10 +160,10 @@ def genericdetect(self):
reason += ' while the response code to a file inclusion attack is "%s"' % resp2.status_code
self.knowledge['generic']['reason'] = reason
self.knowledge['generic']['found'] = True
return True
return lfi_url

# Testing the status code upon sending a sqli attack
resp2 = self.performCheck(self.sqliAttack)
resp2, sqli_url = self.performCheck(self.sqliAttack)
if resp1.status_code != resp2.status_code:
self.log.info('Server returned a different response when a SQLi was attempted.')
reason = reasons[2]
Expand All @@ -172,7 +172,7 @@ def genericdetect(self):
reason += ' while the response code to a SQL injection attack is "%s"' % resp2.status_code
self.knowledge['generic']['reason'] = reason
self.knowledge['generic']['found'] = True
return True
return sqli_url

# Checking for the Server header after sending malicious requests
normalserver, attackresponse_server = '', ''
Expand Down Expand Up @@ -272,17 +272,17 @@ def matchContent(self, regex, attack=True):
def identwaf(self, findall=False):
detected = list()
try:
self.attackres = self.performCheck(self.centralAttack)
self.attackres, xurl = self.performCheck(self.centralAttack)
except RequestBlocked:
return detected
return detected, None
for wafvendor in self.checklist:
self.log.info('Checking for %s' % wafvendor)
if self.wafdetections[wafvendor](self):
detected.append(wafvendor)
if not findall:
break
self.knowledge['wafname'] = detected
return detected
return detected, xurl

def calclogginglevel(verbosity):
default = 40 # errors are printed out
Expand All @@ -291,18 +291,21 @@ def calclogginglevel(verbosity):
level = 0
return level

def buildResultRecord(url, waf):
def buildResultRecord(url, waf, evil_url=None):
result = {}
result['url'] = url
if waf:
result['detected'] = True
if waf == 'generic':
result['trigger_url'] = evil_url
result['firewall'] = 'Generic'
result['manufacturer'] = 'Unknown'
else:
result['trigger_url'] = evil_url
result['firewall'] = waf.split('(')[0].strip()
result['manufacturer'] = waf.split('(')[1].replace(')', '').strip()
else:
result['trigger_url'] = evil_url
result['detected'] = False
result['firewall'] = 'None'
result['manufacturer'] = 'None'
Expand Down Expand Up @@ -490,22 +493,23 @@ def main():
else:
print('[-] WAF %s was not found in our list\r\nUse the --list option to see what is available' % options.test)
return
waf = attacker.identwaf(options.findall)
waf, xurl = attacker.identwaf(options.findall)
log.info('Identified WAF: %s' % waf)
if len(waf) > 0:
for i in waf:
results.append(buildResultRecord(target, i))
results.append(buildResultRecord(target, i, xurl))
print('[+] The site %s%s%s is behind %s%s%s WAF.' % (B, target, E, C, (E+' and/or '+C).join(waf), E))
if (options.findall) or len(waf) == 0:
print('[+] Generic Detection results:')
if attacker.genericdetect():
generic_url = attacker.genericdetect()
if generic_url:
log.info('Generic Detection: %s' % attacker.knowledge['generic']['reason'])
print('[*] The site %s seems to be behind a WAF or some sort of security solution' % target)
print('[~] Reason: %s' % attacker.knowledge['generic']['reason'])
results.append(buildResultRecord(target, 'generic'))
results.append(buildResultRecord(target, 'generic', generic_url))
else:
print('[-] No WAF detected by the generic detection')
results.append(buildResultRecord(target, None))
results.append(buildResultRecord(target, None, None))
print('[~] Number of requests: %s' % attacker.requestnumber)
#print table of results
if len(results) > 0:
Expand All @@ -514,7 +518,7 @@ def main():
if options.output == '-':
enableStdOut()
if options.format == 'json':
json.dump(results, sys.stdout, indent=2)
json.dump(results, sys.stdout, indent=2, sort_keys=True)
elif options.format == 'csv':
csvwriter = csv.writer(sys.stdout, delimiter=',', quotechar='"',
quoting=csv.QUOTE_MINIMAL)
Expand All @@ -530,7 +534,7 @@ def main():
elif options.output.endswith('.json'):
log.debug("Exporting data in json format to file: %s" % (options.output))
with open(options.output, 'w') as outfile:
json.dump(results, outfile, indent=2)
json.dump(results, outfile, indent=2, sort_keys=True)
elif options.output.endswith('.csv'):
log.debug("Exporting data in csv format to file: %s" % (options.output))
with open(options.output, 'w') as outfile:
Expand All @@ -547,7 +551,7 @@ def main():
log.debug("Exporting data in text format to file: %s" % (options.output))
if options.format == 'json':
with open(options.output, 'w') as outfile:
json.dump(results, outfile, indent=2)
json.dump(results, outfile, indent=2, sort_keys=True)
elif options.format == 'csv':
with open(options.output, 'w') as outfile:
csvwriter = csv.writer(outfile, delimiter=',', quotechar='"',
Expand Down

0 comments on commit ae6a67f

Please sign in to comment.