Skip to content

Instantly share code, notes, and snippets.

@richardevcom
Created May 14, 2020 04:59
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save richardevcom/acdda000794b9c762aba74a6c430d6a9 to your computer and use it in GitHub Desktop.
Save richardevcom/acdda000794b9c762aba74a6c430d6a9 to your computer and use it in GitHub Desktop.
Scan for Stored XSS vulnerabilities in multiple forms & inputs using exploit list
import requests
import argparse
import sys
from bs4 import BeautifulSoup as bs
from urllib.parse import urljoin
""" Prepare arguments for script parse """
parser = argparse.ArgumentParser(description="Detect if target is vulnerable to XSS!?")
parser.add_argument('-u', dest='url', type=str, help="Target URL")
parser.add_argument('-f', dest='file', type=str, help="File containing XSS exploits")
def get_all_forms(u):
""" Parse HTML and get all forms """
soup = bs(requests.get(u).content, "html.parser")
forms = soup.find_all("form")
if len(forms):
print(f"Found {len(forms)} forms.")
return forms
else:
print("No forms found.")
return False
def get_data(forms):
""" Prepare form inputs - input,textarea """
data = {}
i = 0
if forms:
for form in forms:
method = form["method"].lower()
data[i] = {'action' : form["action"].lower(), 'method':method, 'inputs' : []}
form_inputs = form.find_all("input", recursive = False)
form_textareas = form.find_all("textarea", recursive = False)
if len(form_inputs) or len(form_textareas):
if len(form_inputs):
for form_input in form_inputs:
data[i]["inputs"].append(form_input)
if len(form_textareas):
for form_textarea in form_textareas:
data[i]["inputs"].append(form_textarea)
else:
print(f"No inputs found.")
return False
i+=1
return data
def get_contents(fl):
with open(fl) as f:
content = f.readlines()
content = [x.strip() for x in content]
return content
def has_xss(u, f):
forms = get_all_forms(u)
inputs = get_data(forms)
xss = get_contents(f)
if xss:
for exp in xss:
i = 0
data = {}
while inputs:
data_url = u
data_url = urljoin(u, inputs[i]["action"])
for inp in inputs[i]["inputs"]:
try:
iname = inp["name"]
data[iname] = exp
except:
pass
if inputs[i]["method"] == "post":
print(f"Trying: {exp}")
#get_headers = requests.post(u)
#headers = get_headers.headers
#print(headers)
response = requests.post(data_url, data=data)
else:
print(f"Trying: {exp} on {data_url}")
#get_headers = requests.post(u)
#headers = get_headers.headers
#print(headers)
response = requests.get(data_url, params=data)
print(response.status_code, response.reason)
response = response.content.decode()
if exp in response:
print(f"XSS vulnerability {exp} found in {u}")
sys.exit()
i+=1
if i >= len(inputs):
break
else:
print(f"File not found in {f}.")
sys.exit()
if __name__ == "__main__":
args = parser.parse_args(sys.argv[1:])
has_xss(args.url, args.file)
@richardevcom
Copy link
Author

richardevcom commented May 14, 2020

Test scenario: python3 scan-stored-xss.py -u https://xss-game.appspot.com/level1/frame -f ~/xss-naughty-list.txt
Get XSS exploits list here:https://gist.github.com/richardevcom/c81c59f693b5c3c5de0445bdd2a73c47

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment