def grep(self, request, response): ''' Perform search on current HTTP request/response exchange. Store informations about vulns for further global processing. @param request: HTTP request @param response: HTTP response ''' #Check that current URL has not been already analyzed response_url = str(response.get_url().uri2url()) if response_url in self._urls: return else: self._urls.append(response_url) #Search issues using dedicated module csp_vulns = find_vulns(response) #Analyze issue list if len(csp_vulns) > 0: vuln_store_item = DiskCSPVulnStoreItem(response_url, response.id, csp_vulns) self._vulns.append(vuln_store_item) #Increment the vulnerabilities counter for csp_directive_name in csp_vulns: self._total_count += len(csp_vulns[csp_directive_name])
def test_find_vulns_case02(self): """ Test case in which we set vulnerables policies for "sandbox", "script-nonce","plugin-types","reflected-xss" directives using invalid values. """ header_value = ( "sandbox allow-invalid; script-nonce aaa,bbb;" "plugin-types app/titi application/pdf; reflected-xss disallow;" ) hrds = {CSP_HEADER_W3C: header_value}.items() csp_headers = Headers(hrds) http_response = HTTPResponse(200, "", csp_headers, self.url, self.url) vulns = find_vulns(http_response) self.assertEqual(len(vulns), 4) # >>>"sandbox" self.assertEqual(len(vulns[CSP_DIRECTIVE_SANDBOX]), 1) warn_msg = "Directive 'sandbox' specify invalid value: 'allow-invalid'." self.assertTrue(self._vuln_exists(warn_msg, vulns[CSP_DIRECTIVE_SANDBOX])) # >>>"script-nonce" self.assertEqual(len(vulns[CSP_DIRECTIVE_SCRIPT_NONCE]), 1) warn_msg = "Directive 'script-nonce' is defined " "but nonce contains invalid character (','|';')." self.assertTrue(self._vuln_exists(warn_msg, vulns[CSP_DIRECTIVE_SCRIPT_NONCE])) # >>>"reflected-xss" self.assertEqual(len(vulns[CSP_DIRECTIVE_XSS]), 1) warn_msg = "Directive 'reflected-xss' specify invalid value: 'disallow'." self.assertTrue(self._vuln_exists(warn_msg, vulns[CSP_DIRECTIVE_XSS])) # >>>"plugins-types" self.assertEqual(len(vulns[CSP_DIRECTIVE_PLUGIN_TYPES]), 1) warn_msg = "Directive 'plugin-types' specify invalid mime type: 'app/titi'." self.assertTrue(self._vuln_exists(warn_msg, vulns[CSP_DIRECTIVE_PLUGIN_TYPES]))
def test_find_vulns_case03(self): """ Test case in which we set vulnerables policies for "sandbox","reflected-xss" directives using valid values. """ header_value = ( "sandbox allow-* allow-forms allow-same-origin " "allow-scripts allow-top-navigation;" "reflected-xss allow;" ) hrds = {CSP_HEADER_W3C: header_value}.items() csp_headers = Headers(hrds) http_response = HTTPResponse(200, "", csp_headers, self.url, self.url) vulns = find_vulns(http_response) self.assertEqual(len(vulns), 2) # >>>"sandbox" self.assertEqual(len(vulns[CSP_DIRECTIVE_SANDBOX]), 2) warn_msg = "Directive 'sandbox' apply no restrictions." self.assertTrue(vulns[CSP_DIRECTIVE_SANDBOX][0].desc, warn_msg) self.assertTrue(vulns[CSP_DIRECTIVE_SANDBOX][1].desc, warn_msg) # >>>"reflected-xss" self.assertEqual(len(vulns[CSP_DIRECTIVE_XSS]), 1) warn_msg = ( "Directive 'reflected-xss' instruct user agent to " "disable its active protections against reflected XSS." ) self.assertTrue(self._vuln_exists(warn_msg, vulns[CSP_DIRECTIVE_XSS]))
def test_find_vulns_case03(self): ''' Test case in which we set vulnerables policies for "sandbox","reflected-xss" directives using valid values. ''' header_value = "sandbox allow-* allow-forms allow-same-origin " \ "allow-scripts allow-top-navigation;"\ "reflected-xss allow;" hrds = {CSP_HEADER_W3C: header_value}.items() csp_headers = Headers(hrds) http_response = HTTPResponse(200, '', csp_headers, self.url, self.url) vulns = find_vulns(http_response) self.assertEqual(len(vulns), 2) #>>>"sandbox" self.assertEqual(len(vulns[CSP_DIRECTIVE_SANDBOX]), 2) warn_msg = "Directive 'sandbox' apply no restrictions." self.assertTrue(vulns[CSP_DIRECTIVE_SANDBOX][0].desc, warn_msg) self.assertTrue(vulns[CSP_DIRECTIVE_SANDBOX][1].desc, warn_msg) #>>>"reflected-xss" self.assertEqual(len(vulns[CSP_DIRECTIVE_XSS]), 1) warn_msg = "Directive 'reflected-xss' instruct user agent to "\ "disable its active protections against reflected XSS." self.assertTrue(self._vuln_exists(warn_msg, vulns[CSP_DIRECTIVE_XSS]))
def test_find_vulns_case02(self): ''' Test case in which we set vulnerables policies for "sandbox", "script-nonce","plugin-types","reflected-xss" directives using invalid values. ''' header_value = "sandbox allow-invalid; script-nonce aaa,bbb;"\ "plugin-types app/titi application/pdf; reflected-xss disallow;" hrds = {CSP_HEADER_W3C: header_value}.items() csp_headers = Headers(hrds) http_response = HTTPResponse(200, '', csp_headers, self.url, self.url) vulns = find_vulns(http_response) self.assertEqual(len(vulns), 4) #>>>"sandbox" self.assertEqual(len(vulns[CSP_DIRECTIVE_SANDBOX]), 1) warn_msg = "Directive 'sandbox' specify invalid value: 'allow-invalid'." self.assertTrue( self._vuln_exists(warn_msg, vulns[CSP_DIRECTIVE_SANDBOX])) #>>>"script-nonce" self.assertEqual(len(vulns[CSP_DIRECTIVE_SCRIPT_NONCE]), 1) warn_msg = "Directive 'script-nonce' is defined "\ "but nonce contains invalid character (','|';')." self.assertTrue( self._vuln_exists(warn_msg, vulns[CSP_DIRECTIVE_SCRIPT_NONCE])) #>>>"reflected-xss" self.assertEqual(len(vulns[CSP_DIRECTIVE_XSS]), 1) warn_msg = "Directive 'reflected-xss' specify invalid value: 'disallow'." self.assertTrue(self._vuln_exists(warn_msg, vulns[CSP_DIRECTIVE_XSS])) #>>>"plugins-types" self.assertEqual(len(vulns[CSP_DIRECTIVE_PLUGIN_TYPES]), 1) warn_msg = "Directive 'plugin-types' specify invalid mime type: 'app/titi'." self.assertTrue( self._vuln_exists(warn_msg, vulns[CSP_DIRECTIVE_PLUGIN_TYPES]))
def test_find_vulns_case04(self): ''' Test case in which we configure correctly policies for all directives. ''' header_value = "default-src 'self';script-src 'self';object-src 'self';" \ "style-src 'self';img-src 'self';media-src 'self';" \ "frame-src 'self';font-src 'self';sandbox;" \ "form-action '/myCtx/act';connect-src 'self';"\ "plugin-types application/pdf;reflected-xss filter;"\ "script-nonce AABBCCDDEE;" hrds = {CSP_HEADER_W3C: header_value}.items() csp_headers = Headers(hrds) http_response = HTTPResponse(200, '', csp_headers, self.url, self.url) vulns = find_vulns(http_response) self.assertEqual(len(vulns), 0)
def test_find_vulns_case04(self): """ Test case in which we configure correctly policies for all directives. """ header_value = ( "default-src 'self';script-src 'self';object-src 'self';" "style-src 'self';img-src 'self';media-src 'self';" "frame-src 'self';font-src 'self';sandbox;" "form-action '/myCtx/act';connect-src 'self';" "plugin-types application/pdf;reflected-xss filter;" "script-nonce AABBCCDDEE;" ) hrds = {CSP_HEADER_W3C: header_value}.items() csp_headers = Headers(hrds) http_response = HTTPResponse(200, "", csp_headers, self.url, self.url) vulns = find_vulns(http_response) self.assertEqual(len(vulns), 0)
def test_find_vulns_case05(self): """ Test case in which we misspell somes policies. """ header_value = ( "defauld-src 'self';script-src 'self';object-src 'self';" "style-src 'self';image-src 'self';media-src 'self';" "frame-src 'self';font-src 'self';sandbox;" "form-src '/myCtx/act';connect-src 'self';" "plugin-types application/pdf;reflected-xss filter;" "script-nonce AABBCCDDEE;" ) hrds = {CSP_HEADER_W3C: header_value}.items() csp_headers = Headers(hrds) http_response = HTTPResponse(200, "", csp_headers, self.url, self.url) vulns = find_vulns(http_response) self.assertEqual(len(vulns), 1) self.assertEqual(len(vulns[CSP_MISSPELLED_DIRECTIVES]), 1) warn_msg = "Somes directives are misspelled: " "defauld-src,image-src,form-src" self.assertTrue(self._vuln_exists(warn_msg, vulns[CSP_MISSPELLED_DIRECTIVES]))
def test_find_vulns_case05(self): ''' Test case in which we misspell somes policies. ''' header_value = "defauld-src 'self';script-src 'self';object-src 'self';" \ "style-src 'self';image-src 'self';media-src 'self';" \ "frame-src 'self';font-src 'self';sandbox;" \ "form-src '/myCtx/act';connect-src 'self';"\ "plugin-types application/pdf;reflected-xss filter;"\ "script-nonce AABBCCDDEE;" hrds = {CSP_HEADER_W3C: header_value}.items() csp_headers = Headers(hrds) http_response = HTTPResponse(200, '', csp_headers, self.url, self.url) vulns = find_vulns(http_response) self.assertEqual(len(vulns), 1) self.assertEqual(len(vulns[CSP_MISSPELLED_DIRECTIVES]), 1) warn_msg = "Somes directives are misspelled: "\ "defauld-src,image-src,form-src" self.assertTrue( self._vuln_exists(warn_msg, vulns[CSP_MISSPELLED_DIRECTIVES]))
def test_find_vulns_case01(self): """ Test case in which we set vulnerables policies using "*" as source for all directives that allow this value. """ header_value = ( "default-src '*';script-src '*';object-src '*';" "style-src '*';img-src '*';media-src '*';" "frame-src '*';font-src '*';" "form-action '*';connect-src '*';plugin-types '*';" ) hrds = {CSP_HEADER_W3C: header_value}.items() csp_headers = Headers(hrds) http_response = HTTPResponse(200, "", csp_headers, self.url, self.url) vulns = find_vulns(http_response) self.assertEqual(len(vulns), 11) # >>>"default-src" self.assertEqual(len(vulns[CSP_DIRECTIVE_DEFAULT]), 1) self.assertTrue(self._vuln_exists("Directive 'default-src' allow all sources.", vulns[CSP_DIRECTIVE_DEFAULT])) # >>>"script-src" self.assertEqual(len(vulns[CSP_DIRECTIVE_SCRIPT]), 2) self.assertTrue( self._vuln_exists("Directive 'script-src' allow all javascript sources.", vulns[CSP_DIRECTIVE_SCRIPT]) ) warn_msg = ( "Directive 'script-src' is defined but no directive " "'script-nonce' is defined to protect javascript resources." ) self.assertTrue(self._vuln_exists(warn_msg, vulns[CSP_DIRECTIVE_SCRIPT])) # >>>"object-src" self.assertEqual(len(vulns[CSP_DIRECTIVE_OBJECT]), 1) self.assertTrue( self._vuln_exists("Directive 'object-src' allow all plugin sources.", vulns[CSP_DIRECTIVE_OBJECT]) ) # >>>"style-src" self.assertEqual(len(vulns[CSP_DIRECTIVE_STYLE]), 1) self.assertTrue(self._vuln_exists("Directive 'style-src' allow all CSS sources.", vulns[CSP_DIRECTIVE_STYLE])) # >>>"img-src" self.assertEqual(len(vulns[CSP_DIRECTIVE_IMAGE]), 1) self.assertTrue(self._vuln_exists("Directive 'img-src' allow all image sources.", vulns[CSP_DIRECTIVE_IMAGE])) # >>>"media-src" self.assertEqual(len(vulns[CSP_DIRECTIVE_MEDIA]), 1) self.assertTrue( self._vuln_exists("Directive 'media-src' allow all audio/video sources.", vulns[CSP_DIRECTIVE_MEDIA]) ) # >>>"frame-src" self.assertEqual(len(vulns[CSP_DIRECTIVE_FRAME]), 2) self.assertTrue(self._vuln_exists("Directive 'frame-src' allow all sources.", vulns[CSP_DIRECTIVE_FRAME])) warn_msg = ( "Directive 'frame-src' is defined but no directive " "'sandbox' is defined to protect resources. Perhaps sandboxing " "is defined at html attribute level ?" ) self.assertTrue(self._vuln_exists(warn_msg, vulns[CSP_DIRECTIVE_FRAME])) # >>>"font-src" self.assertEqual(len(vulns[CSP_DIRECTIVE_FONT]), 1) self.assertTrue(self._vuln_exists("Directive 'font-src' allow all font sources.", vulns[CSP_DIRECTIVE_FONT])) # >>>"connect-src" self.assertEqual(len(vulns[CSP_DIRECTIVE_CONNECTION]), 1) self.assertTrue( self._vuln_exists("Directive 'connect-src' allow all connection sources.", vulns[CSP_DIRECTIVE_CONNECTION]) ) # >>>"form-action" self.assertEqual(len(vulns[CSP_DIRECTIVE_FORM]), 1) self.assertTrue( self._vuln_exists("Directive 'form-action' allow all action target.", vulns[CSP_DIRECTIVE_FORM]) ) # >>>"plugin-types" self.assertEqual(len(vulns[CSP_DIRECTIVE_PLUGIN_TYPES]), 1) self.assertTrue( self._vuln_exists("Directive 'plugin-types' allow all plugins types.", vulns[CSP_DIRECTIVE_PLUGIN_TYPES]) )
def test_find_vulns_case01(self): ''' Test case in which we set vulnerables policies using "*" as source for all directives that allow this value. ''' header_value = "default-src '*';script-src '*';object-src '*';" \ "style-src '*';img-src '*';media-src '*';" \ "frame-src '*';font-src '*';" \ "form-action '*';connect-src '*';plugin-types '*';" hrds = {CSP_HEADER_W3C: header_value}.items() csp_headers = Headers(hrds) http_response = HTTPResponse(200, '', csp_headers, self.url, self.url) vulns = find_vulns(http_response) self.assertEqual(len(vulns), 11) #>>>"default-src" self.assertEqual(len(vulns[CSP_DIRECTIVE_DEFAULT]), 1) self.assertTrue( self._vuln_exists("Directive 'default-src' allow all sources.", vulns[CSP_DIRECTIVE_DEFAULT])) #>>>"script-src" self.assertEqual(len(vulns[CSP_DIRECTIVE_SCRIPT]), 2) self.assertTrue( self._vuln_exists( "Directive 'script-src' allow all javascript sources.", vulns[CSP_DIRECTIVE_SCRIPT])) warn_msg = "Directive 'script-src' is defined but no directive " \ "'script-nonce' is defined to protect javascript resources." self.assertTrue( self._vuln_exists(warn_msg, vulns[CSP_DIRECTIVE_SCRIPT])) #>>>"object-src" self.assertEqual(len(vulns[CSP_DIRECTIVE_OBJECT]), 1) self.assertTrue( self._vuln_exists( "Directive 'object-src' allow all plugin sources.", vulns[CSP_DIRECTIVE_OBJECT])) #>>>"style-src" self.assertEqual(len(vulns[CSP_DIRECTIVE_STYLE]), 1) self.assertTrue( self._vuln_exists("Directive 'style-src' allow all CSS sources.", vulns[CSP_DIRECTIVE_STYLE])) #>>>"img-src" self.assertEqual(len(vulns[CSP_DIRECTIVE_IMAGE]), 1) self.assertTrue( self._vuln_exists("Directive 'img-src' allow all image sources.", vulns[CSP_DIRECTIVE_IMAGE])) #>>>"media-src" self.assertEqual(len(vulns[CSP_DIRECTIVE_MEDIA]), 1) self.assertTrue( self._vuln_exists( "Directive 'media-src' allow all audio/video sources.", vulns[CSP_DIRECTIVE_MEDIA])) #>>>"frame-src" self.assertEqual(len(vulns[CSP_DIRECTIVE_FRAME]), 2) self.assertTrue( self._vuln_exists("Directive 'frame-src' allow all sources.", vulns[CSP_DIRECTIVE_FRAME])) warn_msg = "Directive 'frame-src' is defined but no directive " \ "'sandbox' is defined to protect resources. Perhaps sandboxing " \ "is defined at html attribute level ?" self.assertTrue(self._vuln_exists(warn_msg, vulns[CSP_DIRECTIVE_FRAME])) #>>>"font-src" self.assertEqual(len(vulns[CSP_DIRECTIVE_FONT]), 1) self.assertTrue( self._vuln_exists("Directive 'font-src' allow all font sources.", vulns[CSP_DIRECTIVE_FONT])) #>>>"connect-src" self.assertEqual(len(vulns[CSP_DIRECTIVE_CONNECTION]), 1) self.assertTrue( self._vuln_exists( "Directive 'connect-src' allow all connection sources.", vulns[CSP_DIRECTIVE_CONNECTION])) #>>>"form-action" self.assertEqual(len(vulns[CSP_DIRECTIVE_FORM]), 1) self.assertTrue( self._vuln_exists( "Directive 'form-action' allow all action target.", vulns[CSP_DIRECTIVE_FORM])) #>>>"plugin-types" self.assertEqual(len(vulns[CSP_DIRECTIVE_PLUGIN_TYPES]), 1) self.assertTrue( self._vuln_exists( "Directive 'plugin-types' allow all plugins types.", vulns[CSP_DIRECTIVE_PLUGIN_TYPES]))