Esempio n. 1
0
    def check(self, headers, opt_options=dict()):
        findings = []
        expectct = self.getexpectct(headers)

        if not expectct:
            return findings

        findings = []
        if not expectct.enforce():
            findings.append(
                Finding(
                    expectct.headerkey, FindingType.NOT_ENFORCED,
                    expectct.headerkey + 'is not enforced as ' +
                    ExpectCT.directive.ENFORCE.value + ' is not set.',
                    FindingSeverity.LOW, ExpectCT.directive.ENFORCE, None))
        if expectct.maxage() == 0:
            findings.append(
                Finding(
                    expectct.headerkey, FindingType.NOT_ENFORCED,
                    expectct.headerkey + 'is not enforced as ' +
                    ExpectCT.directive.MAX_AGE.value + ' is set to 0',
                    FindingSeverity.LOW, ExpectCT.directive.MAX_AGE, '0'))
        elif expectct.maxage() and expectct.maxage() < 3000:
            findings.append(
                Finding(
                    expectct.headerkey, FindingType.NOT_ENFORCED,
                    expectct.headerkey +
                    'is only enforced for a very short amount of time as ' +
                    ExpectCT.directive.MAX_AGE.value + ' is set to ' +
                    str(expectct.maxage()), FindingSeverity.LOW,
                    ExpectCT.directive.MAX_AGE, str(expectct.maxage())))
        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))
Esempio n. 3
0
    def mycheck(self, data):
        findings = []

        if not data:
            return findings

        directiveclazz = data.directive
        if not hasattr(directiveclazz, 'anydirective') or (
                hasattr(directiveclazz, 'anydirective')
                and not directiveclazz.anydirective):
            seperator = directiveclazz.directivevalueseperator()
            for directive in data.keys():
                if not directiveclazz.isDirective(directive):
                    if directive.endswith(seperator):
                        findings.append(
                            Finding(
                                data.headerkey, FindingType.UNKNOWN_DIRECTIVE,
                                str(data.headerkey) +
                                " directives don't end with a " +
                                str(seperator), FindingSeverity.SYNTAX, None,
                                directive))
                    else:
                        findings.append(
                            Finding(
                                data.headerkey, FindingType.UNKNOWN_DIRECTIVE,
                                'Directive "' + str(directive) +
                                '" is not a known ' + str(data.headerkey) +
                                ' directive.', FindingSeverity.SYNTAX,
                                directive))

        return findings
Esempio n. 4
0
    def mycheck(self, data):
        findings = []
        if not data:
            return findings

        if not hasattr(data, 'directive'):
            return []
        isDirective = data.directive
        if not isDirective:
            return []

        directiveseperator = isDirective.directiveseperator()

        for directive in data.keys():
            for value in data[directive]:             
                value = str(value)
                if isDirective.isDirective(value):
                    finding = Finding(data.headerkey, FindingType.MISSING_SEMICOLON,'Did you forget the '+ str(directiveseperator) + ' character? "' + str(value) + '" seems to be a directive, not a value',FindingSeverity.SYNTAX, directive, value)
                    if not finding in findings:
                        findings.append(finding)
                for directive2 in list(isDirective):
                    if str(directive2) in str(value).lower()and not isDirective.isDirective(value) and not str(directive2) +'.' in str(value).lower() and not "_" + str(directive2) in str(value).lower(): #to avoid things like https://*.sandbox.paypal.com or xss_report                        
                        finding = Finding(data.headerkey, FindingType.MISSING_SEMICOLON,'Did you forget the '+ str(directiveseperator) + ' character? "' + str(value) + '" seems to be a directive, not a value',FindingSeverity.SYNTAX, directive, value)
                        if not finding in findings:
                            findings.append(finding)
           
        return findings 
    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. 6
0
 def checkframing(self, directive, directiveValues, findings):
     csp = self.csp
     description = "This directive tells the browser whether you want to allow your site to be framed or not. By preventing a browser from framing your site you can defend against attacks like clickjacking. The recommended value is 'none' or 'self'."
     for value in directiveValues:
         if directive == csp.directive.FRAME_ANCESTORS:
            if self.__notcontains_keyword__(value, csp.keyword.NONE) and self.__notcontains_keyword__(value, csp.keyword.SELF):
                findings.append(Finding(csp.headerkey, FindingType.ALLOW_FROM,description,FindingSeverity.MEDIUM_MAYBE, directive, value))                  
Esempio n. 7
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
Esempio n. 8
0
    def mycheck(self, headers, header, description, options):
        if not header or not headers:
           return []

        if header in headers.keys():
            return [Finding(header, FindingType.INFO_DISCLOSURE, header + ' header present. ' + description,FindingSeverity.INFO, None, headers[header])]
        return []  
    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
