Last active
July 23, 2023 16:32
-
-
Save ndavison/f17f235f866f618634ea81258ea7bccf to your computer and use it in GitHub Desktop.
Checks a URL for CORS header security posture
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import requests | |
from urllib.parse import urlparse | |
from argparse import ArgumentParser | |
parser = ArgumentParser(description="Checks a URL for CORS header security posture") | |
parser.add_argument("-u", "--url", help="the URL to check") | |
parser.add_argument("-o", "--origin", help="the origin to supply (defaults to the origin in the URL)") | |
parser.add_argument("-H", "--header", action="append", help="add a request header") | |
parser.add_argument("-v", "--verbose", action="store_true", help="More output") | |
args = parser.parse_args() | |
if not args.url: | |
print('Must supply a URL to check') | |
exit(1) | |
url = args.url | |
verbose = args.verbose | |
headers = args.header if args.header else [] | |
if args.origin: | |
origin = args.origin | |
else: | |
url_parsed = urlparse(url) | |
origin = '%s://zzz.%s' % (url_parsed.scheme, url_parsed.hostname) | |
if url_parsed.port: | |
origin = origin + ':%s' % (url_parsed.port) | |
if verbose: | |
print('Trying "%s"' % (url)) | |
request_headers = {} | |
for header in headers: | |
request_headers[header.split(':')[0]] = header.split(':')[1].strip() | |
request_headers['Origin'] = origin | |
if verbose: | |
print('Headers: %s' % (request_headers)) | |
r = requests.get(url, headers=request_headers) | |
cors_allow_origin = r.headers.get('access-control-allow-origin', None) | |
cors_allow_auth = r.headers.get('access-control-allow-credentials', False) | |
if not cors_allow_origin: | |
print('No CORS headers in response') | |
exit(1) | |
results = { | |
'origin_reflected': False, | |
'origin_wildcard': False, | |
'authenticated': False | |
} | |
if cors_allow_origin == origin: | |
if verbose: | |
print('Origin in request was the same as Access-Control-Allow-Origin in response') | |
results['origin_reflected'] = True | |
if cors_allow_origin == '*': | |
if verbose: | |
print('Access-Control-Allow-Origin allows all origins') | |
results['origin_wildcard'] = True | |
results['authenticated'] = cors_allow_auth | |
if verbose: | |
print('Authentication is allowed' if cors_allow_auth else 'Authentication is NOT allowed') | |
print('url: %s\tresponse: %s\torigin: %s\treflected: %s\tauthenticated: %s\twildcard: %s' % (url, r.status_code, origin, 'YES' if results['origin_reflected'] else 'NO', 'YES' if results['authenticated'] else 'NO', 'YES' if results['origin_wildcard'] else 'NO')) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment