From a4aa0d13a6155dec01a1ab1b1a0494f593d100d0 Mon Sep 17 00:00:00 2001 From: Glenn McGuire Date: Wed, 22 Feb 2017 17:02:57 +1100 Subject: [PATCH 01/12] huge code cleanup and removed superfluous try-catches --- XssPy.py | 191 +++++++++++++++++++------------------------------------ 1 file changed, 67 insertions(+), 124 deletions(-) diff --git a/XssPy.py b/XssPy.py index e7647b9..578014d 100644 --- a/XssPy.py +++ b/XssPy.py @@ -53,78 +53,63 @@ def log(lvl, col, msg): logger.setLevel(logging.DEBUG if results.verbose else logging.INFO) -def initializeAndFind(firstDomains): +def initializeAndFind(): - dummy = 0 #dummy variable for doing nothing - firstDomains = [] #list of domains if not results.url: #if the url has been passed or not color.log(logging.INFO, color.GREEN, 'Url not provided correctly') - return 0 + return - smallurl = results.url #small url is the part of url without http and www - + firstDomains = [] #list of domains allURLS = [] - allURLS.append(smallurl) #just one url at the moment + allURLS.append(results.url) #just one url at the moment largeNumberOfUrls = [] #in case one wants to do comprehensive search - color.log(logging.INFO, color.GREEN, 'Doing a short traversal.') #doing a short traversal if no command line argument is being passed - for url in allURLS: - x = str(url) - smallurl = x - try: # Test HTTPS/HTTP compatibility. Prefers HTTPS but defaults to HTTP if any errors are encountered - test = httplib.HTTPSConnection(smallurl) - test.request("GET", "/") - response = test.getresponse() - if (response.status == 200) | (response.status == 302): - url = "https://www." + str(url) - elif response.status == 301: - loc = response.getheader('Location') - url = loc.scheme + '://' + loc.netloc - else: - url = "http://www." + str(url) - except: - url = "http://www." + str(url) - - try: - br.open(url) - color.log(logging.INFO, color.GREEN, 'Finding all the links of the website ' + str(url)) - try: - for link in br.links(): #finding the links of the website - if smallurl in str(link.absolute_url): - firstDomains.append(str(link.absolute_url)) - firstDomains = list(set(firstDomains)) - except: - dummy = 0 - except: - dummy = 0 - color.log(logging.INFO, color.GREEN, 'Number of links to test are: ' + str(len(firstDomains))) - + color.log(logging.INFO, color.GREEN, 'Doing a short traversal.') #doing a short traversal if no command line argument is being passed + for url in allURLS: + smallurl = str(url) + try: # Test HTTPS/HTTP compatibility. Prefers HTTPS but defaults to HTTP if any errors are encountered + test = httplib.HTTPSConnection(smallurl) + test.request("GET", "/") + response = test.getresponse() + if (response.status == 200) | (response.status == 302): + url = "https://www." + str(url) + elif response.status == 301: + loc = response.getheader('Location') + url = loc.scheme + '://' + loc.netloc + else: + url = "http://www." + str(url) + except: + url = "http://www." + str(url) + try: + br.open(url) + color.log(logging.INFO, color.GREEN, 'Finding all the links of the website ' + str(url)) + for link in br.links(): #finding the links of the website + if smallurl in str(link.absolute_url): + firstDomains.append(str(link.absolute_url)) + firstDomains = list(set(firstDomains)) + except: + pass + color.log(logging.INFO, color.GREEN, 'Number of links to test are: ' + str(len(firstDomains))) if results.compOn: - color.log(logging.INFO, color.GREEN, 'Doing a comprehensive traversal. This could take a while') - for link in firstDomains: - try: - br.open(link) - try: - for newlink in br.links(): #going deeper into each link and finding its links - if smallurl in str(newlink.absolute_url): - largeNumberOfUrls.append(newlink.absolute_url) - except: - dummy = 0 - except: - dummy = 0 - - firstDomains = list(set(firstDomains + largeNumberOfUrls)) - color.log(logging.INFO, color.GREEN, 'Total Number of links to test have become: ' + str(len(firstDomains))) #all links have been found + color.log(logging.INFO, color.GREEN, 'Doing a comprehensive traversal. This could take a while') + for link in firstDomains: + try: + br.open(link) + for newlink in br.links(): #going deeper into each link and finding its links + if url in str(newlink.absolute_url): + largeNumberOfUrls.append(newlink.absolute_url) + except: + pass + firstDomains = list(set(firstDomains + largeNumberOfUrls)) + color.log(logging.INFO, color.GREEN, 'Total Number of links to test have become: ' + str(len(firstDomains))) #all links have been found return firstDomains def findxss(firstDomains): color.log(logging.INFO, color.GREEN, 'Started finding XSS') #starting finding XSS xssLinks = [] #TOTAL CROSS SITE SCRIPTING FINDINGS - count = 0 #to check for forms - dummyVar = 0 #dummy variable for doing nothing - if len(firstDomains) > 0: #if there is atleast one link + if firstDomains: #if there is atleast one link for link in firstDomains: y = str(link) color.log(logging.DEBUG, color.YELLOW, str(link)) @@ -133,79 +118,37 @@ def findxss(firstDomains): elif 'pdf' in y: color.log(logging.DEBUG, color.RED, '\tNot a good url to test') else: - try: + try: br.open(str(link)) #open the link - except: - dummyVar = 0 - try: - for form in br.forms(): #check its forms - count = count + 1 - except: - dummyVar = 0 - if count > 0: #if a form exists, submit it - try: + if br.forms(): #if a form exists, submit it params = list(br.forms())[0] #our form - except: - dummyVar = 0 - try: br.select_form(nr=0) #submit the first form - except: - dummyVar = 0 - for p in params.controls: - par = str(p) - if 'TextControl' in par: #submit only those forms which require text - color.log(logging.DEBUG, color.YELLOW, '\tParam: ' + str(p.name)) - try: - br.form[str(p.name)] = '' #our payload - except: - dummyVar = 0 - try: - br.submit() - except: - dummyVar = 0 - try: - if '' in br.response().read(): #if payload is found in response, we have XSS - color.log(logging.INFO, color.BOLD+color.GREEN, 'Xss found and the link is ' + str(link) + ' And the payload is ') - xssLinks.append(link) - else: - dummyVar = 0 - except: - color.log(logging.INFO, color.RED, '\tcould not read the page') - try: - br.back() - except: - dummyVar = 0 - - #SECOND PAYLOAD - - try: - br.form[str(p.name)] = 'javascript:alert(1)' #second payload - except: - dummyVar = 0 - try: - br.submit() - except: - dummyVar = 0 - try: - if '' #our payload + br.submit() + if '' in br.response().read(): #if payload is found in response, we have XSS + color.log(logging.INFO, color.BOLD+color.GREEN, 'Xss found and the link is ' + str(link) + ' And the payload is ') + xssLinks.append(link) + br.back() + #SECOND PAYLOAD + br.form[str(p.name)] = 'javascript:alert(1)' #second payload + br.submit() + if '', '" onfocus="alert(1);', 'javascript:alert(1)'] +blacklist = ['.png', '.jpg', '.jpeg', '.mp3', '.mp4', '.avi', '.gif', '.svg', '.pdf'] class color: RED = '\033[91m' @@ -27,6 +29,7 @@ def log(lvl, col, msg): Email: fsecurify@gmail.com Usage: pythonXssPy.py website.com (Do not write www.website.com OR http://www.website.com) Comprehensive Scan: python XssPy.py website.com -e +Verbose logging: python XssPy.py website.com -v Description: XssPy is a python tool for finding Cross Site Scripting vulnerabilities in websites. This tool is the first of its kind. @@ -53,18 +56,25 @@ def log(lvl, col, msg): logger.setLevel(logging.DEBUG if results.verbose else logging.INFO) +def testPayload(payload, p, link): + br.form[str(p.name)] = payload + br.submit() + if payload in br.response().read(): #if payload is found in response, we have XSS + color.log(logging.INFO, color.BOLD+color.GREEN, 'Xss found and the link is %s And the payload is %s' % (str(link), payload)) + xssLinks.append(link) + br.back() + def initializeAndFind(): if not results.url: #if the url has been passed or not color.log(logging.INFO, color.GREEN, 'Url not provided correctly') - return + return [] firstDomains = [] #list of domains allURLS = [] allURLS.append(results.url) #just one url at the moment largeNumberOfUrls = [] #in case one wants to do comprehensive search - color.log(logging.INFO, color.GREEN, 'Doing a short traversal.') #doing a short traversal if no command line argument is being passed for url in allURLS: smallurl = str(url) @@ -87,22 +97,22 @@ def initializeAndFind(): for link in br.links(): #finding the links of the website if smallurl in str(link.absolute_url): firstDomains.append(str(link.absolute_url)) - firstDomains = list(set(firstDomains)) + firstDomains = list(set(firstDomains)) except: pass - color.log(logging.INFO, color.GREEN, 'Number of links to test are: ' + str(len(firstDomains))) - if results.compOn: - color.log(logging.INFO, color.GREEN, 'Doing a comprehensive traversal. This could take a while') - for link in firstDomains: - try: - br.open(link) - for newlink in br.links(): #going deeper into each link and finding its links - if url in str(newlink.absolute_url): - largeNumberOfUrls.append(newlink.absolute_url) - except: - pass - firstDomains = list(set(firstDomains + largeNumberOfUrls)) - color.log(logging.INFO, color.GREEN, 'Total Number of links to test have become: ' + str(len(firstDomains))) #all links have been found + color.log(logging.INFO, color.GREEN, 'Number of links to test are: ' + str(len(firstDomains))) + if results.compOn: + color.log(logging.INFO, color.GREEN, 'Doing a comprehensive traversal. This could take a while') + for link in firstDomains: + try: + br.open(link) + for newlink in br.links(): #going deeper into each link and finding its links + if smallurl in str(newlink.absolute_url): + largeNumberOfUrls.append(newlink.absolute_url) + except: + pass + firstDomains = list(set(firstDomains + largeNumberOfUrls)) + color.log(logging.INFO, color.GREEN, 'Total Number of links to test have become: ' + str(len(firstDomains))) #all links have been found return firstDomains @@ -111,13 +121,15 @@ def findxss(firstDomains): xssLinks = [] #TOTAL CROSS SITE SCRIPTING FINDINGS if firstDomains: #if there is atleast one link for link in firstDomains: + blacklisted = False y = str(link) color.log(logging.DEBUG, color.YELLOW, str(link)) - if 'jpg' in y: #just a small check - color.log(logging.DEBUG, color.RED, '\tNot a good url to test') - elif 'pdf' in y: - color.log(logging.DEBUG, color.RED, '\tNot a good url to test') - else: + for ext in blacklist: + if ext in y: + color.log(logging.DEBUG, color.RED, '\tNot a good url to test') + blacklisted = True + break + if not blacklisted: try: br.open(str(link)) #open the link if br.forms(): #if a form exists, submit it @@ -127,20 +139,8 @@ def findxss(firstDomains): par = str(p) if 'TextControl' in par: #submit only those forms which require text color.log(logging.DEBUG, color.YELLOW, '\tParam: ' + str(p.name)) - br.form[str(p.name)] = '' #our payload - br.submit() - if '' in br.response().read(): #if payload is found in response, we have XSS - color.log(logging.INFO, color.BOLD+color.GREEN, 'Xss found and the link is ' + str(link) + ' And the payload is ') - xssLinks.append(link) - br.back() - #SECOND PAYLOAD - br.form[str(p.name)] = 'javascript:alert(1)' #second payload - br.submit() - if ' Date: Wed, 22 Feb 2017 18:58:47 +1100 Subject: [PATCH 04/12] added element and payload field to output. made it look better for both verbose and non verbose --- XssPy.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/XssPy.py b/XssPy.py index 2db9fb2..e5bc0eb 100644 --- a/XssPy.py +++ b/XssPy.py @@ -12,6 +12,7 @@ payloads = ['', '" onfocus="alert(1);', 'javascript:alert(1)'] blacklist = ['.png', '.jpg', '.jpeg', '.mp3', '.mp4', '.avi', '.gif', '.svg', '.pdf'] +xssLinks = [] #TOTAL CROSS SITE SCRIPTING FINDINGS class color: BLUE = '\033[94m' @@ -63,8 +64,10 @@ def testPayload(payload, p, link): br.form[str(p.name)] = payload br.submit() if payload in br.response().read(): #if payload is found in response, we have XSS - color.log(logging.INFO, color.BOLD+color.GREEN, 'Xss found and the link is %s And the payload is %s' % (str(link), payload)) - xssLinks.append(link) + color.log(logging.DEBUG, color.BOLD+color.GREEN, 'XSS found!') + report = 'Link: %s, Payload: %s, Element: %s' % (str(link), payload, str(p.name)) + color.log(logging.INFO, color.BOLD+color.GREEN, report) + xssLinks.append(report) br.back() def initializeAndFind(): @@ -125,7 +128,6 @@ def initializeAndFind(): def findxss(firstDomains): color.log(logging.INFO, color.GREEN, 'Started finding XSS') #starting finding XSS - xssLinks = [] #TOTAL CROSS SITE SCRIPTING FINDINGS if firstDomains: #if there is atleast one link for link in firstDomains: blacklisted = False From 084fb8c4292593de4387344ef5aa0a9343990f3a Mon Sep 17 00:00:00 2001 From: Glenn McGuire Date: Thu, 23 Feb 2017 16:15:47 +1100 Subject: [PATCH 05/12] fixed logging level on cookie listing --- XssPy.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/XssPy.py b/XssPy.py index e5bc0eb..caf32d7 100644 --- a/XssPy.py +++ b/XssPy.py @@ -100,7 +100,7 @@ def initializeAndFind(): try: br.open(url) for cookie in results.cookies: - color.log(logging.DEBUG, color.BLUE, 'Adding cookie: %s' % cookie) + color.log(logging.INFO, color.BLUE, 'Adding cookie: %s' % cookie) br.set_cookie(cookie) br.open(url) color.log(logging.INFO, color.GREEN, 'Finding all the links of the website ' + str(url)) From 4048740dc3c2c72f8cd63877f15f301f19d23c69 Mon Sep 17 00:00:00 2001 From: Matthew Brener Date: Sun, 19 Mar 2017 14:18:08 +1100 Subject: [PATCH 06/12] 98% PEP-8 Compliant --- XssPy.py | 257 +++++++++++++++++++++++++++++++------------------------ 1 file changed, 145 insertions(+), 112 deletions(-) diff --git a/XssPy.py b/XssPy.py index caf32d7..591c63f 100644 --- a/XssPy.py +++ b/XssPy.py @@ -5,38 +5,45 @@ import logging from urlparse import urlparse -br = mechanize.Browser() #initiating the browser -br.addheaders = [('User-agent', 'Mozilla/5.0 (Windows; U; Windows NT 5.1; it; rv:1.8.1.11)Gecko/20071127 Firefox/2.0.0.11')] +br = mechanize.Browser() # initiating the browser +br.addheaders = [ + ('User-agent', + 'Mozilla/5.0 (Windows; U; Windows NT 5.1; it; rv:1.8.1.11)Gecko/20071127 Firefox/2.0.0.11') +] br.set_handle_robots(False) br.set_handle_refresh(False) payloads = ['', '" onfocus="alert(1);', 'javascript:alert(1)'] -blacklist = ['.png', '.jpg', '.jpeg', '.mp3', '.mp4', '.avi', '.gif', '.svg', '.pdf'] -xssLinks = [] #TOTAL CROSS SITE SCRIPTING FINDINGS +blacklist = ['.png', '.jpg', '.jpeg', '.mp3', '.mp4', '.avi', '.gif', '.svg', + '.pdf'] +xssLinks = [] # TOTAL CROSS SITE SCRIPTING FINDINGS + class color: - BLUE = '\033[94m' - RED = '\033[91m' - GREEN = '\033[92m' - YELLOW = '\033[93m' - BOLD = '\033[1m' - END = '\033[0m' - @staticmethod - def log(lvl, col, msg): - logger.log(lvl, col + msg + color.END) + BLUE = '\033[94m' + RED = '\033[91m' + GREEN = '\033[92m' + YELLOW = '\033[93m' + BOLD = '\033[1m' + END = '\033[0m' + + @staticmethod + def log(lvl, col, msg): + logger.log(lvl, col + msg + color.END) + print color.BOLD + color.RED + """ XssPy - Finding XSS made easier Author: Faizan Ahmad (Fsecurify) Email: fsecurify@gmail.com -Usage: pythonXssPy.py website.com (Do not write www.website.com OR http://www.website.com) +Usage: XssPy.py website.com (Not www.website.com OR http://www.website.com) Comprehensive Scan: python XssPy.py -u website.com -e Verbose logging: python XssPy.py -u website.com -v Cookies: python XssPy.py -u website.complex -c name=val name=val -Description: XssPy is a python tool for finding Cross Site Scripting +Description: XssPy is a python tool for finding Cross Site Scripting vulnerabilities in websites. This tool is the first of its kind. -Instead of just checking one page as most of the tools do, this tool +Instead of just checking one page as most of the tools do, this tool traverses the website and find all the links and subdomains first. After that, it starts scanning each and every input on each and every page that it found while its traversal. It uses small yet effective @@ -52,112 +59,138 @@ def log(lvl, col, msg): lh.setFormatter(formatter) parser = argparse.ArgumentParser() -parser.add_argument('-u', action='store', dest='url', help='The URL to analyze') -parser.add_argument('-e', action='store_true', dest='compOn', help='Enable comprehensive scan') -parser.add_argument('-v', action='store_true', dest='verbose', help='Enable verbose logging') -parser.add_argument('-c', action='store', dest='cookies', help='Space separated list of cookies', nargs='+', default=[]) +parser.add_argument('-u', action='store', dest='url', + help='The URL to analyze') +parser.add_argument('-e', action='store_true', dest='compOn', + help='Enable comprehensive scan') +parser.add_argument('-v', action='store_true', dest='verbose', + help='Enable verbose logging') +parser.add_argument('-c', action='store', dest='cookies', + help='Space separated list of cookies', + nargs='+', default=[]) results = parser.parse_args() logger.setLevel(logging.DEBUG if results.verbose else logging.INFO) + def testPayload(payload, p, link): - br.form[str(p.name)] = payload - br.submit() - if payload in br.response().read(): #if payload is found in response, we have XSS - color.log(logging.DEBUG, color.BOLD+color.GREEN, 'XSS found!') - report = 'Link: %s, Payload: %s, Element: %s' % (str(link), payload, str(p.name)) - color.log(logging.INFO, color.BOLD+color.GREEN, report) - xssLinks.append(report) - br.back() + br.form[str(p.name)] = payload + br.submit() + # if payload is found in response, we have XSS + if payload in br.response().read(): + color.log(logging.DEBUG, color.BOLD + color.GREEN, 'XSS found!') + report = 'Link: %s, Payload: %s, Element: %s' % (str(link), + payload, str(p.name)) + color.log(logging.INFO, color.BOLD + color.GREEN, report) + xssLinks.append(report) + br.back() + def initializeAndFind(): - if not results.url: #if the url has been passed or not - color.log(logging.INFO, color.GREEN, 'Url not provided correctly') - return [] - - firstDomains = [] #list of domains - allURLS = [] - allURLS.append(results.url) #just one url at the moment - largeNumberOfUrls = [] #in case one wants to do comprehensive search - - color.log(logging.INFO, color.GREEN, 'Doing a short traversal.') #doing a short traversal if no command line argument is being passed - for url in allURLS: - smallurl = str(url) - try: # Test HTTPS/HTTP compatibility. Prefers HTTPS but defaults to HTTP if any errors are encountered - test = httplib.HTTPSConnection(smallurl) - test.request("GET", "/") - response = test.getresponse() - if (response.status == 200) | (response.status == 302): - url = "https://www." + str(url) - elif response.status == 301: - loc = response.getheader('Location') - url = loc.scheme + '://' + loc.netloc - else: - url = "http://www." + str(url) - except: - url = "http://www." + str(url) - try: - br.open(url) - for cookie in results.cookies: - color.log(logging.INFO, color.BLUE, 'Adding cookie: %s' % cookie) - br.set_cookie(cookie) - br.open(url) - color.log(logging.INFO, color.GREEN, 'Finding all the links of the website ' + str(url)) - for link in br.links(): #finding the links of the website - if smallurl in str(link.absolute_url): - firstDomains.append(str(link.absolute_url)) - firstDomains = list(set(firstDomains)) - except: - pass - color.log(logging.INFO, color.GREEN, 'Number of links to test are: ' + str(len(firstDomains))) - if results.compOn: - color.log(logging.INFO, color.GREEN, 'Doing a comprehensive traversal. This could take a while') - for link in firstDomains: - try: - br.open(link) - for newlink in br.links(): #going deeper into each link and finding its links - if smallurl in str(newlink.absolute_url): - largeNumberOfUrls.append(newlink.absolute_url) - except: - pass - firstDomains = list(set(firstDomains + largeNumberOfUrls)) - color.log(logging.INFO, color.GREEN, 'Total Number of links to test have become: ' + str(len(firstDomains))) #all links have been found - return firstDomains + if not results.url: # if the url has been passed or not + color.log(logging.INFO, color.GREEN, 'Url not provided correctly') + return [] + + firstDomains = [] # list of domains + allURLS = [] + allURLS.append(results.url) # just one url at the moment + largeNumberOfUrls = [] # in case one wants to do comprehensive search + + # doing a short traversal if no command line argument is being passed + color.log(logging.INFO, color.GREEN, 'Doing a short traversal.') + for url in allURLS: + smallurl = str(url) + # Test HTTPS/HTTP compatibility. Prefers HTTPS but defaults to + # HTTP if any errors are encountered + try: + test = httplib.HTTPSConnection(smallurl) + test.request("GET", "/") + response = test.getresponse() + if (response.status == 200) | (response.status == 302): + url = "https://www." + str(url) + elif response.status == 301: + loc = response.getheader('Location') + url = loc.scheme + '://' + loc.netloc + else: + url = "http://www." + str(url) + except: + url = "http://www." + str(url) + try: + br.open(url) + for cookie in results.cookies: + color.log(logging.INFO, color.BLUE, + 'Adding cookie: %s' % cookie) + br.set_cookie(cookie) + br.open(url) + color.log(logging.INFO, color.GREEN, + 'Finding all the links of the website ' + str(url)) + for link in br.links(): # finding the links of the website + if smallurl in str(link.absolute_url): + firstDomains.append(str(link.absolute_url)) + firstDomains = list(set(firstDomains)) + except: + pass + color.log(logging.INFO, color.GREEN, + 'Number of links to test are: ' + str(len(firstDomains))) + if results.compOn: + color.log(logging.INFO, color.GREEN, + 'Doing a comprehensive traversal. This may take a while') + for link in firstDomains: + try: + br.open(link) + # going deeper into each link and finding its links + for newlink in br.links(): + if smallurl in str(newlink.absolute_url): + largeNumberOfUrls.append(newlink.absolute_url) + except: + pass + firstDomains = list(set(firstDomains + largeNumberOfUrls)) + color.log(logging.INFO, color.GREEN, + 'Total Number of links to test have become: ' + + str(len(firstDomains))) # all links have been found + return firstDomains def findxss(firstDomains): - color.log(logging.INFO, color.GREEN, 'Started finding XSS') #starting finding XSS - if firstDomains: #if there is atleast one link - for link in firstDomains: - blacklisted = False - y = str(link) - color.log(logging.DEBUG, color.YELLOW, str(link)) - for ext in blacklist: - if ext in y: - color.log(logging.DEBUG, color.RED, '\tNot a good url to test') - blacklisted = True - break - if not blacklisted: - try: - br.open(str(link)) #open the link - if br.forms(): #if a form exists, submit it - params = list(br.forms())[0] #our form - br.select_form(nr=0) #submit the first form - for p in params.controls: - par = str(p) - if 'TextControl' in par: #submit only those forms which require text - color.log(logging.DEBUG, color.YELLOW, '\tParam: ' + str(p.name)) - for item in payloads: - testPayload(item, p, link) - except: - pass - color.log(logging.DEBUG, color.GREEN+color.BOLD, 'The following links are vulnerable: ') - for link in xssLinks: #print all xss findings - color.log(logging.DEBUG, color.GREEN, '\t'+link) - else: - color.log(logging.INFO, color.RED+color.BOLD, '\tNo link found, exiting') - -#calling the function + # starting finding XSS + color.log(logging.INFO, color.GREEN, 'Started finding XSS') + if firstDomains: # if there is atleast one link + for link in firstDomains: + blacklisted = False + y = str(link) + color.log(logging.DEBUG, color.YELLOW, str(link)) + for ext in blacklist: + if ext in y: + color.log(logging.DEBUG, color.RED, + '\tNot a good url to test') + blacklisted = True + break + if not blacklisted: + try: + br.open(str(link)) # open the link + if br.forms(): # if a form exists, submit it + params = list(br.forms())[0] # our form + br.select_form(nr=0) # submit the first form + for p in params.controls: + par = str(p) + # submit only those forms which require text + if 'TextControl' in par: + color.log(logging.DEBUG, color.YELLOW, + '\tParam: ' + str(p.name)) + for item in payloads: + testPayload(item, p, link) + except: + pass + color.log(logging.DEBUG, color.GREEN + color.BOLD, + 'The following links are vulnerable: ') + for link in xssLinks: # print all xss findings + color.log(logging.DEBUG, color.GREEN, '\t' + link) + else: + color.log(logging.INFO, color.RED + color.BOLD, + '\tNo link found, exiting') + + +# calling the function firstDomains = initializeAndFind() findxss(firstDomains) From 71a9b2fd6871ea5eb5b947349d0d81e980ab9bec Mon Sep 17 00:00:00 2001 From: Santiago Castro Date: Tue, 18 Apr 2017 02:08:10 -0300 Subject: [PATCH 07/12] Fix broken Markdown headings --- README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 7be5711..a0c28d0 100644 --- a/README.md +++ b/README.md @@ -4,27 +4,27 @@ A tool by Fsecurify Author: Faizan Ahmad https://pk.linkedin.com/in/faizan-ahmad-015964118 -#Great News: Xsspy was recently used by an engineer at microsoft to find a bug in Pentagon's Bug Bounty Program. +# Great News: Xsspy was recently used by an engineer at microsoft to find a bug in Pentagon's Bug Bounty Program. http://holisticinfosec.blogspot.com/2016/06/toolsmith-tidbit-xsspy.html -#How to Use: +# How to Use: http://fsecurify.com/xsspy-web-application-xss-scanner/ -#Installation: +# Installation: Type the following in the terminal. git clone https://github.com/faizann24/XssPy/ /opt/xsspy The tool works on Python 2.7 and you should have mechanize installed. If mechanize is not installed, type "pip install mechanize" in the terminal. -#Usage: +# Usage: python XssPy.py website.com (Do not write www.website.com OR http://www.website.com) -#Payloads +# Payloads If you have found a XSS vulnerability, you can try the following payloads. http://pastebin.com/J1hCfL9J -#Description: +# Description: XssPy is a python tool for finding Cross Site Scripting vulnerabilities in websites. This tool is the first of its kind. Instead of just checking one page as most of the tools do, this tool traverses the website and find all the links and subdomains first. After that, it starts scanning each and every input on each and every page that it found while its traversal. It uses small yet effective payloads to search for XSS vulnerabilities. The tool has been tested parallel with paid Vulnerability Scanners and most of the scanners failed to detect the vulnerabilities that the tool was able to find. Moreover, most paid tools scan only one site whereas XSSPY first finds a lot of subdomains and then scan all the links altogether. The tool comes with: @@ -37,7 +37,7 @@ The tool has been tested parallel with paid Vulnerability Scanners and most of t With this tool, Cross Site Scripting vulnerabilities have been found in the websites of MIT, Stanford, Duke University, Informatica, Formassembly, ActiveCompaign, Volcanicpixels, Oxford, Motorola, Berkeley and many more. -#NOTE: +# NOTE: Mail me if you encounter any errors (fsecurify@gmail.com). You can also post your problems on the website. I'll try my best to respond as soon as possible. Best Regards From c8f78eeddb537bf2e0d1c7b91f33998ff50fe5b0 Mon Sep 17 00:00:00 2001 From: Auriga Date: Sun, 31 Dec 2017 02:06:53 -0800 Subject: [PATCH 08/12] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a0c28d0..080784e 100644 --- a/README.md +++ b/README.md @@ -13,12 +13,12 @@ http://fsecurify.com/xsspy-web-application-xss-scanner/ # Installation: Type the following in the terminal. -git clone https://github.com/faizann24/XssPy/ /opt/xsspy +`git clone https://github.com/faizann24/XssPy/` /opt/xsspy The tool works on Python 2.7 and you should have mechanize installed. If mechanize is not installed, type "pip install mechanize" in the terminal. # Usage: -python XssPy.py website.com (Do not write www.website.com OR http://www.website.com) +`python XssPy.py website.com` (Do not write www.website.com OR http://www.website.com) # Payloads If you have found a XSS vulnerability, you can try the following payloads. From 404b6fb4f2d58a6ebb8a1054abf0374e8557a993 Mon Sep 17 00:00:00 2001 From: Lerie Taylor Date: Tue, 13 Mar 2018 08:37:21 -0700 Subject: [PATCH 09/12] Installation requirements --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 080784e..9d67809 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,9 @@ Type the following in the terminal. The tool works on Python 2.7 and you should have mechanize installed. If mechanize is not installed, type "pip install mechanize" in the terminal. +You will also need the mechanize distribution, you can install it with pip: +```pip install mechanize``` + # Usage: `python XssPy.py website.com` (Do not write www.website.com OR http://www.website.com) From 3d76a3675d9cef8fc862796bcbc488f281b75186 Mon Sep 17 00:00:00 2001 From: bannsec <7632864+bannsec@users.noreply.github.com> Date: Sun, 22 Jul 2018 13:29:20 -0400 Subject: [PATCH 10/12] Make this ./ runable --- XssPy.py | 1 + 1 file changed, 1 insertion(+) diff --git a/XssPy.py b/XssPy.py index 591c63f..05b16b9 100644 --- a/XssPy.py +++ b/XssPy.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python import mechanize import sys import httplib From cc573f6e61450244b6c260e4cc3203d4dba07cce Mon Sep 17 00:00:00 2001 From: Fabian Knorr Date: Fri, 9 Aug 2019 13:29:36 +0200 Subject: [PATCH 11/12] Enabled usage in Docker --- Dockerfile | 12 ++++++++++++ README.md | 13 +++++++++++++ requirements.txt | 4 ++++ 3 files changed, 29 insertions(+) create mode 100644 Dockerfile create mode 100644 requirements.txt diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..dab3d91 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,12 @@ +FROM python:2.7.16-alpine3.10 + +ENV WORKDIR /src +RUN mkdir -p ${WORKDIR} +WORKDIR ${WORKDIR} + +COPY ./requirements.txt ${WORKDIR}/requirements.txt +RUN pip install -r requirements.txt + +COPY ./ ${WORKDIR}/ + +ENTRYPOINT ["python", "XssPy.py"] diff --git a/README.md b/README.md index 9d67809..8b90538 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,19 @@ You will also need the mechanize distribution, you can install it with pip: # Usage: `python XssPy.py website.com` (Do not write www.website.com OR http://www.website.com) +# Docker +Advantage of Docker is that is will run on every machine. You don't need to install Pip packages or use a Venv. +Package versions are pinned. This ensures that XssPy will also run in the future. Regardless which Python-Version you've running on you machine. +## Docker build +``` +docker build -ti xsspy . +``` +## Docker usage +After you build +``` +docker run -ti xsspy website.com +``` + # Payloads If you have found a XSS vulnerability, you can try the following payloads. http://pastebin.com/J1hCfL9J diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..b35fdf4 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +html5lib==1.0.1 +mechanize==0.4.2 +six==1.12.0 +webencodings==0.5.1 From bc44e4fccb9f68cae582abe2a908717d9a7e756d Mon Sep 17 00:00:00 2001 From: AvivAvital2 <47418316+AvivAvital2@users.noreply.github.com> Date: Sun, 22 Sep 2019 14:27:12 +0300 Subject: [PATCH 12/12] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8b90538..085b439 100644 --- a/README.md +++ b/README.md @@ -28,12 +28,12 @@ Advantage of Docker is that is will run on every machine. You don't need to inst Package versions are pinned. This ensures that XssPy will also run in the future. Regardless which Python-Version you've running on you machine. ## Docker build ``` -docker build -ti xsspy . +docker build -t xsspy . ``` ## Docker usage After you build ``` -docker run -ti xsspy website.com +docker run -t xsspy -u website.com ``` # Payloads