Esempio n. 10
0
    def check(self, headers, opt_options=dict()):
        opts = self.getxframeoptions(headers)
        csp = self.getcsp(headers)
        if not opts or not csp:
            return []

        value = None
        if csp.directive.FRAME_ANCESTORS in csp.keys():
            value = csp[csp.directive.FRAME_ANCESTORS]
        if not value:
            return []

        inconsistent = False
        if opts.deny() and not self.__notcontains_keyword__(
                value, csp.keyword.NONE):
            inconsistent = True
        elif opts.sameorigin() and not self.__notcontains_keyword__(
                value, csp.keyword.SELF):
            inconsistent = True
        elif opts.allowfrom() not in value:
            inconsistent = True

        if inconsistent:
            return [
                Finding(
                    CSP.headerkey, FindingType.INCONSISTENCIES,
                    'The X-Frame-Options and the Content-Security-Policy have different framing policies. The Content-Security-Policy header had a '
                    + str(csp.directive.FRAME_ANCESTORS) +
                    ' directive with as value ' + ", ".join(value) +
                    ', while the X-Frame-Options header had as value "' +
                    str(opts.keys()[0]) +
                    '". Browsers should follow the CSP, but that behavior is not guaranteed.',
                    FindingSeverity.INFO, csp.directive.FRAME_ANCESTORS, value)
            ]
        return []
Esempio n. 11
0
    def check(self, headers, opt_options=dict()): 
        cookie = self.getcookie(headers)

        if not cookie:
            return []
        if not cookie.secure() and requires_security(cookie):
            return [Finding(SetCookie.headerkey, FindingType.INSECURE_HEADER, 'The cookie does not have the secure flag set.', FindingSeverity.MEDIUM,SetCookie.directive.SECURE, None)]
        return []
Esempio n. 12
0
 def check(self, headers, opt_options=dict()):
     opts = self.getxframeoptions(headers)
     if not opts:
         return []
     if opts.allowfrom():
         directive = opts.directives()[0] if opts.directives() else None
         return [Finding(XFrameOptions.headerkey, FindingType.ALLOW_FROM, 'This header tells the browser whether you want to allow your site to be framed or not. By preventing a browser from framing your site you can defend against attacks like clickjacking. The recommended value is "x-frame-options: SAMEORIGIN."' ,FindingSeverity.MEDIUM_MAYBE, directive, None)]
     return []
Esempio n. 13
0
    def check(self):
        csp = self.csp
        if not csp:
            return []

        findings = []

        directivesCausingXss = csp.DIRECTIVES_CAUSING_XSS
        if csp.parsedstring and csp.directive.DEFAULT_SRC in csp.parsedstring:
            defaultSrcValues = csp[csp.directive.DEFAULT_SRC]
            if not csp.directive.OBJECT_SRC in csp.parsedstring and (
                    not csp.keyword.NONE in defaultSrcValues
                    or not str(csp.keyword.NONE) in defaultSrcValues):
                findings.append(
                    Finding(csp.headerkey, FindingType.MISSING_DIRECTIVES,
                            'Can you restrict object-src to \'none\'?',
                            FindingSeverity.HIGH_MAYBE,
                            csp.directive.OBJECT_SRC))
            if csp.directive.BASE_URI in csp.parsedstring:
                return findings
            else:
                directivesCausingXss = [csp.directive.BASE_URI]
        else:
            findings.append(
                Finding(
                    csp.headerkey, FindingType.MISSING_DIRECTIVES,
                    "The default-src directive should be set as a fall-back when other restrictions have not been specified. ",
                    FindingSeverity.HIGH, csp.directive.DEFAULT_SRC))

        for directive in directivesCausingXss:
            if not csp.parsedstring or not directive in csp.parsedstring:
                description = directive.value + ' directive is missing.'
                if directive == csp.directive.OBJECT_SRC:
                    description = 'Missing object-src allows the injection of plugins which can execute JavaScript. Can you set it to \'none\'?'
                elif directive == csp.directive.BASE_URI:
                    if not csp.policyHasScriptNonces(
                    ) and not csp.policyHasScriptHashes(
                    ) and csp.policyHasStrictDynamic():
                        continue
                    description = 'Missing base-uri allows the injection of base tags. They can be used to set the base URL for all relative (script) URLs to an attacker controlled domain. Can you set it to \'none\' or \'self\'?'
                findings.append(
                    Finding(csp.headerkey, FindingType.MISSING_DIRECTIVES,
                            description, FindingSeverity.HIGH, directive))

        return findings
Esempio n. 14
0
 def check(self, headers, opt_options=dict()):
     if not headers:
         return []
     findings = []
     for header in headers.keys():
         findings.append(
             Finding(header, FindingType.INFO_HEADER, headers[header],
                     FindingSeverity.NONE, None, None))
     return findings
Esempio n. 15
0
    def check(self, headers, opt_options=dict()): 
        findings = []
        hsts = self.gethsts(headers) 

        if not hsts:
            return findings
        if hsts.maxAge() == 0:
            return [Finding(HSTS.headerkey, FindingType.MAX_AGE_ZERO, str(HSTS.headerkey) + ' is disabled due to max age equal to zero.', FindingSeverity.LOW, HSTS.directive.MAX_AGE)]

        return findings
Esempio n. 16
0
 def checkNonce(self, directive, directiveValues, findings):
     nonce_pattern = re.compile("^'nonce-(.+)'$")
     for value in directiveValues:
         value = str(value)
         match = nonce_pattern.search(value)
         #nonce value starts with nonce- but does not have an actual value
         if not bool(match) and "nonce-" in value:
             findings.append(Finding(self.csp.headerkey,FindingType.NONCE_LENGTH,'Nonces should be at least 8 characters long.',FindingSeverity.MEDIUM, directive, value))
         #no nonce value in the directive value
         if not bool(match):
             continue
         #nonce value in the directive value
         else:
             #get the value of the nonce; i.e. everything after nonce-
             nonceValue = match.group(1)
             if len(nonceValue) < 8:
                 findings.append(Finding(self.csp.headerkey,FindingType.NONCE_LENGTH,'Nonces should be at least 8 characters long.',FindingSeverity.MEDIUM, directive, value))
             if not self.csp.isNonce(value, True):
                 findings.append(Finding(self.csp.headerkey,FindingType.NONCE_LENGTH,'Nonces should only use the base64 charset.',FindingSeverity.INFO, directive, value))
Esempio n. 17
0
 def mycheck(self, data):
     if not data:
         return []
     if not data.hasdirectives() and isinstance(data, SecurityHeader):
         return [
             Finding(data.headerkey, FindingType.MISSING_HEADER,
                     str(data.headerkey) + ' header is empty.',
                     FindingSeverity.INFO, data.headerkey)
         ]
     return []
Esempio n. 18
0
    def check(self, headers, opt_options=dict()):
        rocsp = CSPReportOnlyChecker.getcsp(self, headers)
        csp = CSPChecker.getcsp(self, headers)

        if not csp and rocsp:
            description = "The CSP is not enforced as only the content-security-policy-report-only header is present. Can you set the content-security-policy?"
            return [
                Finding(rocsp.headerkey, FindingType.REPORT_ONLY, description,
                        FindingSeverity.INFO, None, None)
            ]
        return []
Esempio n. 19
0
 def check(self, headers, opt_options=dict()):
     xxss = self.getxxss(headers)
     if xxss and not xxss.one():
         return [
             Finding(
                 XXSSProtection.headerkey, FindingType.DISABLE_XSS_FILTER,
                 'This header sets the configuration for the cross-site scripting filter built into most browsers. The recommended value is "X-XSS-Protection: 1; mode=block".',
                 FindingSeverity.LOW, XXSSProtectionDirective.ONE,
                 XXSSProtectionDirective.ZERO)
         ]
     return []
Esempio n. 20
0
 def check(self, headers, opt_options=dict()):
     origins = self.getorigins(headers)
     if origins and origins.isstar():
         return [
             Finding(
                 AccessControlAllowOrigin.headerkey,
                 FindingType.STAR_ORIGIN,
                 str(AccessControlAllowOrigin.headerkey) +
                 " should not be *", FindingSeverity.HIGH,
                 AccessControlAllowOriginDirective.STAR, None)
         ]
     return []
Esempio n. 21
0
    def check(self, headers, opt_options=dict()):
        xxss = self.getxxss(headers)

        if xxss and xxss.report() and xxss.report().startswith('http:'):
            return [
                Finding(
                    XXSSProtection.headerkey, FindingType.HTTP_REPORT,
                    'This header sets the configuration for the cross-site scripting filter built into most browsers. Violations should be reported to an HTTPS endpoint".',
                    FindingSeverity.LOW, XXSSProtectionDirective.REPORT,
                    xxss.report())
            ]
        return []
Esempio n. 22
0
 def checksrchttp(self, directive, directiveValues, findings):
     csp = self.csp
     for value in directiveValues:
         description = None
         if directive == csp.directive.REPORT_URI:
             description = 'Use HTTPS to send violation reports securely.'
         else:
             description = 'Allow only resources downloaded over HTTPS.'
         if value.startswith('http://'):
             findings.append(
                 Finding(csp.headerkey, FindingType.SRC_HTTP, description,
                         FindingSeverity.MEDIUM, directive, value))
