Add files via upload
This commit is contained in:
21
core/colors.py
Normal file
21
core/colors.py
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import sys
|
||||||
|
|
||||||
|
colors = True # Output should be colored
|
||||||
|
machine = sys.platform # Detecting the os of current system
|
||||||
|
if machine.lower().startswith(('os', 'win', 'darwin', 'ios')):
|
||||||
|
colors = False # Colors shouldn't be displayed in mac & windows
|
||||||
|
if not colors:
|
||||||
|
end = red = white = green = yellow = grey = run = bad = good = info = que = ''
|
||||||
|
else:
|
||||||
|
grey = '\033[37m'
|
||||||
|
white = '\033[97m'
|
||||||
|
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'
|
||||||
16
core/requester.py
Normal file
16
core/requester.py
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import requests
|
||||||
|
|
||||||
|
headers = {
|
||||||
|
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:70.0) Gecko/20100101 Firefox/70.0',
|
||||||
|
'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',
|
||||||
|
'DNT': '1',
|
||||||
|
'Connection': 'close',
|
||||||
|
}
|
||||||
|
|
||||||
|
def requester(url, scheme, origin):
|
||||||
|
headers['Origin'] = scheme + origin
|
||||||
|
response = requests.get(url, headers).headers
|
||||||
|
if 'Access-Control-Allow-Origin' in response:
|
||||||
|
return response['Access-Control-Allow-Origin']
|
||||||
51
core/tests.py
Normal file
51
core/tests.py
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
import time
|
||||||
|
|
||||||
|
from core.utils import host
|
||||||
|
from core.requester import requester
|
||||||
|
|
||||||
|
def passive_tests(url, acao_header):
|
||||||
|
root = host(url)
|
||||||
|
if root:
|
||||||
|
if root != host(acao_header):
|
||||||
|
return 'Third party allowed'
|
||||||
|
elif url.startswith('http://'):
|
||||||
|
return 'HTTP origin allowed'
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
elif acao_header == '*':
|
||||||
|
return 'Wildcard value'
|
||||||
|
else:
|
||||||
|
return 'Invalid value'
|
||||||
|
|
||||||
|
def active_tests(url, root, scheme, delay):
|
||||||
|
acao_header = requester(url, scheme, 'example.com')
|
||||||
|
if acao_header:
|
||||||
|
if acao_header == (scheme + 'example.com'):
|
||||||
|
return 'Origin reflected'
|
||||||
|
time.sleep(delay)
|
||||||
|
acao_header = requester(url, scheme, root + '.example.com')
|
||||||
|
if acao_header:
|
||||||
|
if acao_header == (scheme + root + '.example.com'):
|
||||||
|
return 'Post domain wildcard'
|
||||||
|
time.sleep(delay)
|
||||||
|
acao_header = requester(url, scheme, 'd3v' + root)
|
||||||
|
if acao_header:
|
||||||
|
if acao_header == (scheme + 'd3v' + root):
|
||||||
|
return 'Pre domain wildcard'
|
||||||
|
time.sleep(delay)
|
||||||
|
acao_header = requester(url, '', 'null')
|
||||||
|
if acao_header:
|
||||||
|
if acao_header == 'null':
|
||||||
|
return 'Null origin allowed'
|
||||||
|
time.sleep(delay)
|
||||||
|
acao_header = requester(url, scheme, root + '%60.example.com')
|
||||||
|
if acao_header:
|
||||||
|
if '`.example.com' in acao_header:
|
||||||
|
return 'Broken parser'
|
||||||
|
time.sleep(delay)
|
||||||
|
acao_header = requester(url, 'http', root)
|
||||||
|
if acao_header:
|
||||||
|
if acao_header.startswith('http://'):
|
||||||
|
return 'HTTP origin allowed'
|
||||||
|
else:
|
||||||
|
return passive_tests(url, acao_header)
|
||||||
17
core/utils.py
Normal file
17
core/utils.py
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import tld
|
||||||
|
import json
|
||||||
|
|
||||||
|
def load_file(path):
|
||||||
|
with open(path, 'r') as f:
|
||||||
|
result = [line.rstrip('\n').encode('utf-8').decode('utf-8') for line in f]
|
||||||
|
return '\n'.join(result)
|
||||||
|
|
||||||
|
def host(string):
|
||||||
|
if string and '*' not in string:
|
||||||
|
try:
|
||||||
|
return tld.get_fld(string, fix_protocol=True)
|
||||||
|
except:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def load_json(file):
|
||||||
|
return json.loads(load_file('./db/details.json'))
|
||||||
52
corsy.py
Normal file
52
corsy.py
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
import argparse
|
||||||
|
|
||||||
|
from core.utils import load_json, host
|
||||||
|
from core.tests import active_tests
|
||||||
|
from core.colors import white, green, info, bad, good, grey, end
|
||||||
|
|
||||||
|
try:
|
||||||
|
from urllib.parse import urlparse
|
||||||
|
except ImportError:
|
||||||
|
from urlparse import urlparse
|
||||||
|
|
||||||
|
print('''
|
||||||
|
%sCORSY %s{%sv0.1-beta%s}%s
|
||||||
|
''' % (green, white, grey, white, end))
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument('-u', help='target url', dest='url')
|
||||||
|
parser.add_argument('-d', help='request delay', dest='delay', type=float, default=0)
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
target_url = args.url
|
||||||
|
delay = args.delay
|
||||||
|
|
||||||
|
def cors(target, delay, scheme=False):
|
||||||
|
url = target
|
||||||
|
if not target.startswith(('http://', 'https://')):
|
||||||
|
url = scheme + '://' + url
|
||||||
|
root = host(url)
|
||||||
|
parsed = urlparse(url)
|
||||||
|
netloc = parsed.netloc
|
||||||
|
scheme = parsed.scheme
|
||||||
|
url = scheme + '://' + netloc
|
||||||
|
active = active_tests(url, root, scheme, delay)
|
||||||
|
return active
|
||||||
|
|
||||||
|
details = load_json('./db/details.json')
|
||||||
|
|
||||||
|
if target_url:
|
||||||
|
if target_url.startswith(('http://', 'https://')):
|
||||||
|
result = cors(target_url, delay)
|
||||||
|
if result:
|
||||||
|
print('%s Misconfiguration found!' % good)
|
||||||
|
print('%s Title: %s' % (info, result))
|
||||||
|
print('%s Description: %s' % (info, details[result.lower()]['Description']))
|
||||||
|
print('%s Severity: %s' % (info, details[result.lower()]['Severity']))
|
||||||
|
print('%s Exploitation: %s' % (info, details[result.lower()]['Exploitation']))
|
||||||
|
else:
|
||||||
|
print('%s No misconfiguration found.' % bad)
|
||||||
|
else:
|
||||||
|
print('%s Please use https://example.com not example.com' % bad)
|
||||||
|
else:
|
||||||
|
print('\n' + parser.format_help().lower())
|
||||||
48
db/details.json
Normal file
48
db/details.json
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
{
|
||||||
|
"wildcard value" : {
|
||||||
|
"Description" : "This host allows requests made from any origin. However, browsers will block all requests to this host by default.",
|
||||||
|
"Severity" : "Low",
|
||||||
|
"Exploitation" : "Not possible"
|
||||||
|
},
|
||||||
|
"third party allowed" : {
|
||||||
|
"Description" : "This host has whitelisted a third party host for cross origin requests.",
|
||||||
|
"Severity" : "Medium",
|
||||||
|
"Exploitation" : "If the whitelisted host is a code hosting platform such as codepen.io or has an XSS vulnerbaility, it can be used to exploit this misconfiguration."
|
||||||
|
|
||||||
|
},
|
||||||
|
"origin reflected" : {
|
||||||
|
"Description" : "This host allows any origin to make requests to it.",
|
||||||
|
"Severity" : "High",
|
||||||
|
"Exploitation" : "Make requests from any domain you control."
|
||||||
|
},
|
||||||
|
"invalid value" : {
|
||||||
|
"Description" : "Header's value is invalid, this CORS implementation doesn't work at all.",
|
||||||
|
"Severity" : "Low",
|
||||||
|
"Exploitation" : "Not possible"
|
||||||
|
},
|
||||||
|
"post domain wildcard" : {
|
||||||
|
"Description" : "The origin verification is flawed, it allows requests from a host that has this host as as preffix.",
|
||||||
|
"Severity" : "High",
|
||||||
|
"Exploitation" : "Make requests from target.com.attacker.com"
|
||||||
|
},
|
||||||
|
"pre domain wildcard" : {
|
||||||
|
"Description" : "The origin verification is flawed, it allows requests from a host that has this host as as suffix.",
|
||||||
|
"Severity" : "High",
|
||||||
|
"Exploitation" : "Make requests from attacker-target.com"
|
||||||
|
},
|
||||||
|
"null origin allowed" : {
|
||||||
|
"Description" : "This host allows requests from 'null' origin.",
|
||||||
|
"Severity" : "High",
|
||||||
|
"Exploitation" : "Make requests from a sanboxed iframe."
|
||||||
|
},
|
||||||
|
"http origin allowed" : {
|
||||||
|
"Description" : "This host allows sharing resources over an unencrypted (HTTP) connection.",
|
||||||
|
"Severity" : "Low",
|
||||||
|
"Exploitation" : "Sniff requests made over the unencrypted channel."
|
||||||
|
},
|
||||||
|
"broken parser" : {
|
||||||
|
"Description" : "The origin verification is flawed and can be bypassed using a backtick (`).",
|
||||||
|
"Severity" : "High",
|
||||||
|
"Exploitation" : "Set the 'Origin' header to %60.example.com"
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user