Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added security-headers-missing module that checks for various security headers. #78

Merged
merged 1 commit into from
Dec 5, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions astra.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
from modules.redirect import open_redirect_check
from modules.xxe import xxe_scan
from modules.crlf import crlf_check
from modules.security_headers_missing import security_headers_missing
from core.zap_config import zap_start
from multiprocessing import Process
from utils.db import Database_update
Expand Down Expand Up @@ -194,8 +195,10 @@ def modules_scan(url,method,headers,body,scanid=None):
update_scan_status(scanid, "xxe")
if attack['crlf'] == 'Y' or attack['crlf'] == 'y':
handleException(lambda: crlf_check(url,method,headers,body,scanid), "CRLF")
update_scan_status(scanid, "crlf")

update_scan_status(scanid, "crlf")
if attack['security_headers'] == 'Y' or attack['security_headers'] == 'y':
handleException(lambda: security_headers_missing(url,method,headers,body,scanid), "security_headers")
update_scan_status(scanid, "security_headers")

def handleException(method, module_name):
try:
Expand Down
83 changes: 83 additions & 0 deletions modules/security_headers_missing.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import re

from utils.logger import logger
from utils.db import Database_update
import sendrequest as req


dbupdate = Database_update()
api_logger = logger()

def csp_check(url, method, req_headers, req_body, scan_id, res_headers, res_body):
# checks if csp header is implemented
if 'Content-Security-Policy' not in res_headers:
attack_result = { "id" : 15, "scanid" : scan_id, "url" : url, "alert": "CSP Header Missing", "impact": "Low", "req_headers": req_headers, "req_body": req_body, "res_headers": res_headers ,"res_body": res_body}
dbupdate.insert_record(attack_result)

def xss_protection_check(url, method, req_headers, req_body, scan_id, res_headers, res_body):
# checks if xss-protection is enabled and configured correctly
if 'X-XSS-Protection' not in res_headers:
attack_result = { "id" : 16, "scanid" : scan_id, "url" : url, "alert": "X-XSS-Protection Header Missing", "impact": "Low", "req_headers": req_headers, "req_body": req_body, "res_headers": res_headers ,"res_body": res_body}
dbupdate.insert_record(attack_result)
else:
xss_protection = res_headers['X-XSS-Protection']
xss_protection = str(xss_protection.replace(" ", "")) # remove space
if xss_protection == "0":
attack_result = { "id" : 17, "scanid" : scan_id, "url" : url, "alert": "X-XSS-Protection Header Disabled", "impact": "Low", "req_headers": req_headers, "req_body": req_body, "res_headers": res_headers ,"res_body": res_body}
dbupdate.insert_record(attack_result)
elif xss_protection != "1;mode=block":
attack_result = { "id" : 18, "scanid" : scan_id, "url" : url, "alert": "X-XSS-Protection Header not securly implemented", "impact": "Low", "req_headers": req_headers, "req_body": req_body, "res_headers": res_headers ,"res_body": res_body}
dbupdate.insert_record(attack_result)

def x_frame_options_check(url, method, req_headers, req_body, scan_id, res_headers, res_body):
# check if X-Frame-Options header is present
if 'X-Frame-Options' not in res_headers:
attack_result = { "id" : 19, "scanid" : scan_id, "url" : url, "alert": "X-Frame-Options Header Missing", "impact": "Low", "req_headers": req_headers, "req_body": req_body, "res_headers": res_headers ,"res_body": res_body}
dbupdate.insert_record(attack_result)

def x_content_type_options_check(url, method, req_headers, req_body, scan_id, res_headers, res_body):
# check if Content-Type-Options header is present
if 'X-Content-Type-Options' not in res_headers:
attack_result = { "id" : 20, "scanid" : scan_id, "url" : url, "alert": "X-Content-Type-Options Header Missing", "impact": "Low", "req_headers": req_headers, "req_body": req_body, "res_headers": res_headers ,"res_body": res_body}
dbupdate.insert_record(attack_result)

def hsts_check(url, method, req_headers, req_body, scan_id, res_headers, res_body):
# check if Strict-Transport-Security header is present
if 'Strict-Transport-Security' not in res_headers:
attack_result = { "id" : 21, "scanid" : scan_id, "url" : url, "alert": "Strict-Transport-Security Header Missing", "impact": "Low", "req_headers": req_headers, "req_body": req_body, "res_headers": res_headers ,"res_body": res_body}
dbupdate.insert_record(attack_result)

def cookies_check(cookies, url, method, req_headers, req_body, scan_id, res_headers, res_body):
# check if cookies are marked secure and httponly
for cookie in cookies:
if not cookie.secure or not cookie.has_nonstandard_attr('HttpOnly'):
attack_result = { "id" : 22, "scanid" : scan_id, "url" : url, "alert": "Cookie not marked secure or httponly", "impact": "Low", "req_headers": req_headers, "req_body": req_body, "res_headers": res_headers ,"res_body": res_body}
dbupdate.insert_record(attack_result)
break

