v3.1.0
- browser engine integration for zero false positives - coverage of event handler context - bug fixes
This commit is contained in:
28
core/browserEngine.py
Normal file
28
core/browserEngine.py
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import re
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
from core.config import xsschecker
|
||||||
|
from core.utils import writer
|
||||||
|
from selenium import webdriver
|
||||||
|
from selenium.webdriver.firefox.options import Options
|
||||||
|
from selenium.common.exceptions import UnexpectedAlertPresentException
|
||||||
|
|
||||||
|
def browserEngine(url, response):
|
||||||
|
options = Options()
|
||||||
|
options.add_argument('--headless')
|
||||||
|
browser = webdriver.Firefox(options=options)
|
||||||
|
response = re.sub(r'<script.*?src=.*?>', '<script src=#>', response, re.I)
|
||||||
|
response = re.sub(r'href=.*?>', 'href=#>', response, re.I)
|
||||||
|
writer(response, 'test.html')
|
||||||
|
browser.get('file://' + sys.path[0] + '/test.html')
|
||||||
|
os.remove('test.html')
|
||||||
|
popUp = False
|
||||||
|
actions = webdriver.ActionChains(browser)
|
||||||
|
try:
|
||||||
|
actions.move_by_offset(2, 2)
|
||||||
|
actions.perform()
|
||||||
|
browser.close()
|
||||||
|
except UnexpectedAlertPresentException:
|
||||||
|
popUp = True
|
||||||
|
browser.quit()
|
||||||
|
return popUp
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
changes = '''ability to load seeds from file;show parameter name while bruteforcing;fixed payload display while using POST method'''
|
changes = '''browser engine integration for zero false positives;coverage of event handler context;bug fixes'''
|
||||||
|
|
||||||
defaultEditor = 'nano'
|
defaultEditor = 'nano'
|
||||||
blindPayload = '' # your blind XSS payload
|
blindPayload = '' # your blind XSS payload
|
||||||
|
|||||||
@@ -11,13 +11,17 @@ def filterChecker(url, params, headers, GET, delay, occurences, timeout, encodin
|
|||||||
for i, occurence in zip(range(len(occurences)), occurences.values()):
|
for i, occurence in zip(range(len(occurences)), occurences.values()):
|
||||||
environments.add(occurence['context'][1])
|
environments.add(occurence['context'][1])
|
||||||
location = occurence['context'][0]
|
location = occurence['context'][0]
|
||||||
attribute = occurence['context'][3]
|
try:
|
||||||
|
attributeName = list(occurence['context'][3].keys())[0]
|
||||||
|
attributeValue = list(occurence['context'][3].values())[0]
|
||||||
|
except AttributeError:
|
||||||
|
attributeName = occurence['context'][3]
|
||||||
positions[str(i)] = occurence['position']
|
positions[str(i)] = occurence['position']
|
||||||
if location == 'comment':
|
if location == 'comment':
|
||||||
environments.add('-->')
|
environments.add('-->')
|
||||||
elif location == 'script':
|
elif location == 'script':
|
||||||
environments.add('</scRipT/>')
|
environments.add('</scRipT/>')
|
||||||
elif attribute == 'srcdoc': # srcdoc attribute accepts html data with html entity encoding
|
elif attributeName == 'srcdoc': # srcdoc attribute accepts html data with html entity encoding
|
||||||
environments.add('<') # so let's add the html entity
|
environments.add('<') # so let's add the html entity
|
||||||
environments.add('>') # encoded versions of < and >
|
environments.add('>') # encoded versions of < and >
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
from core.config import badTags, fillings, eFillings, lFillings, jFillings, eventHandlers, tags, functions
|
from core.config import xsschecker, badTags, fillings, eFillings, lFillings, jFillings, eventHandlers, tags, functions
|
||||||
from core.jsContexter import jsContexter
|
from core.jsContexter import jsContexter
|
||||||
from core.utils import randomUpper as r, genGen, extractScripts
|
from core.utils import randomUpper as r, genGen, extractScripts
|
||||||
|
|
||||||
@@ -12,7 +12,11 @@ def generator(occurences, response):
|
|||||||
context = occurences[i]['context'][0]
|
context = occurences[i]['context'][0]
|
||||||
breaker = occurences[i]['context'][1]
|
breaker = occurences[i]['context'][1]
|
||||||
special = occurences[i]['context'][2]
|
special = occurences[i]['context'][2]
|
||||||
attribute = occurences[i]['context'][3]
|
try:
|
||||||
|
attributeName = list(occurences[i]['context'][3].keys())[0]
|
||||||
|
attributeValue = list(occurences[i]['context'][3].values())[0]
|
||||||
|
except AttributeError:
|
||||||
|
attributeName = occurences[i]['context'][3]
|
||||||
if special not in badTags:
|
if special not in badTags:
|
||||||
special = ''
|
special = ''
|
||||||
elif context == 'attribute':
|
elif context == 'attribute':
|
||||||
@@ -35,6 +39,7 @@ def generator(occurences, response):
|
|||||||
for payload in payloads:
|
for payload in payloads:
|
||||||
vectors[10].add(payload)
|
vectors[10].add(payload)
|
||||||
elif context == 'attribute':
|
elif context == 'attribute':
|
||||||
|
found = False
|
||||||
breakerEfficiency = occurences[i]['score'][breaker]
|
breakerEfficiency = occurences[i]['score'][breaker]
|
||||||
greatBracketEfficiency = occurences[i]['score']['>']
|
greatBracketEfficiency = occurences[i]['score']['>']
|
||||||
ends = ['//']
|
ends = ['//']
|
||||||
@@ -48,28 +53,62 @@ def generator(occurences, response):
|
|||||||
payload = payload.replace(breaker, breaker + '>')
|
payload = payload.replace(breaker, breaker + '>')
|
||||||
else:
|
else:
|
||||||
payload = '>' + payload
|
payload = '>' + payload
|
||||||
vectors[10].add(payload)
|
found = True
|
||||||
|
vectors[6].add(payload)
|
||||||
if breakerEfficiency == 100:
|
if breakerEfficiency == 100:
|
||||||
for filling in fillings:
|
for filling in fillings:
|
||||||
for function in functions:
|
for function in functions:
|
||||||
vector = breaker + filling + 'auTOfOcuS' + \
|
vector = breaker + filling + 'auTOfOcuS' + \
|
||||||
filling + 'OnFoCUs' + '=' + breaker + function
|
filling + 'OnFoCUs' + '=' + breaker + function
|
||||||
|
found = True
|
||||||
vectors[6].add(vector)
|
vectors[6].add(vector)
|
||||||
if breakerEfficiency == 90:
|
if breakerEfficiency == 90:
|
||||||
for filling in fillings:
|
for filling in fillings:
|
||||||
for function in functions:
|
for function in functions:
|
||||||
vector = '\\' + breaker + filling + 'auTOfOcuS' + filling + \
|
vector = '\\' + breaker + filling + 'auTOfOcuS' + filling + \
|
||||||
'OnFoCUs' + '=' + function + filling + '\\' + breaker
|
'OnFoCUs' + '=' + function + filling + '\\' + breaker
|
||||||
|
found = True
|
||||||
vectors[6].add(vector)
|
vectors[6].add(vector)
|
||||||
if attribute == 'srcdoc':
|
if attributeName == 'srcdoc':
|
||||||
if occurences[i]['score']['<']:
|
if occurences[i]['score']['<']:
|
||||||
if occurences[i]['score']['>']:
|
if occurences[i]['score']['>']:
|
||||||
del ends[:]
|
del ends[:]
|
||||||
ends.append('&t;')
|
ends.append('%26gt;')
|
||||||
payloads = genGen(
|
payloads = genGen(
|
||||||
fillings, eFillings, lFillings, eventHandlers, tags, functions, ends, '', '')
|
fillings, eFillings, lFillings, eventHandlers, tags, functions, ends, '', '')
|
||||||
for payload in payloads:
|
for payload in payloads:
|
||||||
vectors[10].add(payload.replace('<', '<'))
|
found = True
|
||||||
|
vectors[9].add(payload.replace('<', '%26lt;'))
|
||||||
|
if attributeName.startswith('on'):
|
||||||
|
closer = jsContexter(attributeValue)
|
||||||
|
breaker = ''
|
||||||
|
for char in attributeValue.split(xsschecker)[1]:
|
||||||
|
if char in ['\'', '"', '`']:
|
||||||
|
breaker = char
|
||||||
|
break
|
||||||
|
if closer:
|
||||||
|
suffix = '//\\'
|
||||||
|
for filling in jFillings:
|
||||||
|
for function in functions:
|
||||||
|
vector = breaker + closer + filling + function + suffix
|
||||||
|
if found:
|
||||||
|
vectors[7].add(vector)
|
||||||
|
else:
|
||||||
|
vectors[9].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
|
||||||
|
if found:
|
||||||
|
vectors[7].add(vector)
|
||||||
|
else:
|
||||||
|
vectors[9].add(vector)
|
||||||
|
|
||||||
elif context == 'comment':
|
elif context == 'comment':
|
||||||
lessBracketEfficiency = occurences[i]['score']['<']
|
lessBracketEfficiency = occurences[i]['score']['<']
|
||||||
greatBracketEfficiency = occurences[i]['score']['>']
|
greatBracketEfficiency = occurences[i]['score']['>']
|
||||||
@@ -83,13 +122,13 @@ def generator(occurences, response):
|
|||||||
for payload in payloads:
|
for payload in payloads:
|
||||||
vectors[10].add(payload)
|
vectors[10].add(payload)
|
||||||
elif context == 'script':
|
elif context == 'script':
|
||||||
try:
|
if scripts:
|
||||||
script = scripts[index]
|
|
||||||
except IndexError:
|
|
||||||
try:
|
try:
|
||||||
|
script = scripts[index]
|
||||||
|
except IndexError:
|
||||||
script = scripts[0]
|
script = scripts[0]
|
||||||
except:
|
else:
|
||||||
continue
|
continue
|
||||||
closer = jsContexter(script)
|
closer = jsContexter(script)
|
||||||
scriptEfficiency = occurences[i]['score']['</scRipT/>']
|
scriptEfficiency = occurences[i]['score']['</scRipT/>']
|
||||||
greatBracketEfficiency = occurences[i]['score']['>']
|
greatBracketEfficiency = occurences[i]['score']['>']
|
||||||
|
|||||||
@@ -69,7 +69,11 @@ def htmlParser(response, encoding):
|
|||||||
for attr in attrs: # iterate over the attribute
|
for attr in attrs: # iterate over the attribute
|
||||||
if xsschecker in attr: # is xsschecker in this attribute?
|
if xsschecker in attr: # is xsschecker in this attribute?
|
||||||
# alright, this is the one we need
|
# alright, this is the one we need
|
||||||
attributes.append(attr.split('=')[0])
|
attributeName = attr.split('=')[0]
|
||||||
|
attributeValue = ''.join(attr.split('=')[1:])
|
||||||
|
if attributeValue.startswith('\'') or attributeValue.startswith('"'):
|
||||||
|
attributeValue = attributeValue[1:-1]
|
||||||
|
attributes.append({attributeName:attributeValue})
|
||||||
break
|
break
|
||||||
try:
|
try:
|
||||||
# finds the tag "inside" which input is refelcted
|
# finds the tag "inside" which input is refelcted
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ def genGen(fillings, eFillings, lFillings, eventHandlers, tags, functions, ends,
|
|||||||
r = randomUpper # randomUpper randomly converts chars of a string to uppercase
|
r = randomUpper # randomUpper randomly converts chars of a string to uppercase
|
||||||
for tag in tags:
|
for tag in tags:
|
||||||
if tag == 'd3v' or tag == 'a':
|
if tag == 'd3v' or tag == 'a':
|
||||||
bait = 'z'
|
bait = xsschecker
|
||||||
else:
|
else:
|
||||||
bait = ''
|
bait = ''
|
||||||
for eventHandler in eventHandlers:
|
for eventHandler in eventHandlers:
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import copy
|
import copy
|
||||||
|
import re
|
||||||
from urllib.parse import urlparse, quote, unquote
|
from urllib.parse import urlparse, quote, unquote
|
||||||
|
|
||||||
from core.arjun import arjun
|
from core.arjun import arjun
|
||||||
|
from core.browserEngine import browserEngine
|
||||||
from core.checker import checker
|
from core.checker import checker
|
||||||
from core.colors import good, bad, end, info, green, run, red, que
|
from core.colors import good, bad, end, info, green, run, red, que
|
||||||
from core.config import xsschecker, minEfficiency
|
from core.config import xsschecker, minEfficiency
|
||||||
@@ -86,29 +88,51 @@ def scan(target, paramData, verbose, encoding, headers, delay, timeout, skipDOM,
|
|||||||
progress = 0
|
progress = 0
|
||||||
for confidence, vects in vectors.items():
|
for confidence, vects in vectors.items():
|
||||||
for vect in vects:
|
for vect in vects:
|
||||||
|
printVector = vect
|
||||||
progress += 1
|
progress += 1
|
||||||
if not GET:
|
print ('%s Progress: %i/%i' % (run, progress, total), end='\r')
|
||||||
|
if confidence == 10:
|
||||||
|
if not GET:
|
||||||
|
vect = unquote(vect)
|
||||||
|
efficiencies = checker(
|
||||||
|
url, paramsCopy, headers, GET, delay, vect, positions, timeout, encoding)
|
||||||
|
if not efficiencies:
|
||||||
|
for i in range(len(occurences)):
|
||||||
|
efficiencies.append(0)
|
||||||
|
bestEfficiency = max(efficiencies)
|
||||||
|
if bestEfficiency == 100 or (vect[0] == '\\' and bestEfficiency >= 95):
|
||||||
|
print(('%s-%s' % (red, end)) * 60)
|
||||||
|
print('%s Payload: %s' % (good, printVector))
|
||||||
|
print('%s Efficiency: %i' % (info, bestEfficiency))
|
||||||
|
print('%s Confidence: %i' % (info, confidence))
|
||||||
|
if not skip:
|
||||||
|
choice = input(
|
||||||
|
'%s Would you like to continue scanning? [y/N] ' % que).lower()
|
||||||
|
if choice != 'y':
|
||||||
|
quit()
|
||||||
|
elif bestEfficiency > minEfficiency:
|
||||||
|
print(('%s-%s' % (red, end)) * 60)
|
||||||
|
print('%s Payload: %s' % (good, printVector))
|
||||||
|
print('%s Efficiency: %i' % (info, bestEfficiency))
|
||||||
|
print('%s Confidence: %i' % (info, confidence))
|
||||||
|
else:
|
||||||
|
if re.search(r'<(a|d3|details)|lt;(a|d3|details)', vect.lower()):
|
||||||
|
continue
|
||||||
vect = unquote(vect)
|
vect = unquote(vect)
|
||||||
efficiencies = checker(
|
if encoding:
|
||||||
url, paramsCopy, headers, GET, delay, vect, positions, timeout, encoding)
|
paramsCopy[paramName] = encoding(vect)
|
||||||
if not GET:
|
else:
|
||||||
vect = quote(vect)
|
paramsCopy[paramName] = vect
|
||||||
if not efficiencies:
|
response = requester(url, paramsCopy, headers, GET, delay, timeout).text
|
||||||
for i in range(len(occurences)):
|
success = browserEngine(response)
|
||||||
efficiencies.append(0)
|
if success:
|
||||||
bestEfficiency = max(efficiencies)
|
print(('%s-%s' % (red, end)) * 60)
|
||||||
if bestEfficiency == 100 or (vect[0] == '\\' and bestEfficiency >= 95):
|
print('%s Payload: %s' % (good, printVector))
|
||||||
print(('%s-%s' % (red, end)) * 60)
|
print('%s Efficiency: %i' % (info, 100))
|
||||||
print('%s Payload: %s' % (good, vect))
|
print('%s Confidence: %i' % (info, 10))
|
||||||
print('%s Efficiency: %i' % (info, bestEfficiency))
|
if not skip:
|
||||||
print('%s Confidence: %i' % (info, confidence))
|
choice = input(
|
||||||
if not skip:
|
'%s Would you like to continue scanning? [y/N] ' % que).lower()
|
||||||
choice = input(
|
if choice != 'y':
|
||||||
'%s Would you like to continue scanning? [y/N] ' % que).lower()
|
quit()
|
||||||
if choice != 'y':
|
print ('')
|
||||||
quit()
|
|
||||||
elif bestEfficiency > minEfficiency:
|
|
||||||
print(('%s-%s' % (red, end)) * 60)
|
|
||||||
print('%s Payload: %s' % (good, vect))
|
|
||||||
print('%s Efficiency: %i' % (info, bestEfficiency))
|
|
||||||
print('%s Confidence: %i' % (info, confidence))
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
tld
|
tld
|
||||||
fuzzywuzzy
|
fuzzywuzzy
|
||||||
requests
|
requests
|
||||||
|
selenium
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ from modes.singleFuzz import singleFuzz
|
|||||||
|
|
||||||
# Just a fancy ass banner
|
# Just a fancy ass banner
|
||||||
print('''%s
|
print('''%s
|
||||||
\tXSStrike %sv3.0.5
|
\tXSStrike %sv3.1.0
|
||||||
%s''' % (red, white, end))
|
%s''' % (red, white, end))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|||||||
Reference in New Issue
Block a user