Skip to content

Instantly share code, notes, and snippets.

@ndavison
Last active July 23, 2023 16:32
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save ndavison/f17f235f866f618634ea81258ea7bccf to your computer and use it in GitHub Desktop.
Save ndavison/f17f235f866f618634ea81258ea7bccf to your computer and use it in GitHub Desktop.
Checks a URL for CORS header security posture
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