def check_version_disclosure(url, method, req_headers, req_body, scan_id, res_headers, res_body):
# check if any of the headers in the list discloses version information
version_headers = ["Server", "X-Powered-By", "X-AspNet-Version"]
for each_version_header in version_headers:
if each_version_header in res_headers:
header_value = res_headers[each_version_header]
if bool(re.search('\d', header_value)): #checks if the header has any digit.
attack_result = { "id" : 23, "scanid" : scan_id, "url" : url, "alert": "Server Version Disclosure", "impact": "Low", "req_headers": req_headers, "req_body": req_body, "res_headers": res_headers ,"res_body": res_body}
dbupdate.insert_record(attack_result)
break

def security_headers_missing(url, method, headers, body, scan_id=None):
# checks if a security header is missing
resp = req.api_request(url, method, headers, body)
res_headers = resp.headers
res_body = resp.text
cookies = resp.cookies
csp_check(url, method, headers, body, scan_id, res_headers, res_body)
xss_protection_check(url, method, headers, body, scan_id, res_headers, res_body)
x_frame_options_check(url, method, headers, body, scan_id, res_headers, res_body)
x_content_type_options_check(url, method, headers, body, scan_id, res_headers, res_body)
hsts_check(url, method, headers, body, scan_id, res_headers, res_body)
cookies_check(cookies, url, method, headers, body, scan_id, res_headers, res_body)
check_version_disclosure(url, method, headers, body, scan_id, res_headers, res_body)


9 changes: 5 additions & 4 deletions utils/scan.property
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
[scan-policy]
attack = {
"cors" : "y",
"Broken auth" : "y",
"cors" : "n",
"Broken auth" : "n",
"Rate limit" : "y",
"csrf" : 'y',
"zap" : 'n',
"zap" : 'y',
"jwt" : 'y',
"sqli" : 'y',
"xss" : 'y',
"open-redirection" : "y",
"xxe" : "y",
"crlf" : "y"
"crlf" : "y",
"security_headers": "y"
}


Expand Down
59 changes: 59 additions & 0 deletions utils/vulnerabilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,5 +86,64 @@
'name': 'XML External Entity Attack',
'Description': 'An XML External Entity attack is a type of attack against an application that parses XML input. This attack occurs when XML input containing a reference to an external entity is processed by a weakly configured XML parser. This attack may lead to the disclosure of confidential data, denial of service, server side request forgery, port scanning from the perspective of the machine where the parser is located, and other system impacts.',
'remediation': 'The XML processor should be configured to use a local static DTD and disallow any declared DTD included in the XML document.'
},
{
'id': 15,
'name': 'Security Headers Missing',
'Description': ' ',
'remediation': 'Implement proper CSP header.'
},
{
'id': 16,
'name': 'X-XSS-Protection Header Missing',
'Description': 'The HTTP X-XSS-Protection response header is a feature of Internet Explorer, Chrome and Safari that stops pages from loading when they detect reflected cross-site scripting (XSS) attacks.',
'remediation': 'Implement X-XSS-Protection: 1; mode=block.'
},
{
'id': 17,
'name': 'X-XSS-Protection Header disabled',
'Description': 'The HTTP X-XSS-Protection response header is a feature of Internet Explorer, Chrome and Safari that stops pages from loading when they detect reflected cross-site scripting (XSS) attacks',
'remediation': 'X-XSS-Protection is Disabled. Implement X-XSS-Protection: 1; mode=block '
},
{
'id': 18,
'name': 'X-XSS-Protection Header not securly implemented',
'Description': 'The HTTP X-XSS-Protection response header is a feature of Internet Explorer, Chrome and Safari that stops pages from loading when they detect reflected cross-site scripting (XSS) attacks.',
'remediation': 'Implement X-XSS-Protection: 1; mode=block.'
},
{
'id': 19,
'name': 'X-Frame-Options Header Missing',
'Description': 'The X-Frame-Options HTTP response header can be used to indicate whether or not a browser should be allowed to render a page in a <frame>, <iframe> or <object>',
'remediation': 'Set X-Frame-Options header to deny, sameorigin or allow-from <domain>'
},
{
'id': 20,
'name': 'X-Content-Type-Options Header Missing',
'Description': 'The X-Content-Type-Options response HTTP header is a marker used by the server to indicate that the MIME types advertised in the Content-Type headers should not be changed and be followed.',
'remediation': 'Implement X-Content-Type-Options: nosniff'
},
{
'id': 21,
'name': 'Strict-Transport-Security Header Missing',
'Description': 'The X-Content-Type-Options response HTTP header is a marker used by the server to indicate that the MIME types advertised in the Content-Type headers should not be changed and be followed.',
'remediation': 'Implement X-Content-Type-Options: nosniff'
},
{
'id': 22,
'name': 'Cookie not marked secure or httponly',
'Description': 'The secure flag is an option that can be set by the application server when sending a new cookie to the user within an HTTP Response. The purpose of the secure flag is to prevent cookies from being observed by unauthorized parties due to the transmission of a the cookie in clear text. Using the HttpOnly flag when generating a cookie helps mitigate the risk of client side script accessing the protected cookie.',
'remediation': 'Cookie should be marked secure and httponly.'
},
{
'id': 23,
'name': 'Version disclosed in response header',
'Description': "Some of these headers, 'Server', 'X-Powered-By', 'X-AspNet-Version' are revealing server version number.",
'remediation': 'Configure these headers to give out generic server name in response.'
}

]