diff --git a/astra.py b/astra.py index 90e7c49..42719a7 100644 --- a/astra.py +++ b/astra.py @@ -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 @@ -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: diff --git a/modules/security_headers_missing.py b/modules/security_headers_missing.py new file mode 100644 index 0000000..195612e --- /dev/null +++ b/modules/security_headers_missing.py @@ -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) + + diff --git a/utils/scan.property b/utils/scan.property index e8439ac..9c7eac0 100644 --- a/utils/scan.property +++ b/utils/scan.property @@ -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" } diff --git a/utils/vulnerabilities.py b/utils/vulnerabilities.py index 6a70448..6ca4f89 100644 --- a/utils/vulnerabilities.py +++ b/utils/vulnerabilities.py @@ -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 ' + }, + { + '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.' } + ] + + + +