コード例 #1
0
 def testDirective_eq(self):
     srcExpr1 = URISourceExpression("http", "seclab.nu", "*", None)
     srcExpr2 = URISourceExpression("https", "seclab.nu", 443, "/")
     directive1a = Directive("object-src", [srcExpr1, srcExpr2])
     directive1b = Directive("object-src", [srcExpr2, srcExpr1])
     directive2 = Directive("frame-src", [srcExpr1, srcExpr2])
     directive3 = Directive("object-src", [srcExpr2])
     directive4a = Directive("script-src",
                             (SourceExpression.UNSAFE_INLINE(), ))
     directive4b = Directive("script-src",
                             (SourceExpression("unsafe-inline"), ))
     assert directive1a == directive1b
     assert hash(directive1a) == hash(directive1b)
     assert directive1a != directive2
     assert directive1a != directive3
     assert directive2 != directive3
     assert directive4a == directive4b
     assert hash(directive4a) == hash(directive4b)
     assert Directive.INVALID() == Directive.INVALID()
     assert Directive.INVALID() not in (directive1a, directive1b,
                                        directive2, directive3)
     assert Directive.INLINE_STYLE_BASE_RESTRICTION() not in (directive1a,
                                                              directive1b,
                                                              directive2,
                                                              directive3)
コード例 #2
0
 def test_EvalInlineSourceExpression_eq(self):
     assert SourceExpression.UNSAFE_EVAL() == SourceExpression.UNSAFE_EVAL()
     assert hash(SourceExpression.UNSAFE_EVAL()) \
         == hash(SourceExpression.UNSAFE_EVAL())
     assert SourceExpression.UNSAFE_INLINE(
     ) == SourceExpression.UNSAFE_INLINE()
     assert hash(SourceExpression.UNSAFE_INLINE()) \
         == hash(SourceExpression.UNSAFE_INLINE())
     assert SourceExpression.UNSAFE_INLINE(
     ) != SourceExpression.UNSAFE_EVAL()
コード例 #3
0
 def testDirectiveParser_parse_standard(self):
     assert DirectiveParser(strict=True).parse("default-src https: 'unsafe-inline' 'unsafe-eval'") \
         == Directive("default-src", [URISourceExpression("https", None, None, None),
                                      SourceExpression.UNSAFE_INLINE(), SourceExpression.UNSAFE_EVAL()])
     assert DirectiveParser(strict=True).parse("default-src 'self'") \
         == Directive("default-src", [SelfSourceExpression.SELF()])
     assert DirectiveParser(strict=True).parse("img-src *") \
         == Directive("img-src", [URISourceExpression(None, "*", None, None)])
     assert DirectiveParser(strict=True).parse("object-src media1.example.com media2.example.com *.cdn.example.com") \
         == Directive("object-src", [URISourceExpression(None, "media1.example.com", None, None),
                                     URISourceExpression(None, "media2.example.com", None, None),
                                     URISourceExpression(None, "*.cdn.example.com", None, None)])
コード例 #4
0
 def test_EvalInlineSourceExpression_match(self):
     """The source expressions 'unsafe-inline' and 'unsafe-eval' do not match any URI."""
     srcExprEval = SourceExpression.UNSAFE_EVAL()
     srcExprInline = SourceExpression.UNSAFE_INLINE()
     selfURI = SourceExpressionTest.uri_chromeExtension
     assert not srcExprEval.matches(SourceExpressionTest.uri_empty, selfURI)
     assert not srcExprInline.matches(SourceExpressionTest.uri_empty,
                                      selfURI)
     assert not srcExprEval.matches(URI.INVALID(), selfURI)
     assert not srcExprInline.matches(URI.INVALID(), selfURI)
     assert srcExprInline.matches(URI.INLINE(), selfURI)
     assert not srcExprInline.matches(URI.EVAL(), selfURI)
     assert not srcExprEval.matches(URI.INLINE(), selfURI)
     assert srcExprEval.matches(URI.EVAL(), selfURI)
コード例 #5
0
ファイル: test_fileio.py プロジェクト: PandaBearz/csp-utils
class PolicyDataReaderTest(unittest.TestCase):

    samplePolicy = Policy([
        Directive("default-src", ()),
        Directive("style-src", [SourceExpression.UNSAFE_INLINE()]),
        Directive("img-src",
                  [URISourceExpression(None, "seclab.nu", "*", None)])
    ])

    @pytest.fixture(autouse=True)
    def initdir(self, tmpdir):
        tmpdir.chdir()

    def setUp(self):
        self.fileIn = PolicyDataReader(True)
        self.filename = "policystorage.dat"
        self.fileOut = DataWriter(self.filename)

    def testReportCreation(self):
        """Writes a LogEntry and loads it back as an object."""
        self.fileOut.storeAll([PolicyDataReaderTest.samplePolicy])
        self.fileOut.close()
        dataOut = self.fileIn.loadAll(self.filename)
        assert len(dataOut) == 1
        assert PolicyDataReaderTest.samplePolicy in dataOut
コード例 #6
0
 def test_URISourceExpression_schemeOnly(self):
     srcExprFull = URISourceExpression("chrome-extension",
                                       "mkfokfffehpeedafpekjeddnmnjhmcmk",
                                       None, None)
     assert srcExprFull.schemeOnly() == URISourceExpression(
         "chrome-extension", None, None, None)
     srcExprIncomplete = URISourceExpression(None, "seclab.nu", None, None)
     assert srcExprIncomplete.schemeOnly() == SourceExpression.INVALID()
コード例 #7
0
 def test_URISourceExpression_eq(self):
     srcExprFull1 = URISourceExpression("http", "seclab.nu", 80, "/")
     srcExprFull2 = URISourceExpression("http", "seclab.nu", 80, "/")
     assert srcExprFull1 == srcExprFull2
     assert hash(srcExprFull1) == hash(srcExprFull2)
     srcExprStar = URISourceExpression("http", "*.seclab.nu", None, None)
     assert srcExprFull1 != srcExprStar
     assert srcExprFull1 != SourceExpression.UNSAFE_EVAL()
コード例 #8
0
ファイル: test_fileio.py プロジェクト: PandaBearz/csp-utils
class ReportDataReaderTest(unittest.TestCase):

    sampleURI1a = URI("http", "seclab.nu", None, None, None)
    sampleURI1b = URI("http", "seclab.nu", None, None, None)
    sampleURI2 = URI("http", "seclab.nu", None, "/blocked", "query")
    sampleDirective1a = Directive("default-src", ())
    sampleDirective1b = Directive("default-src", ())
    sampleDirective2a = Directive("script-src",
                                  (SourceExpression.UNSAFE_INLINE(), ))
    sampleDirective2b = Directive("script-src",
                                  (SourceExpression.UNSAFE_INLINE(), ))
    samplePolicy1a = Policy((sampleDirective1a, sampleDirective2a))
    samplePolicy1b = Policy((sampleDirective1b, sampleDirective2b))
    samplePolicy2 = Policy((sampleDirective1a, ))

    @pytest.fixture(autouse=True)
    def initdir(self, tmpdir):
        tmpdir.chdir()

    def setUp(self):
        self.fileIn = ReportDataReader(True)
        self.filename = "encodingdecoding.dat"
        self.fileOut = DataWriter(self.filename)

    def tearDown(self):
        pass

    def testReportCreation(self):
        """Writes a Report and loads it back as an object."""
        report = Report({
            "abc": True,
            "def": 1,
            "ghi": "http://seclab.nu/",
            "document-uri": ReportDataReaderTest.sampleURI1a,
            "violated-directive": ReportDataReaderTest.sampleDirective1a,
            "original-policy": ReportDataReaderTest.samplePolicy1a,
            "blocked-uri": ReportDataReaderTest.sampleURI2
        })
        self.fileOut.storeAll([report])
        self.fileOut.close()
        dataOut = self.fileIn.loadAll(self.filename)
        assert len(dataOut) == 1
        print report
        print dataOut[0]
        assert report in dataOut
コード例 #9
0
 def testPolicy_compareTo_recursive(self):
     pol1 = Policy([PolicyTest.sampleDirective6])
     pol2 = Policy(
         [Directive("style-src", [SourceExpression.UNSAFE_INLINE()])])
     assert pol1.compareTo(pol2) == (
         set([pol2]),
         set([
             Policy([Directive("style-src", [SelfSourceExpression.SELF()])])
         ]), set([]))
コード例 #10
0
 def testPolicy_combinedPolicy_normal(self):
     pol1 = Policy([
         PolicyTest.sampleDirective6, PolicyTest.sampleDirective2,
         PolicyTest.sampleDirective3
     ])
     pol2 = Policy(
         [PolicyTest.sampleDirective4, PolicyTest.sampleDirective7])
     expected = Policy([
         PolicyTest.sampleDirective6, PolicyTest.sampleDirective3,
         Directive("script-src", [
             SourceExpression.UNSAFE_EVAL(),
             SourceExpression.UNSAFE_INLINE()
         ])
     ])
     assert pol1.combinedPolicy(pol1) == pol1
     assert pol2.combinedPolicy(pol2) == pol2
     assert pol1.combinedPolicy(pol2) == expected
     assert pol2.combinedPolicy(pol1) == expected
コード例 #11
0
 def testPolicy_combinedPolicy_validDefaultSrcOnly(self):
     """Combination of two policies with default directive is possible only if both policies contain
     only a default directive."""
     pol1 = Policy([PolicyTest.sampleDirective1a])
     pol2 = Policy([PolicyTest.sampleDirective9])
     expected = Policy([
         Directive("default-src", [
             PolicyTest.sampleSourceExpression1,
             SourceExpression.UNSAFE_INLINE()
         ])
     ])
     assert pol1.combinedPolicy(pol2) == expected
     assert pol2.combinedPolicy(pol1) == expected
コード例 #12
0
 def test_InvalidSourceExpression_match(self):
     """The invalid source expression does not match anything."""
     srcExpr = SourceExpression.INVALID()
     selfURI = SourceExpressionTest.uri_chromeExtension
     assert not srcExpr.matches(SourceExpressionTest.uri_empty, selfURI)
     assert not srcExpr.matches(SourceExpressionTest.uri_urlFull, selfURI)
     assert not srcExpr.matches(SourceExpressionTest.uri_urlSubstring,
                                selfURI)
     assert not srcExpr.matches(SourceExpressionTest.uri_domain, selfURI)
     assert not srcExpr.matches(SourceExpressionTest.uri_data, selfURI)
     assert not srcExpr.matches(URI.INVALID(), selfURI)
     assert not srcExpr.matches(URI.EVAL(), selfURI)
     assert not srcExpr.matches(URI.INLINE(), selfURI)
コード例 #13
0
class ReportTest(unittest.TestCase):

    sampleURI1a = URI("http", "seclab.nu", None, None, None)
    sampleURI1b = URI("http", "seclab.nu", None, None, None)
    sampleURI2 = URI("https", "seclab.ccs.neu.edu", None, None, "query")
    sampleDirective1a = Directive("default-src",
                                  (SelfSourceExpression.SELF(), ))
    sampleDirective1b = Directive("default-src", (SelfSourceExpression(), ))
    sampleDirective2a = Directive("script-src",
                                  (SourceExpression.UNSAFE_INLINE(), ))
    sampleDirective2b = Directive("script-src",
                                  (SourceExpression.UNSAFE_INLINE(), ))
    sampleDirective3 = Directive(
        "script-src", (URISourceExpression("http", "seclab.nu", None, None), ))
    samplePolicy1a = Policy((sampleDirective1a, sampleDirective2a))
    samplePolicy1b = Policy((sampleDirective1b, sampleDirective2b))

    def testReport_str_invalid(self):
        assert str(Report.INVALID()) == "[invalid]"

    def testReport_str_regular(self):
        """Extended object types should be serialised to strings when getting the report as a string."""
        report = Report({
            "violated-directive": ReportTest.sampleDirective2a,
            "original-policy": ReportTest.samplePolicy1a
        })
        assert str(report) == """{"original-policy": "default-src 'self'; script-src 'unsafe-inline'",""" \
                                + """ "violated-directive": "script-src 'unsafe-inline'"}"""

    def testReport_str_primitives(self):
        """A Report with basic data types in it (instead of strings) should have them serialised
        to JSON-supported basic data types, not all strings."""
        report = Report({"abc": True, "def": 1, "ghi": ReportTest.sampleURI1a})
        expected = """{"abc": true, "def": 1, "ghi": "http://seclab.nu"}"""
        assert str(report) == expected

    def testReport_dict_iterateAndImmutable(self):
        report = Report({
            "violated-directive": ReportTest.sampleDirective2a,
            "original-policy": ReportTest.samplePolicy1a
        })
        assert len(report) == 2
        assert "violated-directive" in report
        assert report["violated-directive"] == ReportTest.sampleDirective2a
        assert "original-policy" in report
        assert report["original-policy"] == ReportTest.samplePolicy1a
        for (key, value) in report.iteritems():
            assert key in ("violated-directive", "original-policy")
            assert value in (ReportTest.sampleDirective2a,
                             ReportTest.samplePolicy1a)
        with pytest.raises(TypeError):
            report["original-policy"] = None
        with pytest.raises(TypeError):
            report["something-else"] = 123

    def testReport_eq(self):
        report1a = Report({
            "violated-directive": ReportTest.sampleDirective2a,
            "original-policy": ReportTest.samplePolicy1a
        })
        report1b = Report({
            "violated-directive": ReportTest.sampleDirective2b,
            "original-policy": ReportTest.samplePolicy1b
        })
        report2 = Report({
            "violated-directive": ReportTest.sampleDirective1a,
            "original-policy": ReportTest.samplePolicy1a
        })

        assert report1a == report1b
        assert hash(report1a) == hash(report1b)
        assert report1a != report2
        assert report1a != Report.INVALID()
        assert report2 != Report.INVALID()

    def testReport_generatePolicy_regular(self):
        report = Report({
            "blocked-uri": ReportTest.sampleURI1a,
            "violated-directive": ReportTest.sampleDirective2a,
            "document-uri": ReportTest.sampleURI2
        })
        assert report.generatePolicy("regular") == Policy(
            [ReportTest.sampleDirective3])

    def testReport_generatePolicy_invalid(self):
        assert Report.INVALID().generatePolicy("regular") == Policy.INVALID()

    def testReport_generatePolicy_missingReportField(self):
        reportNoViolated = Report({
            "blocked-uri": ReportTest.sampleURI1a,
            "document-uri": ReportTest.sampleURI2
        })
        reportNoBlocked = Report({
            "violated-directive": ReportTest.sampleDirective2a,
            "document-uri": ReportTest.sampleURI2
        })
        assert reportNoViolated.generatePolicy("regular") == Policy.INVALID()
        assert reportNoBlocked.generatePolicy("regular") == Policy.INVALID()

    def testReport_generatePolicy_fromInvalidDirectiveResult(self):
        reportDefaultSrc = Report({
            "blocked-uri": ReportTest.sampleURI1a,
            "violated-directive": ReportTest.sampleDirective1a,
            "document-uri": ReportTest.sampleURI2
        })
        assert reportDefaultSrc.generatePolicy("regular") == Policy.INVALID()

    def testReport_generatePolicy_wrongDocumentURI(self):
        reportEmptyDocument = Report({
            "blocked-uri": ReportTest.sampleURI1a,
            "violated-directive": ReportTest.sampleDirective1a,
            "document-uri": URI.EMPTY()
        })
        assert reportEmptyDocument.generatePolicy(
            "regular") == Policy.INVALID()

    def testReportParser_parse_typeFields(self):
        """Check that type indications for fields are properly parsed."""
        report = """{"uri": "https://seclab.ccs.neu.edu?query", "directive": "script-src 'unsafe-inline'",""" \
                + """ "policy": "script-src 'unsafe-inline'; default-src 'self'",""" \
                + """ "nothing": "123"}"""
        cspReport = ReportParser(uriKeys=["uri", "url"],
                                 directiveKeys=["directive"],
                                 policyKeys=["policy"],
                                 requiredKeys=[],
                                 strict=True).parseString(report)
        expected = Report({
            "uri": ReportTest.sampleURI2,
            "directive": ReportTest.sampleDirective2a,
            "policy": ReportTest.samplePolicy1a,
            "nothing": "123"
        })
        assert cspReport == expected

    def testReportParser_parse_stringVsJSON(self):
        """Ensure the string parsing returns the same result as JSON parsing."""
        reportJSON = {"something": 123, "uri": "http://seclab.nu"}
        reportString = """{"something": 123, "uri": "http://seclab.nu"}"""
        expected = Report({"something": 123, "uri": ReportTest.sampleURI1a})
        parser = ReportParser(uriKeys=["uri"], requiredKeys=[], strict=True)
        parsedFromJSON = parser.parseJsonDict(reportJSON)
        parsedFromString = parser.parseString(reportString)
        print parsedFromJSON
        print parsedFromString
        assert parsedFromJSON == parsedFromString
        assert parsedFromJSON == expected

    def testReportParser_parse_fieldNameReplacements(self):
        """Checks that old field names are replaced correctly."""
        report = """{"document-url": "http://seclab.nu", "original-policy": "default-src 'self'; script-src 'unsafe-inline'"}"""
        expected = Report({
            "document-uri": ReportTest.sampleURI1a,
            "original-policy": ReportTest.samplePolicy1a
        })
        parser = ReportParser(
            uriKeys=["document-uri"],
            policyKeys=["original-policy"],
            requiredKeys=["document-uri", "original-policy"],
            strict=True,
            keyNameReplacements={"document-url": "document-uri"})
        cspReport = parser.parseString(report)
        assert cspReport == expected

    def testReportParser_parse_requiredFields(self):
        """Required fields must be present even if strict=False."""
        report = """{"this-is": "a quite empty report"}"""
        expected = Report({"this-is": "a quite empty report"})
        assert ReportParser(requiredKeys=[],
                            strict=False).parseString(report) == expected
        assert ReportParser(
            requiredKeys=["does-not-exist"],
            strict=False).parseString(report) == Report.INVALID()

    def testReportParser_parse_emptyOrSelfURI(self):
        """This tests that the internal settings of the URI parser are chosen such that empty or self URIs are
        correctly handled."""
        report = """{"empty-uri": "", "self-uri": "self", "document-uri": "http://seclab.nu"}"""
        expected = Report({
            "empty-uri": URI.EMPTY(),
            "self-uri": ReportTest.sampleURI1a,
            "document-uri": ReportTest.sampleURI1a
        })
        assert ReportParser(requiredKeys=[], strict=True, uriKeys=["empty-uri", "self-uri", "document-uri"]) \
                        .parseString(report) == expected

    def testReportParser_parse_failIfStrict(self):
        """The report must be declared invalid in strict mode when a child element is invalid."""
        report = """{"invalid-policy": "awesomeness-src 'self'", "example": true}"""
        assert ReportParser(requiredKeys=[], strict=True, policyKeys=["invalid-policy"]) \
                        .parseString(report) == Report.INVALID()

    def testReportParser_parse_skipIfNotStrict(self):
        """Invalid portions of the report must be skipped in non-strict mode."""
        report = """{"invalid-policy": "awesomeness-src 'self'", "example": true}"""
        expected = Report({"example": True})
        assert ReportParser(requiredKeys=[], strict=False, policyKeys=["invalid-policy"]) \
                        .parseString(report) == expected

    def testReportParser_parse_inferSelfURI(self):
        """Tests if the self URI is correctly inferred from the "document-uri" field (even
        after renaming)."""
        report = """{"violated-directive": "default-src 'self'", "referrer": "",""" \
                + """ "blocked-uri": "self", "document-URL":""" \
                + """ "http://seclab.nu"}"""
        expected = Report({
            "violated-directive": ReportTest.sampleDirective1a,
            "referrer": URI.EMPTY(),
            "blocked-uri": ReportTest.sampleURI1a,
            "document-uri": ReportTest.sampleURI1a
        })
        parser = ReportParser(
            requiredKeys=["violated-directive", "document-uri", "blocked-uri"],
            strict=True,
            directiveKeys=["violated-directive"],
            uriKeys=["referrer", "blocked-uri", "document-uri"],
            keyNameReplacements={'document-url': 'document-uri'})
        cspReport = parser.parseString(report)
        assert cspReport == expected

    def testReportParser_parse_selfURIFailStrict(self):
        """Tests that parsing fails if strict and no document-uri but another 'self' URI."""
        report = """{"blocked-uri": "self", "other": "value"}"""
        parser = ReportParser(requiredKeys=[],
                              strict=True,
                              uriKeys=["blocked-uri", "document-uri"])
        cspReport = parser.parseString(report)
        assert cspReport == Report.INVALID()

    def testReportParser_parse_selfURISkipStrict(self):
        """Tests that parsing fails if strict and no document-uri but another 'self' URI."""
        report = """{"blocked-uri": "self", "other": "value"}"""
        expected = Report({"other": "value"})
        parser = ReportParser(requiredKeys=[],
                              strict=False,
                              uriKeys=["blocked-uri", "document-uri"])
        cspReport = parser.parseString(report)
        assert cspReport == expected

    def testReportParser_parse_unicode(self):
        """The JSON deserialiser returns strings as unicode objects. Check that they are correctly parsed in URIs."""
        fullReport = """{"remote-addr": "XXX", "policy-type": "regular", "http-user-agent":""" \
                    + """ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:27.0) Gecko/20100101 Firefox/27.0",""" \
                    + """ "timestamp-utc": "2014-03-01 12:13:14.156789", "csp-report": {"violated-directive":""" \
                    + """ "img-src 'none'", "referrer": "http://handbook5.com/a/a-security-analysis-of-amazon%E2%80%99s-elastic-compute-cloud-service-w14847.html",""" \
                    + """ "blocked-uri": "http://www.iseclab.org/images/anr.png", "document-uri":""" \
                    + """ "http://www.iseclab.org/?p"}, "header-type": "standard"}"""
        expected = Report({
            "violated-directive":
            Directive("img-src", ()),
            "referrer":
            URI(
                "http", "handbook5.com", None,
                u"/a/a-security-analysis-of-amazon’s-elastic-compute-cloud-service-w14847.html"
            ),
            "blocked-uri":
            URI("http", "www.iseclab.org", None, u"/images/anr.png"),
            "document-uri":
            URI("http", "www.iseclab.org", None, u"/", "p")
        })
        parser = ReportParser(requiredKeys=[])
        jsonReport = json.loads(fullReport)
        cspReport = parser.parseJsonDict(jsonReport["csp-report"])
        assert cspReport == expected
コード例 #14
0
 def test_EvalSourceExpression_str(self):
     srcExprEval = SourceExpression.UNSAFE_EVAL()
     assert str(srcExprEval) == "'unsafe-eval'"
コード例 #15
0
 def test_InlineSourceExpression_str(self):
     srcExprInline = SourceExpression.UNSAFE_INLINE()
     assert str(srcExprInline) == "'unsafe-inline'"
コード例 #16
0
 def test_SelfSourceExpression_eq(self):
     srcExpr1 = SelfSourceExpression()
     srcExpr2 = SelfSourceExpression.SELF()
     assert srcExpr1 == srcExpr2
     assert hash(srcExpr1) == hash(srcExpr2)
     assert srcExpr1 != SourceExpression.UNSAFE_EVAL()
コード例 #17
0
 def testDirective_init_removeInvalidSourceExpressions(self):
     assert Directive("img-src", [SourceExpression.INVALID()]) == Directive(
         "img-src", [])
コード例 #18
0
 def test_parse_unsupported_scheme_fails(self):
     exprStr = "my-scheme://domain/path"
     srcExpr = SourceExpressionParser(knownSchemes=('http',
                                                    'https')).parse(exprStr)
     assert srcExpr == SourceExpression.INVALID()
コード例 #19
0
 def testDirective_generateDirective_eval_special(self):
     violated = Directive.EVAL_SCRIPT_BASE_RESTRICTION()
     generated = violated.generateDirective("eval",
                                            DirectiveTest.sampleURI2)
     assert generated == Directive("script-src",
                                   [SourceExpression.UNSAFE_EVAL()])
コード例 #20
0
 def testDirective_generateDirective_eval(self):
     violated = Directive("script-src", [DirectiveTest.sampleSrcExpr1a])
     generated = violated.generateDirective("eval", URI.EMPTY())
     assert generated == Directive("script-src",
                                   [SourceExpression.UNSAFE_EVAL()])
コード例 #21
0
 def testDirective_generateDirective_inline(self):
     violated = Directive("style-src", [DirectiveTest.sampleSrcExpr2])
     generated = violated.generateDirective("inline", URI.EMPTY())
     assert generated == Directive("style-src",
                                   [SourceExpression.UNSAFE_INLINE()])
コード例 #22
0
ファイル: test_log.py プロジェクト: PandaBearz/csp-utils
 def testLogEntry_generatePolicy_standard(self):
     assert LogEntryTest.cspLogEntry.generatePolicy() == Policy(
         [Directive("style-src", [SourceExpression.UNSAFE_INLINE()])])
コード例 #23
0
ファイル: test_log.py プロジェクト: PandaBearz/csp-utils
class LogEntryTest(unittest.TestCase):

    starSourceExpr = URISourceExpression(None, "*", None, None)
    strLogEntry = """{"csp-report": {"blocked-uri": "", "document-uri": "http://seclab.nu/csp-test.html", """ \
                        + """"original-policy": "default-src *; script-src 'unsafe-eval' *; style-src *", """ \
                        + """"referrer": "", "status-code": 200, "violated-directive": "style-src *"}, """ \
                        + """"header-type": "webkit", "http-user-agent": """ \
                        + """"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_5) AppleWebKit/537.36 (KHTML, """ \
                        + """like Gecko) Chrome/31.0.1650.63 Safari/537.36", "policy-type": "inline", """ \
                        + """"remote-addr": "1.2.3.4", "timestamp-utc": "2013-12-14 01:02:03.456789"}"""
    logEntryData = {u"csp-report": Report({u"document-uri": URI("http", "seclab.nu", None, u"/csp-test.html"),
                                                  u"referrer": URI.EMPTY(),
                                                  u"violated-directive": Directive("style-src",
                                                                                  (starSourceExpr,)),
                                                  u"original-policy": Policy((Directive("default-src",
                                                                                       (starSourceExpr,)),
                                                                             Directive("script-src",
                                                                                       (starSourceExpr,
                                                                                        SourceExpression.UNSAFE_EVAL())),
                                                                             Directive("style-src",
                                                                                       (starSourceExpr,)))),
                                                  u"blocked-uri": URI.EMPTY(),
                                                  u"status-code": 200
                                                  }),
                            u"remote-addr": u"1.2.3.4",
                            u"http-user-agent": u"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_5) " \
                                + u"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36",
                            u"timestamp-utc": u"2013-12-14 01:02:03.456789",
                            u"policy-type": u"inline",
                            u"header-type": u"webkit"
                            }
    cspLogEntry = LogEntry(logEntryData)

    def testLogEntry_str_invalid(self):
        assert str(LogEntry.INVALID()) == "[invalid]"

    def testLogEntry_str_regular(self):
        assert str(LogEntryTest.cspLogEntry) == LogEntryTest.strLogEntry

    def testLogEntry_dict_iterateAndImmutable(self):
        assert len(LogEntryTest.cspLogEntry) == 6
        assert "http-user-agent" in LogEntryTest.cspLogEntry
        assert LogEntryTest.cspLogEntry["remote-addr"] == "1.2.3.4"
        for key in LogEntryTest.cspLogEntry.keys():
            assert key in ("csp-report", "remote-addr", "http-user-agent",
                           "timestamp-utc", "policy-type", "header-type")
        with pytest.raises(TypeError):
            LogEntryTest.cspLogEntry["csp-report"] = None
        with pytest.raises(TypeError):
            LogEntryTest.cspLogEntry["something-else"] = 123

    def testLogEntry_eq(self):
        assert LogEntryTest.cspLogEntry != LogEntry.INVALID()

    def testLogEntry_generatePolicy_standard(self):
        assert LogEntryTest.cspLogEntry.generatePolicy() == Policy(
            [Directive("style-src", [SourceExpression.UNSAFE_INLINE()])])

    def testLogEntry_generatePolicy_invalid(self):
        assert LogEntry.INVALID().generatePolicy() == Policy.INVALID()

    def testLogEntry_generatePolicy_incomplete(self):
        logEntryNoReport = LogEntryTest.logEntryData.copy()
        del logEntryNoReport['csp-report']
        logEntryNoPolicyType = LogEntryTest.logEntryData.copy()
        del logEntryNoPolicyType['policy-type']
        assert LogEntry(logEntryNoReport).generatePolicy() == Policy.INVALID()
        assert LogEntry(
            logEntryNoPolicyType).generatePolicy() == Policy.INVALID()

    def testLogEntryParser_parse(self):
        parser = LogEntryParser(strict=True)
        parsed = parser.parseString(LogEntryTest.strLogEntry)
        print parsed._entryData
        print LogEntryTest.cspLogEntry._entryData
        print parsed._entryData[
            'csp-report'] == LogEntryTest.cspLogEntry._entryData['csp-report']
        assert parsed == LogEntryTest.cspLogEntry
コード例 #24
0
class PolicyTest(unittest.TestCase):

    sampleURI1a = URI("http", "seclab.nu", None, None, None)
    sampleURI1b = URI("http", "seclab.nu", None, None, None)
    sampleURI2 = URI("http", "seclab.ccs.neu.edu", None, None, None)
    sampleSourceExpression1 = URISourceExpression("http", "seclab.nu", None,
                                                  None)
    sampleSourceExpression2 = SelfSourceExpression.SELF()
    sampleDirective1a = Directive(
        "default-src",
        (URISourceExpression("http", "seclab.nu", None, None), ))
    sampleDirective1b = Directive(
        "default-src",
        (URISourceExpression("http", "seclab.nu", None, None), ))
    sampleDirective2 = Directive("script-src",
                                 (SourceExpression.UNSAFE_INLINE(), ))
    sampleDirective3 = Directive(
        "img-src", (URISourceExpression(None, "*", None, None), ))
    sampleDirective4 = Directive("img-src", ())
    sampleDirective5 = Directive(
        "connect-src",
        (SelfSourceExpression.SELF(),
         URISourceExpression("chrome-extension", None, None, None),
         URISourceExpression("https", "abc.seclab.nu", None, "/path")))
    sampleDirective6 = Directive(
        "style-src",
        (SourceExpression.UNSAFE_INLINE(), SelfSourceExpression.SELF()))
    sampleDirective7 = Directive("script-src",
                                 (SourceExpression.UNSAFE_EVAL(), ))
    sampleDirective8 = Directive("style-src", (SelfSourceExpression.SELF(), ))
    sampleDirective9 = Directive("default-src",
                                 (SourceExpression.UNSAFE_INLINE(), ))

    def testPolicy_str_invalid(self):
        assert str(Policy.INVALID()) == "[invalid]"

    def testPolicy_str_empty(self):
        assert str(Policy(())) == ""

    def testPolicy_str_normal(self):
        pol = Policy(
            (PolicyTest.sampleDirective1a, PolicyTest.sampleDirective2,
             PolicyTest.sampleDirective3))
        assert str(
            pol
        ) == "default-src http://seclab.nu; img-src *; script-src 'unsafe-inline'"

    def testPolicy_eq(self):
        pol1a = Policy(
            (PolicyTest.sampleDirective1a, PolicyTest.sampleDirective2,
             PolicyTest.sampleDirective3))
        pol1b = Policy(
            (PolicyTest.sampleDirective1b, PolicyTest.sampleDirective2,
             PolicyTest.sampleDirective3))
        pol2 = Policy(
            (PolicyTest.sampleDirective2, PolicyTest.sampleDirective3))
        assert Policy.INVALID() == Policy.INVALID()
        assert pol1a == pol1b
        assert hash(pol1a) == hash(pol1b)
        assert pol1a != pol2

    def testPolicy_init_duplicateType(self):
        pol = Policy(
            (PolicyTest.sampleDirective1a, PolicyTest.sampleDirective3,
             PolicyTest.sampleDirective4))
        directives = pol.getDirectives()
        assert PolicyTest.sampleDirective1a in directives and (PolicyTest.sampleDirective3 in directives \
                                                              or PolicyTest.sampleDirective4 in directives)

    def testPolicy_init_duplicateDirective(self):
        pol = Policy(
            (PolicyTest.sampleDirective1a, PolicyTest.sampleDirective1b,
             PolicyTest.sampleDirective2))
        assert pol == Policy(
            (PolicyTest.sampleDirective1a, PolicyTest.sampleDirective2))
        assert pol == Policy(
            (PolicyTest.sampleDirective1b, PolicyTest.sampleDirective2))

    def testPolicy_init_noDuplicatesHere(self):
        directives = set([
            PolicyTest.sampleDirective1a, PolicyTest.sampleDirective2,
            PolicyTest.sampleDirective5
        ])
        pol = Policy(directives)
        assert pol.getDirectives() == directives

    def testPolicy_init_removeNotRegularDirective(self):
        pol = Policy([
            PolicyTest.sampleDirective1a,
            Directive.INVALID(),
            Directive.EVAL_SCRIPT_BASE_RESTRICTION()
        ])
        expected = Policy([PolicyTest.sampleDirective1a])
        assert pol == expected

    def testPolicy_matches_invalid(self):
        """An invalid policy matches nothing."""
        selfURI = PolicyTest.sampleURI2
        assert not Policy.INVALID().matches(PolicyTest.sampleURI1a,
                                            "script-src", selfURI)
        assert not Policy.INVALID().matches(URI.INVALID(), "script-src",
                                            selfURI)
        assert not Policy.INVALID().matches(URI.EMPTY(), "script-src", selfURI)
        assert not Policy.INVALID().matches(URI.INLINE(), "script-src",
                                            selfURI)
        assert not Policy.INVALID().matches(URI.EVAL(), "script-src", selfURI)

    def testPolicy_matches_matchingDirectiveType(self):
        """Policy contains directive of resource type that matches."""
        pol = Policy(
            (PolicyTest.sampleDirective1a, PolicyTest.sampleDirective5))
        selfURI = PolicyTest.sampleURI2
        assert pol.matches(
            URI("https", "abc.seclab.nu", 443, "/path", "some-query"),
            "connect-src", selfURI)

    def testPolicy_matches_nonMatchingDirectiveTypeButDefaultMatches(self):
        """Policy contains directive of resource type that does not match
        and default directive that does match, but it should not be applied."""
        pol = Policy(
            (PolicyTest.sampleDirective1a, PolicyTest.sampleDirective5))
        selfURI = PolicyTest.sampleURI2
        assert not pol.matches(PolicyTest.sampleURI1a, "connect-src", selfURI)

    def testPolicy_matches_defaultSrcMatches(self):
        """Policy contains no directive of resource type, but a default directive that matches."""
        pol = Policy(
            (PolicyTest.sampleDirective1a, PolicyTest.sampleDirective5))
        selfURI = PolicyTest.sampleURI2
        assert pol.matches(PolicyTest.sampleURI1a, "script-src", selfURI)

    def testPolicy_matches_defaultSrcNoMatch(self):
        """Policy contains no directive of resource type, but a default directive.
        Default-src does not match."""
        pol = Policy((PolicyTest.sampleDirective1a, ))
        selfURI = PolicyTest.sampleURI1a
        assert not pol.matches(PolicyTest.sampleURI2, "img-src", selfURI)

    def testPolicy_matches_defaultSrcNotUsable(self):
        """Policy contains no directive of resource type, but a default directive.
        Default-src cannot be used in this case because not allowed for resource type."""
        pol = Policy((PolicyTest.sampleDirective1a, ))
        selfURI = PolicyTest.sampleURI2
        assert not pol.matches(PolicyTest.sampleURI1a, "form-action", selfURI)

    def testPolicy_matches_defaultSrcNotSpecified_match(self):
        """Policy contains no directive of resource type, and no default directive either.
        Should assume 'default-src *' (match for regular resources)."""
        pol = Policy((PolicyTest.sampleDirective5, ))
        selfURI = PolicyTest.sampleURI1a
        assert pol.matches(PolicyTest.sampleURI2, "script-src", selfURI)

    def testPolicy_matches_defaultSrcNotSpecified_noMatch(self):
        """Policy contains no directive of resource type, and no default directive either.
        Should assume 'default-src *' (no match for inline/eval resources)."""
        pol = Policy((PolicyTest.sampleDirective5, ))
        selfURI = PolicyTest.sampleURI1a
        assert not pol.matches(URI.INLINE(), "script-src", selfURI)
        assert not pol.matches(URI.EVAL(), "script-src", selfURI)

    def testPolicyParser_parse_normal(self):
        simplePolicy = """connect-src 'self' https://abc.seclab.nu/path chrome-extension:; img-src 'none'"""
        cspSimplePolicy = PolicyParser().parse(simplePolicy)
        print cspSimplePolicy
        assert cspSimplePolicy == Policy(
            [PolicyTest.sampleDirective4, PolicyTest.sampleDirective5])

    def testPolicyParser_parse_strict_onlyValidDirectives(self):
        """Ensures that a CSP policy does not parse in strict mode if it contains an invalid directive."""
        policy = """img-src 'none'; script-src"""
        cspPolicy = PolicyParser(strict=True).parse(policy)
        assert cspPolicy == Policy.INVALID()

    def testPolicyParser_parse_nonstrict_onlyValidDirectives(self):
        """Ensures that a CSP policy does ignore invalid portions in non-strict mode if it contains an invalid directive."""
        policy = """img-src 'none'; script-src"""
        cspPolicy = PolicyParser(strict=False).parse(policy)
        assert cspPolicy == Policy([PolicyTest.sampleDirective4])

    def testPolicyParser_parse_ignoredDirective(self):
        """Ensure that unsupported directives ('report-uri' etc.) are skipped without
         causing an error."""
        policy = """img-src *; report-uri /csp.cgi"""
        cspPolicy = PolicyParser(strict=True,
                                 ignoredTypes=("report-uri", )).parse(policy)
        assert cspPolicy == Policy([PolicyTest.sampleDirective3])

    def testPolicyParser_parse_defaultSrcRewriting(self):
        """The default directive is used for each type that is not specifically defined (if the flag is enabled)."""
        policy = """default-src 'self' http://seclab.nu; connect-src 'self' https://abc.seclab.nu/path chrome-extension:"""
        cspPolicy = PolicyParser(expandDefaultSrc=True,
                                 defaultSrcTypes=("img-src",
                                                  "connect-src")).parse(policy)
        assert cspPolicy == Policy([
            PolicyTest.sampleDirective5,
            Directive("img-src", [
                PolicyTest.sampleSourceExpression1,
                PolicyTest.sampleSourceExpression2
            ])
        ])

    def testPolicyParser_parse_noDefaultSrcRewriting(self):
        policy = """default-src 'self' http://seclab.nu"""
        cspPolicy = PolicyParser(expandDefaultSrc=False,
                                 defaultSrcTypes=("img-src",
                                                  "connect-src")).parse(policy)
        assert cspPolicy == Policy([
            Directive("default-src", [
                PolicyTest.sampleSourceExpression1,
                PolicyTest.sampleSourceExpression2
            ])
        ])

    def testPolicyParser_parse_duplicates(self):
        """The CSP standard mandates that only the first directive of each type should be used."""
        duplicatePolicy = """connect-src 'self' chrome-extension: https://abc.seclab.nu/path; """ \
                            + """font-src 'self' http://seclab.nu; """ \
                            + """connect-src 'self' https://example.com"""
        cspPolicy = PolicyParser().parse(duplicatePolicy)
        assert cspPolicy == Policy([
            PolicyTest.sampleDirective5,
            Directive("font-src", [
                PolicyTest.sampleSourceExpression1,
                PolicyTest.sampleSourceExpression2
            ])
        ])

    def testPolicy_combinedPolicy_normal(self):
        pol1 = Policy([
            PolicyTest.sampleDirective6, PolicyTest.sampleDirective2,
            PolicyTest.sampleDirective3
        ])
        pol2 = Policy(
            [PolicyTest.sampleDirective4, PolicyTest.sampleDirective7])
        expected = Policy([
            PolicyTest.sampleDirective6, PolicyTest.sampleDirective3,
            Directive("script-src", [
                SourceExpression.UNSAFE_EVAL(),
                SourceExpression.UNSAFE_INLINE()
            ])
        ])
        assert pol1.combinedPolicy(pol1) == pol1
        assert pol2.combinedPolicy(pol2) == pol2
        assert pol1.combinedPolicy(pol2) == expected
        assert pol2.combinedPolicy(pol1) == expected

    def testPolicy_combinedPolicy_invalidPolicy(self):
        pol = Policy([
            PolicyTest.sampleDirective1a, PolicyTest.sampleDirective2,
            PolicyTest.sampleDirective3
        ])
        assert pol.combinedPolicy(Policy.INVALID()) == Policy.INVALID()
        assert Policy.INVALID().combinedPolicy(pol) == Policy.INVALID()

    def testPolicy_combinedPolicy_invalidDefaultSrcAndOtherDirective(self):
        pol1 = Policy(
            [PolicyTest.sampleDirective1a, PolicyTest.sampleDirective3])
        pol2 = Policy([PolicyTest.sampleDirective9])
        assert pol1.combinedPolicy(pol2) == Policy.INVALID()
        assert pol2.combinedPolicy(pol1) == Policy.INVALID()

    def testPolicy_combinedPolicy_invalidDefaultSrcInOnePolicyOnly(self):
        pol1 = Policy([PolicyTest.sampleDirective3])
        pol2 = Policy([PolicyTest.sampleDirective9])
        assert pol1.combinedPolicy(pol2) == Policy.INVALID()
        assert pol2.combinedPolicy(pol1) == Policy.INVALID()

    def testPolicy_combinedPolicy_validDefaultSrcOnly(self):
        """Combination of two policies with default directive is possible only if both policies contain
        only a default directive."""
        pol1 = Policy([PolicyTest.sampleDirective1a])
        pol2 = Policy([PolicyTest.sampleDirective9])
        expected = Policy([
            Directive("default-src", [
                PolicyTest.sampleSourceExpression1,
                SourceExpression.UNSAFE_INLINE()
            ])
        ])
        assert pol1.combinedPolicy(pol2) == expected
        assert pol2.combinedPolicy(pol1) == expected

    def testPolicy_withoutPaths(self):
        withPaths = Policy([
            PolicyTest.sampleDirective3, PolicyTest.sampleDirective5,
            PolicyTest.sampleDirective7
        ])
        withoutPaths = Policy([
            PolicyTest.sampleDirective3,
            PolicyTest.sampleDirective5.withoutPaths(),
            PolicyTest.sampleDirective7
        ])
        assert withPaths.withoutPaths() == withoutPaths
        assert withoutPaths.withoutPaths() == withoutPaths
        assert Policy.INVALID().withoutPaths() == Policy.INVALID()

    def testPolicy_withoutPaths_schemeOnly(self):
        withPaths = Policy(
            [PolicyTest.sampleDirective3, PolicyTest.sampleDirective5])
        withoutPaths = Policy([
            PolicyTest.sampleDirective3,
            PolicyTest.sampleDirective5.withoutPaths(["http"])
        ])
        assert withPaths.withoutPaths(["http"]) == withoutPaths

    def testPolicy_asBasicPolicies_single(self):
        assert Policy.INVALID().asBasicPolicies() == set([])
        assert Policy([PolicyTest.sampleDirective1a]).asBasicPolicies() == set(
            [Policy([PolicyTest.sampleDirective1a])])

    def testPolicy_asBasicPolicies_multiple(self):
        assert Policy(
            [PolicyTest.sampleDirective1a,
             PolicyTest.sampleDirective2]).asBasicPolicies() == set([
                 Policy([PolicyTest.sampleDirective1a]),
                 Policy([PolicyTest.sampleDirective2])
             ])

    def testPolicy_asBasicPolicies_recursive(self):
        expected = set(
            map(lambda direct: Policy((direct, )),
                PolicyTest.sampleDirective5.asBasicDirectives()))
        actual = Policy([PolicyTest.sampleDirective5]).asBasicPolicies()
        assert actual == expected

    def testPolicy_isBasicPolicy(self):
        assert Policy.INVALID().isBasicPolicy() == False
        assert Policy([PolicyTest.sampleDirective6]).isBasicPolicy() == False
        assert Policy([PolicyTest.sampleDirective1a]).isBasicPolicy() == True
        assert Policy(
            [PolicyTest.sampleDirective2,
             PolicyTest.sampleDirective4]).isBasicPolicy() == False

    def testPolicy_isBasicNonePolicy(self):
        assert Policy.INVALID().isBasicNonePolicy() == False
        assert Policy([PolicyTest.sampleDirective6
                       ]).isBasicNonePolicy() == False
        assert Policy([PolicyTest.sampleDirective1a
                       ]).isBasicNonePolicy() == False
        assert Policy(
            [PolicyTest.sampleDirective2,
             PolicyTest.sampleDirective4]).isBasicNonePolicy() == False
        assert Policy([PolicyTest.sampleDirective4
                       ]).isBasicNonePolicy() == True

    def testPolicy_hasDefaultDirective(self):
        assert Policy.INVALID().hasDefaultDirective() == False
        assert Policy(
            [PolicyTest.sampleDirective2,
             PolicyTest.sampleDirective9]).hasDefaultDirective() == True
        assert Policy(
            [PolicyTest.sampleDirective5,
             PolicyTest.sampleDirective6]).hasDefaultDirective() == False

    def testPolicy_compareTo_invalid(self):
        assert Policy.INVALID().compareTo(Policy.INVALID()) == (set([]),
                                                                set([]),
                                                                set([]))
        pol = Policy([PolicyTest.sampleDirective9])
        assert pol.compareTo(Policy.INVALID()) == (set([]), set([]), set([]))
        assert Policy.INVALID().compareTo(pol) == (set([]), set([]), set([]))

    def testPolicy_compareTo_regular(self):
        pol1 = Policy(
            [PolicyTest.sampleDirective7, PolicyTest.sampleDirective8])
        pol2 = Policy(
            [PolicyTest.sampleDirective7, PolicyTest.sampleDirective9])
        assert pol1.compareTo(pol2) == (set([
            Policy([PolicyTest.sampleDirective7])
        ]), set([Policy([PolicyTest.sampleDirective8])
                 ]), set([Policy([PolicyTest.sampleDirective9])]))
        assert pol2.compareTo(pol1) == (set([
            Policy([PolicyTest.sampleDirective7])
        ]), set([Policy([PolicyTest.sampleDirective9])
                 ]), set([Policy([PolicyTest.sampleDirective8])]))
        assert pol1.compareTo(pol1) == (set([
            Policy([PolicyTest.sampleDirective7]),
            Policy([PolicyTest.sampleDirective8])
        ]), set([]), set([]))

    def testPolicy_compareTo_recursive(self):
        pol1 = Policy([PolicyTest.sampleDirective6])
        pol2 = Policy(
            [Directive("style-src", [SourceExpression.UNSAFE_INLINE()])])
        assert pol1.compareTo(pol2) == (
            set([pol2]),
            set([
                Policy([Directive("style-src", [SelfSourceExpression.SELF()])])
            ]), set([]))
コード例 #25
0
 def testDirective_str_regular(self):
     srcExpr1 = URISourceExpression("http", "seclab.nu", "*", None)
     srcExpr2 = SourceExpression.UNSAFE_INLINE()
     srcExpr3 = SelfSourceExpression.SELF()
     assert str(Directive("style-src", [srcExpr1, srcExpr2, srcExpr3])) \
         == "style-src 'self' 'unsafe-inline' http://seclab.nu:*"
コード例 #26
0
 def test_parse_eval(self):
     srcExpr = SourceExpressionParser().parse("'unsafe-eval'")
     assert srcExpr == SourceExpression.UNSAFE_EVAL()
     assert srcExpr.getType() == "unsafe-eval"
     assert srcExpr == SourceExpressionParser().parse("'UNSAFE-EVAL'")
コード例 #27
0
 def testDirective_generateDirective_inline_special_script(self):
     violated = Directive.INLINE_SCRIPT_BASE_RESTRICTION()
     generated = violated.generateDirective("inline",
                                            DirectiveTest.sampleURI1)
     assert generated == Directive("script-src",
                                   [SourceExpression.UNSAFE_INLINE()])
コード例 #28
0
 def test_parse_inline(self):
     srcExpr = SourceExpressionParser().parse("'unsafe-inline'")
     assert srcExpr == SourceExpression.UNSAFE_INLINE()
     assert srcExpr.getType() == "unsafe-inline"
     assert srcExpr == SourceExpressionParser().parse("'UNSAFE-INLINE'")