Esempio n. 23
0
    def check(self, headers, opt_options=dict()):
        findings = []
        policy = self.getreferrerpolicy(headers)

        if not policy:
            return findings
        if policy.unsafe_url():
            findings.append(
                Finding(
                    ReferrerPolicy.headerkey, FindingType.UNSAFE_URL,
                    'If this policy is set, it should not use unsafe-url and origin-when-cross-origin as it can transfer sensitive information (via the Referer header) from HTTPS environments to HTTP environments.',
                    FindingSeverity.LOW, ReferrerPolicy.directive.UNSAFE_URL))
        if policy.origin_when_cross_origin():
            findings.append(
                Finding(
                    ReferrerPolicy.headerkey,
                    FindingType.ORIGIN_WHEN_CROSS_ORIGIN,
                    'If this policy is set, it should not use unsafe-url and origin-when-cross-origin as it can transfer sensitive information (via the Referer header) from HTTPS environments to HTTP environments.',
                    FindingSeverity.LOW,
                    ReferrerPolicy.directive.ORIGIN_WHEN_CROSS_ORIGIN))
        return findings
Esempio n. 24
0
 def check(self, headers, opt_options=dict()):
     maxage = self.getmaxage(headers)
     if maxage and maxage.maxage() and maxage.maxage() > 1800:
         return [
             Finding(
                 AccessControlMaxAge.headerkey,
                 FindingType.MAX_AGE_TOO_LONG,
                 str(AccessControlMaxAge.headerkey) +
                 " set to a too large value. This header is used by the server to explicitly instruct browsers to cache responses to CORS requests. An excessively long cache timeout increases the risk that changes to a server's CORS policy will not be honored as they still use a cached response.",
                 FindingSeverity.LOW, AccessControlMaxAgeDirective,
                 str(maxage.maxage()))
         ]
     return []
Esempio n. 25
0
 def check(self, headers, opt_options=dict()):
     opts = self.getxcontenttypeoptions(headers)
     if not opts:
         return []
     if not opts.nosniff():
         directive = opts.directives()[0] if opts.directives() else None
         return [
             Finding(
                 XFrameOptions.headerkey, FindingType.NOSNIFF,
                 'This header stops a browser from trying to MIME-sniff the content type and forces it to stick with the declared content-type. The only valid value for this header is "X-Content-Type-Options: nosniff"',
                 FindingSeverity.MEDIUM, directive, None)
         ]
     return []
Esempio n. 26
0
    def mycheck(self, headers, header):
        if not header or not headers:
            return []

        if header in headers.keys() or header.lower() in headers.keys():
            value = headers[header] if header in headers.keys() else headers[
                header.lower()]
            return [
                Finding(
                    header, FindingType.DEPRECATED_HEADER, header +
                    ' header present. This header is deprecated and should not be used.',
                    FindingSeverity.INFO, None, value)
            ]
        return []
Esempio n. 27
0
    def check(self):
        csp = self.csp
        if not csp or not csp.parsedstring:
            return []

        findings = []
        if csp.directive.REPORT_URI in csp.parsedstring:
            findings.append(
                Finding(
                    csp.headerkey, FindingType.DEPRECATED_DIRECTIVE,
                    'report-uri is deprecated in CSP3. Please use the report-to directive instead.',
                    FindingSeverity.INFO, csp.directive.REPORT_URI))
            return findings
        return []
Esempio n. 28
0
    def check(self, headers, opt_options=dict()):
        findings = []
        hsts = self.gethsts(headers)

        if not hsts:
            return findings
        if not hsts.includesubdomains():
            return [
                Finding(HSTS.headerkey, FindingType.NO_SUBDOMAINS,
                        'include subdomains was not specified.',
                        FindingSeverity.LOW, HSTS.directive.INCLUDESUBDOMAINS)
            ]

        return findings
Esempio n. 29
0
    def check(self, headers, opt_options=dict()):
        findings = []
        expectct = self.getexpectct(headers)

        if not expectct:
            return findings

        findings = []
        if expectct.reporturi() and expectct.reporturi().startswith('http://'):
            findings.append(
                Finding(
                    expectct.headerkey, FindingType.SRC_HTTP,
                    expectct.headerkey +
                    'communicates its reports via an insecure channel.',
                    FindingSeverity.LOW, expectct.reporturi()))
        return findings
    def check(self, headers, opt_options=dict()):
        headers = self.getexposeheaders(headers)
        if not headers:
            return []

        result = []
        for header in headers.headers():
            if self.__issensitive__(header):
                result.append(
                    Finding(
                        AccessControlExposeHeaders.headerkey,
                        FindingType.SENSITIVE_HEADER_EXPOSED,
                        str(AccessControlExposeHeaders.headerkey) +
                        " exposes sensitive headers to JavaScript. An attacker can deceive the victim into browsing to an untrusted origin containing JavaScript that makes an HTTP request to the target origin. The malicious JavaScript code reads the value of the sensitive header and shares it with the attacker. If the header contains session information, the attacker can hijack the victim's session.",
                        FindingSeverity.MEDIUM, str(header), None))
        return result