def test_matchWildcardUrls(self): urls = [ '//vk.com/swf/video.swf', '//ajax.googleapis.com/ajax/libs/yui/2.8.0r4/build/charts/assets/charts.swf' ] self.assertEqual(Util.matchWildcardUrls('https://*.vk.com', urls), None) self.assertEqual( Util.matchWildcardUrls('https://ajax.googleapis.com', urls), urlparse( '//ajax.googleapis.com/ajax/libs/yui/2.8.0r4/build/charts/assets/charts.swf' )) self.assertEqual( Util.matchWildcardUrls('https://*.googleapis.com', urls), urlparse( '//ajax.googleapis.com/ajax/libs/yui/2.8.0r4/build/charts/assets/charts.swf' )) self.assertEqual(Util.matchWildcardUrls(None, urls), None) self.assertEqual( Util.matchWildcardUrls('https://*.googleapis.com', None), None) self.assertEqual( Util.matchWildcardUrls('https://*.googleapis.com', []), None) self.assertEqual( Util.matchWildcardUrls('*.googleapis.com', urls), urlparse( '//ajax.googleapis.com/ajax/libs/yui/2.8.0r4/build/charts/assets/charts.swf' ))
def check(self, opt_options=dict()): csp = self.csp if not csp: return [] findings = [] angular = [] jsonp = [] jsonpeval = [] if 'bypasses' not in opt_options.keys(): bypasses = [] else: bypasses = opt_options['bypasses'] directive = csp.getEffectiveDirective(csp.directive.OBJECT_SRC) objectSrcValues = [] try: objectSrcValues = csp[directive] except KeyError: objectSrcValues = [] if csp.directive.PLUGIN_TYPES in csp.parsedstring: pluginTypes = csp[csp.directive.PLUGIN_TYPES] else: pluginTypes = None if pluginTypes and not 'application/x-shockwave-flash' in pluginTypes: return [] for value in objectSrcValues: if value == csp.keyword.NONE: return [] url = '//' + Util.getSchemeFreeUrl(value) flashBypass = Util.matchWildcardUrls(url, bypasses) if (flashBypass): findings.append( Finding( csp.headerkey, FindingType.OBJECT_WHITELIST_BYPASS, flashBypass.netloc + ' is known to host Flash files which allow to bypass this CSP.', FindingSeverity.HIGH, directive, value)) elif (directive == csp.directive.OBJECT_SRC): findings.append( Finding(csp.headerkey, FindingType.OBJECT_WHITELIST_BYPASS, 'Can you restrict object-src to \'none\' only?', FindingSeverity.MEDIUM_MAYBE, directive, value)) return findings
def check(self, opt_options=dict()): csp = self.csp if not csp: return [] findings = [] cdn = [] if 'cdn' not in opt_options.keys(): cdn = [] elif 'cdn' in opt_options.keys(): cdn = opt_options['cdn'] effectiveScriptSrcDirective = csp.getEffectiveDirective( csp.directive.SCRIPT_SRC) scriptSrcValues = [] try: scriptSrcValues = csp[effectiveScriptSrcDirective] except KeyError: scriptSrcValues = [] for value in scriptSrcValues: if value.startswith('\''): continue if Util.isUrlScheme(value) or value.find('.') == -1: continue url = '//' + Util.getSchemeFreeUrl(value) cdnbypass = Util.matchWildcardUrls(url, cdn) if cdnbypass: bypassDomain = '' bypassUrl = '//' + cdnbypass.netloc + cdnbypass.path bypassDomain = cdnbypass.netloc findings.append( Finding( csp.headerkey, FindingType.SCRIPT_WHITELIST_BYPASS, bypassDomain + ' is known to host many libraries which allow to bypass this CSP. Do not whitelist all scripts of a CDN.', FindingSeverity.HIGH, effectiveScriptSrcDirective, value)) return findings
def check(self, opt_options=dict()): csp = self.csp if not csp: return [] findings = [] angular = [] jsonp = [] jsonpeval = [] if 'angular' not in opt_options.keys(): angular = [] elif 'angular' in opt_options.keys(): angular = opt_options['angular'] if 'jsonp' not in opt_options.keys(): jsonp = [] if 'jsonp' in opt_options.keys(): jsonp = opt_options['jsonp'] if 'jsonpeval' not in opt_options.keys(): jsonpeval = [] if 'jsonpeval' in opt_options.keys(): jsonpeval = opt_options['jsonpeval'] effectiveScriptSrcDirective = csp.getEffectiveDirective( csp.directive.SCRIPT_SRC) scriptSrcValues = [] try: scriptSrcValues = csp[effectiveScriptSrcDirective] except KeyError: scriptSrcValues = [] for value in scriptSrcValues: if value == csp.keyword.SELF or value == str(csp.keyword.SELF): findings.append( Finding( csp.headerkey, FindingType.SCRIPT_WHITELIST_BYPASS, '\'self\' can be problematic if you host JSONP, Angular or user uploaded files.', FindingSeverity.MEDIUM_MAYBE, effectiveScriptSrcDirective, value)) continue if value.startswith('\''): continue if Util.isUrlScheme(value) or value.find('.') == -1: continue url = '//' + Util.getSchemeFreeUrl(value) angularBypass = Util.matchWildcardUrls(url, angular) jsonpBypass = Util.matchWildcardUrls(url, jsonp) if jsonpBypass: bypassUrl = '//' + jsonpBypass.netloc + jsonpBypass.path evalRequired = jsonpBypass.netloc in jsonpeval evalPresent = csp.keyword.UNSAFE_EVAL in scriptSrcValues if evalRequired and not evalPresent: jsonpBypass = None if jsonpBypass or angularBypass: bypassDomain = '' bypassTxt = '' if jsonpBypass: bypassDomain = jsonpBypass.netloc bypassTxt = ' JSONP endpoints' if angularBypass: bypassDomain = angularBypass.netloc if not bypassTxt: bypassTxt += '' else: bypassTxt += ' and' bypassTxt += ' Angular libraries' findings.append( Finding( csp.headerkey, FindingType.SCRIPT_WHITELIST_BYPASS, bypassDomain + ' is known to host' + bypassTxt + ' which allow to bypass this CSP.', FindingSeverity.HIGH, effectiveScriptSrcDirective, value)) else: findings.append( Finding( csp.headerkey, FindingType.SCRIPT_WHITELIST_BYPASS, 'No bypass found; make sure that this URL doesn\'t serve JSONP replies or Angular libraries.', FindingSeverity.MEDIUM_MAYBE, effectiveScriptSrcDirective, value)) return findings