Skip to content

Commit

Permalink
Feature: Greatly improved OWASP compliance checks
Browse files Browse the repository at this point in the history
  • Loading branch information
rfc-st committed Dec 21, 2024
1 parent 7f1ae4c commit 012b1e6
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 58 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<a target="_blank" href="https://www.python.org/downloads/" title="Minimum Python version required to run this tool"><img src="https://img.shields.io/badge/Python-%3E%3D3.8-blue?labelColor=343b41"></a>
<a target="_blank" href="LICENSE" title="License of this tool"><img src="https://img.shields.io/badge/License-MIT-blue.svg?labelColor=343b41"></a>
<a target="_blank" href="https://github.com/rfc-st/humble/releases" title="Latest release of this tool"><img src="https://img.shields.io/github/v/release/rfc-st/humble?display_name=release&label=Latest%20Release&labelColor=343b41"></a>
<a target="_blank" href="https://github.com/rfc-st/humble/commits/master" title="Latest commit of this tool"><img src="https://img.shields.io/badge/Latest_Commit-2024--12--20-blue.svg?labelColor=343b41"></a>
<a target="_blank" href="https://github.com/rfc-st/humble/commits/master" title="Latest commit of this tool"><img src="https://img.shields.io/badge/Latest_Commit-2024--12--21-blue.svg?labelColor=343b41"></a>
<a target="_blank" href="https://github.com/rfc-st/humble/actions?query=workflow%3ACodeQL" title="Results of the last analysis of this tool with CodeQL"><img src="https://github.com/rfc-st/humble/workflows/CodeQL/badge.svg"></a>
<a target="_blank" href="https://pkg.kali.org/pkg/humble" title="Official tool in Kali Linux"><img src="https://img.shields.io/badge/Kali%20Linux-Tool-blue?labelColor=343b41"></a>
<br />
Expand Down Expand Up @@ -58,7 +58,7 @@
:heavy_check_mark: 14 [checks](#checks-missing-headers) for missing security-related HTTP response headers (the ones I consider essential).<br />
:heavy_check_mark: 1186 [checks](#checks-fingerprint-headers) for fingerprinting through HTTP response headers.<br />
:heavy_check_mark: 128 [checks](#checks-deprecated-headersprotocols-and-insecure-values) for deprecated HTTP response headers/protocols or with insecure/wrong values.<br />
:heavy_check_mark: Checks compliance with <a href="https://owasp.org/www-project-secure-headers/#div-bestpractices" target="_blank">OWASP<a> 'Secure Headers Project' Best Practices.<br />
:heavy_check_mark: Checks compliance with OWASP <a href="https://owasp.org/www-project-secure-headers/#div-bestpractices" target="_blank">'Secure Headers Project'<a> Best Practices.<br />
:heavy_check_mark: SSL/TLS checks: requires the **amazing** https://testssl.sh/.<br />
:heavy_check_mark: Browser support references for enabled HTTP security headers: provided by https://caniuse.com/.<br />
:heavy_check_mark: Two types of analysis: brief and detailed, along with HTTP response headers.<br />
Expand Down
86 changes: 37 additions & 49 deletions humble.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@
URL_STRING = ('rfc-st', ' URL : ', 'caniuse')

current_time = datetime.now().strftime("%Y/%m/%d - %H:%M:%S")
local_version = datetime.strptime('2024-12-20', '%Y-%m-%d').date()
local_version = datetime.strptime('2024-12-21', '%Y-%m-%d').date()


class SSLContextAdapter(requests.adapters.HTTPAdapter):
Expand Down Expand Up @@ -1472,56 +1472,44 @@ def extract_compliance_headers(tmp_filename):


def extract_compliance_values(enabled_headers):
check_cache = enabled_headers.get('cache-control', '')
check_clear = enabled_headers.get('clear-site-data', '')
check_csp = enabled_headers.get('content-security-policy', '')
check_coep = enabled_headers.get('cross-origin-embedder-policy', '')
check_coop = enabled_headers.get('cross-origin-opener-policy', '')
check_corp = enabled_headers.get('cross-origin-resource-policy', '')
check_perm = enabled_headers.get('(*) permissions-policy', '')
check_ref = enabled_headers.get('referrer-policy', '')
check_sts = enabled_headers.get('strict-transport-security', '')
check_xcto = enabled_headers.get('x-content-type-options', '')
check_xfo = enabled_headers.get('x-frame-options', '')
check_xpcd = enabled_headers.get('x-permitted-cross-domain-policies', '')
check_compliance_owasp(check_cache, check_clear, check_csp, check_coep,
check_coop, check_corp, check_perm, check_ref,
check_sts, check_xcto, check_xfo, check_xpcd)


# Ashamed of this code... I promise to improve it!.
def check_compliance_owasp(check_cache, check_clear, check_csp, check_coep,
check_coop, check_corp, check_perm, check_ref,
check_sts, check_xcto, check_xfo, check_xpcd):
c_cnt = 0
if not check_cache or any(elem not in check_cache for elem in t_ocache):
c_cnt += 1
if not check_clear or any(elem not in check_clear for elem in t_oclear):
c_cnt += 1
if not check_csp or any(elem not in check_csp for elem in t_ocsp):
c_cnt += 1
if not check_coep or any(elem not in check_coep for elem in t_ocoep):
c_cnt += 1
if not check_coop or any(elem not in check_coop for elem in t_ocoop):
c_cnt += 1
if not check_corp or any(elem not in check_corp for elem in t_ocorp):
c_cnt += 1
if not check_perm or any(elem not in check_perm for elem in t_operm):
c_cnt += 1
if not check_ref or any(elem not in check_ref for elem in t_oref):
c_cnt += 1
if not check_sts or any(elem not in check_sts for elem in t_osts):
c_cnt += 1
if not check_xcto or any(elem not in check_xcto for elem in t_oxcto):
c_cnt += 1
if not check_xfo or any(elem not in check_xfo for elem in t_oxfo):
c_cnt += 1
if not check_xpcd or any(elem not in check_xpcd for elem in t_oxpcd):
c_cnt += 1
if c_cnt > 0:
header_keys = ['cache-control', 'clear-site-data',
'content-security-policy', 'cross-origin-embedder-policy',
'cross-origin-opener-policy',
'cross-origin-resource-policy', '(*) permissions-policy',
'referrer-policy', 'strict-transport-security',
'x-content-type-options', 'x-frame-options',
'x-permitted-cross-domain-policies',]

header_val = [enabled_headers.get(key, '') for key in header_keys]
compliance_val = [t_ocache, t_oclear, t_ocsp, t_ocoep, t_ocoop, t_ocorp,
t_operm, t_oref, t_osts, t_oxcto, t_oxfo, t_oxpcd,]

check_compliance_owasp(header_keys, header_val, compliance_val)


def check_compliance_owasp(header_keys, header_val, compliance_val):
non_cnt = 0
non_rules = []

for key, value, rules in zip(header_keys, header_val, compliance_val):
if not value or any(elem not in value for elem in rules):
non_cnt += 1
header_v = value or get_detail('[comp_header]')
non_rules.append(f"{STYLE[2]}{key.title()}{STYLE[5]}: {header_v}")

print_compliance_owasp(non_cnt, non_rules)


def print_compliance_owasp(non_cnt, non_rules):
if non_cnt > 0:
print("")
print_detail('[ko_owasp]', num_lines=2)
print_detail('[comp_ko_owasp]', num_lines=2)
for rule in non_rules:
print(f" {rule}")
print("")
print_detail('[comp_experimental]', 2)
else:
print_detail('[comp_ok_owasp]', num_lines=2)


def analyze_input_file(input_file):
Expand Down
17 changes: 14 additions & 3 deletions l10n/details.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1642,6 +1642,17 @@ Unhandled exception type:
'(*)' meaning: Experimental HTTP response header
'(*)' ref: https://mdn.io/Experimental_deprecated_obsolete

[ko_owasp]
The HTTP response headers do *not* comply with OWASP 'Secure Headers Project' Best Practices.
Ref: https://owasp.org/www-project-secure-headers/#div-bestpractices
[comp_ko_owasp]
The following HTTP response headers do not comply with the OWASP 'Secure Headers Project' best practices.
Ref: https://owasp.org/www-project-secure-headers/#div-bestpractices

[comp_ok_owasp]
The HTTP response headers comply with the OWASP 'Secure Headers Project' best practices.
Ref: https://owasp.org/www-project-secure-headers/#div-bestpractices

[comp_experimental]
'(*)' meaning: Experimental HTTP response header
'(*)' ref: https://mdn.io/Experimental_deprecated_obsolete

[comp_header]
(Header not enabled)
19 changes: 15 additions & 4 deletions l10n/details_es.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1630,8 +1630,19 @@ Excepción no gestionada:

[experimental_header]
Significado de '(*)': Cabecera de respuesta HTTP experimental
'(*)' ref: https://mdn.io/Experimental_deprecated_obsolete
Referencia de '(*)': https://mdn.io/Experimental_deprecated_obsolete

[ko_owasp]
Las cabeceras HTTP de respuesta *no* cumplen con las buenas prácticas de OWASP 'Secure Headers Project'.
Ref: https://owasp.org/www-project-secure-headers/#div-bestpractices
[comp_ko_owasp]
Las siguientes cabeceras de respuesta HTTP no cumplen con las mejores prácticas de OWASP 'Secure Headers Project'.
Ref: https://owasp.org/www-project-secure-headers/#div-bestpractices

[comp_ok_owasp]
Las cabeceras de respuesta HTTP cumplen con las mejores prácticas de OWASP 'Secure Headers Project'.
Ref: https://owasp.org/www-project-secure-headers/#div-bestpractices

[comp_experimental]
Significado de '(*)': Cabecera de respuesta HTTP experimental
Referencia de '(*)': https://mdn.io/Experimental_deprecated_obsolete

[comp_header]
(Cabecera no habilitada)

0 comments on commit 012b1e6

Please sign in to comment.