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
Esempio n. 2
0
    def check(self, headers, opt_options=dict()):
        policy = self.getfeaturepolicy(headers)
        if not policy or not policy.parsedstring:
            return []

        findings = []

        directivesToCheck = policy.getEffectiveDirectives()

        for directive in directivesToCheck:
            values = policy.getEffectiveValues(directive)

            for value in values:
                url = Util.getSchemeFreeUrl(value)
                if url and str(FeaturePolicyKeyword.STAR) in url and len(
                        url
                ) == 1 and directive != FeaturePolicyDirective.PICTURE_IN_PICTURE:
                    findings.append(
                        Finding(
                            policy.headerkey, FindingType.PLAIN_WILDCARD,
                            directive.value +
                            ' should not allow \'*\' as source. It enables the current page and nesting contexts, such as iframes, to use the feature. It may be better to disable and explicitly tell the iframe which feature is allowed.',
                            FindingSeverity.LOW, directive, value))

        return findings
    def check(self):
        csp = self.csp
        if not csp or not csp.parsedstring:
            return []

        findings = []

        directivesToCheck = csp.getEffectiveDirectives(
            csp.DIRECTIVES_CAUSING_XSS)

        for directive in directivesToCheck:
            values = []
            if directive in csp.parsedstring:
                values = csp[directive]

            for value in values:
                url = Util.getSchemeFreeUrl(value)
                if '*' in url and len(url) == 1:
                    findings.append(
                        Finding(
                            csp.headerkey, FindingType.PLAIN_WILDCARD,
                            directive.value +
                            ' should not allow \'*\' as source. This may enable execution of malicious JavaScript.',
                            FindingSeverity.HIGH, directive, value))

        return findings
    def checkIP(self, directive, directiveValues, findings):
        csp = self.csp
        for value in directiveValues:
            url = '//' + Util.getSchemeFreeUrl(value)
            host = urlparse(url).netloc
            ip = None
            validip = True

            try:
                ip = ipaddress.ip_address(u'' + host)
            except ValueError:
                validip = False
            if validip:
                ipString = str(ip) + ''

                if '127.0.0.1' in ipString:
                    findings.append(
                        Finding(
                            csp.headerkey, FindingType.IP_SOURCE,
                            directive.value +
                            ' directive allows localhost as source. Please make sure to remove this in production environments.',
                            FindingSeverity.INFO, directive, value))
                else:
                    findings.append(
                        Finding(
                            csp.headerkey, FindingType.IP_SOURCE,
                            directive.value +
                            ' directive has an IP-Address as source: ' +
                            ipString + ' (will be ignored by browsers!). ',
                            FindingSeverity.INFO, directive, value))
    def populate(self):
#        path = securityheaders.models.__path__[0]
#        with warnings.catch_warnings():
#            warnings.simplefilter("ignore")
#            Util.load_all_modules_from_dir(path)
        clazzes = list(Util.inheritors(Header))
        clazzes.extend(Util.inheritors(Directive))
        clazzes.extend(Util.inheritors(Keyword))
        for header in list(Util.inheritors(Header)):
            if hasattr(header,'headerkey'):
                self.headers[header.headerkey] = header
    
        all_my_base_classes = {cls: cls for cls in clazzes}
        for clazz in all_my_base_classes:
            self.clazzes[clazz.__name__] = clazz
                
Esempio n. 6
0
 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 populate(self):
     #path = securityheaders.formatters.__path__[0]
     #with warnings.catch_warnings():
     #    warnings.simplefilter("ignore")
     #    Util.load_all_modules_from_dir(path)
     clazzes = list(Util.inheritors(FindingFormatter))
     all_my_base_classes = {cls: cls for cls in clazzes}
     for clazz in all_my_base_classes:
         self.clazzes[clazz.__name__] = clazz
Esempio n. 8
0
 def normalizeDirectiveValue(self, directiveValue):
     directiveValue = directiveValue.strip()
     directiveValueLower = directiveValue.lower()
     if self.directivekeyword:
         if self.directivekeyword.isKeyword(directiveValueLower):
             return self.directivekeyword[directiveValueLower]
         elif self.directivekeyword.isValue(directiveValueLower):
             return self.directivekeyword(directiveValueLower)
         elif Util.isUrlScheme(directiveValue):
             return directiveValueLower
     return directiveValue
    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
Esempio n. 10
0
 def test_getSchemeFreeUrlValid(self):
     self.assertEqual(Util.getSchemeFreeUrl('http://www.synopsys.com'),
                      'www.synopsys.com')
    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
Esempio n. 12
0
from .xcontenttypeoptions import *
from .xframeoptions import *
from .xxssprotection import *
from .referrerpolicy import *
from .featurepolicy import *
from .server import *
from .xpoweredby import *
from .xwebkitcsp import *
from .xcsp import *
from .xdownloadoptions import *
from .expectct import *
from .xaspnetversion import *
from .xaspnetmvcversion import *
from .hpkp import *
from .xpcdp import *
from .setcookie import *

__all__ = [
    'annotations', 'csp', 'cors', 'clearsitedata', 'hsts',
    'xcontenttypeoptions', 'xframeoptions', 'xxssprotection', 'featurepolicy',
    'referrerpolicy', 'server', 'xpoweredby', 'expectct', 'xcsp', 'xwebkitcsp',
    'xpcdp', 'xaspnetversion', 'xaspnetmvcversion', 'hpkp', 'xdownloadoptions'
]
clazzes = list(Util.inheritors(Header))
clazzes.extend(Util.inheritors(Directive))
clazzes.extend(Util.inheritors(Keyword))
all_my_base_classes = {cls.__name__: cls for cls in clazzes}
__all__.extend(all_my_base_classes)
__all__.append('ModelFactory')
__all__.append('CSPVersion')
Esempio n. 13
0
 def test_isUrlSchemeNone(self):
     self.assertFalse(Util.isUrlScheme(None))
Esempio n. 14
0
 def test_isUrlSchemeHttps(self):
     self.assertTrue(Util.isUrlScheme('https:'))
Esempio n. 15
0
 def test_isUrlSchemeInvalid(self):
     self.assertFalse(Util.isUrlScheme('noscheme'))
Esempio n. 16
0
 def test_getSchemeFreeUrlNone(self):
     self.assertEqual(Util.getSchemeFreeUrl(None), None)
Esempio n. 17
0
 def test_getSchemeFreeUrlCapitals(self):
     self.assertEqual(Util.getSchemeFreeUrl('HTTPS://www.synopsys.com'),
                      'www.synopsys.com')