def test_retrieve_csp_policies_with_policies_case04(self): """ Test case in which 4 policies are specified using 4 differents CSP headers and in which 1 is specified using report only CSP header. Test in which we want only mandatory policies. """ hrds = {} hrds[CSP_HEADER_W3C] = CSP_DIRECTIVE_OBJECT + " 'none'" hrds[CSP_HEADER_FIREFOX] = CSP_DIRECTIVE_IMAGE + " *" hrds[CSP_HEADER_CHROME] = CSP_DIRECTIVE_CONNECTION + \ " trust.sample.com" hrds[CSP_HEADER_W3C_REPORT_ONLY] = CSP_DIRECTIVE_SCRIPT + \ " report.sample.com" csp_headers = Headers(hrds.items()) http_response = HTTPResponse(200, '', csp_headers, self.url, self.url) policies = retrieve_csp_policies(http_response) self.assertEqual(len(policies), 3) self.assertEqual(len(policies[CSP_DIRECTIVE_OBJECT]), 1) self.assertEqual(policies[CSP_DIRECTIVE_OBJECT][0], "none") self.assertEqual(len(policies[CSP_DIRECTIVE_IMAGE]), 1) self.assertEqual(policies[CSP_DIRECTIVE_IMAGE][0], "*") self.assertEqual(len(policies[CSP_DIRECTIVE_CONNECTION]), 1) self.assertEqual( policies[CSP_DIRECTIVE_CONNECTION][0], "trust.sample.com")
def test_retrieve_csp_policies_without_policies(self): """ Test case in which no policies are specified into HTTP response. """ hrds = {}.items() csp_headers = Headers(hrds) http_response = HTTPResponse(200, '', csp_headers, self.url, self.url) policies = retrieve_csp_policies(http_response) self.assertEqual(len(policies), 0)
def test_retrieve_csp_policies_with_special_policies_case01(self): """ Test case in which 2 policies are specified using special directives with empty value. """ header_value = "sandbox ; script-nonce " hrds = {CSP_HEADER_W3C: header_value}.items() csp_headers = Headers(hrds) http_response = HTTPResponse(200, '', csp_headers, self.url, self.url) policies = retrieve_csp_policies(http_response) self.assertEqual(len(policies), 2) self.assertEqual(len(policies[CSP_DIRECTIVE_SANDBOX]), 1) self.assertEqual(policies[CSP_DIRECTIVE_SANDBOX][0], "") self.assertEqual(len(policies[CSP_DIRECTIVE_SCRIPT_NONCE]), 1) self.assertEqual(policies[CSP_DIRECTIVE_SCRIPT_NONCE][0], "")
def _is_protected_with_csp(self, request, response): """ Check if the HTTP response has a CSP header, parse it, extract the frame-ancestors attribute and check it is secure. :param request: HTTP request :param response: HTTP response :return: True if the response is protected """ # These are the policies that will be enforced by the browser non_report_only_policies = retrieve_csp_policies(response, False, True) frame_ancestors = non_report_only_policies.get('frame-ancestors', []) # # This is the strictest policy, nobody can frame me! # # Content-Security-Policy: frame-ancestors 'none'; # for policy in frame_ancestors: if policy.lower() == 'none': return True # # Fail when the frame-ancestors has insecure wildcards # # Content-Security-Policy: frame-ancestors '*'; # Content-Security-Policy: frame-ancestors 'https://*'; # insecure_ancestors = ('*', 'http', 'https', 'http://', 'https://', 'http://*', 'https://*') for policy in frame_ancestors: if policy.lower() in insecure_ancestors: return False # Content-Security-Policy: frame-ancestors 'self'; if 'self' in frame_ancestors: return True # Content-Security-Policy: frame-ancestors 'foo.com' '*.somesite.com'; if len(frame_ancestors): return True return False
def test_retrieve_csp_policies_with_special_policies_case02(self): """ Test case in which 2 policies are specified using special directives with explicit values. """ header_value = "sandbox allow-forms allow-scripts ;"\ " script-nonce AABBCCDDEE" hrds = {CSP_HEADER_W3C: header_value}.items() csp_headers = Headers(hrds) http_response = HTTPResponse(200, '', csp_headers, self.url, self.url) policies = retrieve_csp_policies(http_response) self.assertEqual(len(policies), 2) self.assertEqual(len(policies[CSP_DIRECTIVE_SANDBOX]), 2) self.assertTrue("allow-forms" in policies[CSP_DIRECTIVE_SANDBOX]) self.assertTrue("allow-scripts" in policies[CSP_DIRECTIVE_SANDBOX]) self.assertEqual(len(policies[CSP_DIRECTIVE_SCRIPT_NONCE]), 1) self.assertEqual(policies[CSP_DIRECTIVE_SCRIPT_NONCE][0], "AABBCCDDEE")
def test_retrieve_csp_policies_with_policies_case01(self): """ Test case in which 1 same policy is specified using 3 differents CSP headers. """ hrds = {} hrds[CSP_HEADER_W3C] = CSP_DIRECTIVE_OBJECT + " 'self'" hrds[CSP_HEADER_FIREFOX] = CSP_DIRECTIVE_OBJECT + " *" hrds[CSP_HEADER_CHROME] = CSP_DIRECTIVE_OBJECT + " *.sample.com" csp_headers = Headers(hrds.items()) http_response = HTTPResponse(200, '', csp_headers, self.url, self.url) policies = retrieve_csp_policies(http_response) self.assertEqual(len(policies), 1) self.assertEqual(len(policies[CSP_DIRECTIVE_OBJECT]), 3) self.assertTrue("self" in policies[CSP_DIRECTIVE_OBJECT]) self.assertTrue("*" in policies[CSP_DIRECTIVE_OBJECT]) self.assertTrue("*.sample.com" in policies[CSP_DIRECTIVE_OBJECT])
def test_retrieve_csp_policies_with_policies_case03(self): """ Test case in which 3 policies are specified using 3 differents CSP headers. """ hrds = {} hrds[CSP_HEADER_W3C] = CSP_DIRECTIVE_OBJECT + " 'none'" hrds[CSP_HEADER_FIREFOX] = CSP_DIRECTIVE_IMAGE + " *" hrds[CSP_HEADER_CHROME] = CSP_DIRECTIVE_CONNECTION + \ " trust.sample.com" csp_headers = Headers(hrds.items()) http_response = HTTPResponse(200, '', csp_headers, self.url, self.url) policies = retrieve_csp_policies(http_response) self.assertEqual(len(policies), 3) self.assertEqual(len(policies[CSP_DIRECTIVE_OBJECT]), 1) self.assertEqual(policies[CSP_DIRECTIVE_OBJECT][0], "none") self.assertEqual(len(policies[CSP_DIRECTIVE_IMAGE]), 1) self.assertEqual(policies[CSP_DIRECTIVE_IMAGE][0], "*") self.assertEqual(len(policies[CSP_DIRECTIVE_CONNECTION]), 1) self.assertEqual( policies[CSP_DIRECTIVE_CONNECTION][0], "trust.sample.com")
def test_retrieve_csp_policies_with_policies_case02(self): """ Test case in which several policies are specified using only 1 CSP header but with 7 differents directives. """ header_value = "default-src 'self'; img-src *;"\ " object-src media1.example.com media2.example.com"\ " *.cdn.example.com; script-src trustedscripts.example.com;"\ " form-action /ctxroot/action1 /ctxroot/action2;"\ " plugin-types application/pdf application/x-java-applet;"\ " reflected-xss block" hrds = {CSP_HEADER_W3C: header_value}.items() csp_headers = Headers(hrds) http_response = HTTPResponse(200, '', csp_headers, self.url, self.url) policies = retrieve_csp_policies(http_response) self.assertEqual(len(policies), 7) self.assertEqual(len(policies[CSP_DIRECTIVE_DEFAULT]), 1) self.assertEqual(policies[CSP_DIRECTIVE_DEFAULT][0], "self") self.assertEqual(len(policies[CSP_DIRECTIVE_IMAGE]), 1) self.assertEqual(policies[CSP_DIRECTIVE_IMAGE][0], "*") self.assertEqual(len(policies[CSP_DIRECTIVE_SCRIPT]), 1) self.assertEqual( policies[CSP_DIRECTIVE_SCRIPT][0], "trustedscripts.example.com") self.assertEqual(len(policies[CSP_DIRECTIVE_OBJECT]), 3) self.assertTrue("media1.example.com" in policies[CSP_DIRECTIVE_OBJECT]) self.assertTrue("media2.example.com" in policies[CSP_DIRECTIVE_OBJECT]) self.assertTrue("*.cdn.example.com" in policies[CSP_DIRECTIVE_OBJECT]) self.assertEqual(len(policies[CSP_DIRECTIVE_FORM]), 2) self.assertTrue("/ctxroot/action1" in policies[CSP_DIRECTIVE_FORM]) self.assertTrue("/ctxroot/action2" in policies[CSP_DIRECTIVE_FORM]) self.assertEqual(len(policies[CSP_DIRECTIVE_PLUGIN_TYPES]), 2) self.assertTrue( "application/pdf" in policies[CSP_DIRECTIVE_PLUGIN_TYPES]) self.assertTrue( "application/x-java-applet" in policies[CSP_DIRECTIVE_PLUGIN_TYPES]) self.assertEqual(len(policies[CSP_DIRECTIVE_XSS]), 1) self.assertTrue("block" in policies[CSP_DIRECTIVE_XSS])