Ejemplo n.º 1
0
    def test_run_skips_disabled_yara_rules(self):
        assert len(ScannerResult.objects.all()) == 0
        # This rule should match for all files in the xpi but it is disabled.
        ScannerRule.objects.create(
            name='always_true',
            scanner=YARA,
            definition='rule always_true { condition: true }',
            is_active=False,
        )

        run_yara(self.results, self.upload.pk)

        yara_result = ScannerResult.objects.all()[0]
        assert yara_result.upload == self.upload
        assert len(yara_result.results) == 0
Ejemplo n.º 2
0
    def test_does_not_run_when_results_contain_errors(self, yara_compile_mock):
        self.results.update({'errors': 1})
        received_results = run_yara(self.results, self.upload.pk)

        assert not yara_compile_mock.called
        # The task should always return the results.
        assert received_results == self.results
Ejemplo n.º 3
0
    def test_run_with_mocks(self, incr_mock):
        assert len(ScannerResult.objects.all()) == 0

        # This compiled rule will match for all files in the xpi.
        rules = yara.compile(source='rule always_true { condition: true }')
        with mock.patch('yara.compile') as yara_compile_mock:
            yara_compile_mock.return_value = rules
            received_results = run_yara(self.results, self.upload.pk)

        assert yara_compile_mock.called
        yara_results = ScannerResult.objects.all()
        assert len(yara_results) == 1
        yara_result = yara_results[0]
        assert yara_result.upload == self.upload
        assert len(yara_result.matches) == 2
        assert yara_result.matches[0] == {
            'rule': 'always_true',
            'tags': [],
            'meta': {'filename': 'index.js'},
        }
        assert yara_result.matches[1] == {
            'rule': 'always_true',
            'tags': [],
            'meta': {'filename': 'manifest.json'},
        }
        assert incr_mock.called
        assert incr_mock.call_count == 2
        incr_mock.assert_has_calls(
            [
                mock.call('devhub.yara.has_matches'),
                mock.call('devhub.yara.success'),
            ]
        )
        # The task should always return the results.
        assert received_results == self.results
Ejemplo n.º 4
0
    def test_run_in_binary_mode(self):
        self.upload = self.get_upload('webextension_with_image.zip')

        assert len(ScannerResult.objects.all()) == 0
        # This rule will match for all PNG files in the xpi.
        rule = ScannerRule.objects.create(
            name='match_png',
            scanner=YARA,
            definition='rule match_png { '
            'strings: $png = { 89 50 4E 47 0D 0A 1A 0A } '
            'condition: $png at 0 }',
        )

        received_results = run_yara(self.results, self.upload.pk)

        yara_results = ScannerResult.objects.all()
        assert len(yara_results) == 1
        yara_result = yara_results[0]
        assert yara_result.upload == self.upload
        assert len(yara_result.results) == 1
        assert yara_result.results[0] == {
            'rule': rule.name,
            'tags': [],
            'meta': {'filename': 'img.png'},
        }
        # The task should always return the results.
        assert received_results == self.results
Ejemplo n.º 5
0
    def test_run_is_manifest(self, incr_mock):
        assert len(ScannerResult.objects.all()) == 0
        # This rule will match for just the manifest.json
        rule = ScannerRule.objects.create(
            name='is_manifest_true',
            scanner=YARA,
            # 'is_manifest_file' is an external variable we automatically
            # provide.
            definition='rule is_manifest_true { condition: is_manifest_file }',
        )

        received_results = run_yara(self.results, self.upload.pk)

        yara_results = ScannerResult.objects.all()
        assert len(yara_results) == 1
        yara_result = yara_results[0]
        assert yara_result.upload == self.upload
        assert len(yara_result.results) == 1
        assert yara_result.results[0] == {
            'rule': rule.name,
            'tags': [],
            'meta': {'filename': 'manifest.json'},
        }
        assert incr_mock.called
        assert incr_mock.call_count == 3
        incr_mock.assert_has_calls(
            [
                mock.call('devhub.yara.has_matches'),
                mock.call(f'devhub.yara.rule.{rule.id}.match'),
                mock.call('devhub.yara.success'),
            ]
        )
        # The task should always return the results.
        assert received_results == self.results
Ejemplo n.º 6
0
    def test_run_with_invalid_filename(self, incr_mock):
        assert len(ScannerResult.objects.all()) == 0
        # This rule will match for all files in the xpi.
        rule = ScannerRule.objects.create(
            name='always_true',
            scanner=YARA,
            definition='rule always_true { condition: true }',
        )
        self.upload = self.get_upload('archive-with-invalid-chars-in-filenames.zip')

        received_results = run_yara(self.results, self.upload.pk)

        yara_results = ScannerResult.objects.all()
        assert len(yara_results) == 1
        yara_result = yara_results[0]
        assert yara_result.upload == self.upload
        assert len(yara_result.results) == 1
        print(yara_result.results[0])
        assert yara_result.results[0] == {
            'rule': rule.name,
            'tags': [],
            'meta': {'filename': 'path\\to\\file.txt'},
        }
        # The task should always return the results.
        assert received_results == self.results
Ejemplo n.º 7
0
    def test_run_does_not_raise(self, incr_mock, yara_compile_mock):
        yara_compile_mock.side_effect = Exception()

        received_results = run_yara(self.results, self.upload.pk)

        assert incr_mock.called
        incr_mock.assert_called_with('devhub.yara.failure')
        # The task should always return the results.
        assert received_results == self.results
Ejemplo n.º 8
0
    def test_run_does_not_raise(self, incr_mock):
        # This call should not raise even though there will be an error because
        # YARA_RULES_FILEPATH is configured with a wrong path.
        received_results = run_yara(self.results, self.upload.pk)

        assert incr_mock.called
        incr_mock.assert_called_with('devhub.yara.failure')
        # The task should always return the results.
        assert received_results == self.results
Ejemplo n.º 9
0
    def test_skip_non_webextensions_with_mocks(self, yara_compile_mock):
        upload = self.get_upload('search.xml')
        results = {
            **amo.VALIDATOR_SKELETON_RESULTS,
            'metadata': {'is_webextension': False},
        }

        received_results = run_yara(results, upload.pk)

        assert not yara_compile_mock.called
        # The task should always return the results.
        assert received_results == results
Ejemplo n.º 10
0
    def test_run_no_matches_with_mocks(self, incr_mock):
        assert len(ScannerResult.objects.all()) == 0

        # This compiled rule will never match.
        rules = yara.compile(source='rule always_false { condition: false }')
        with mock.patch('yara.compile') as yara_compile_mock:
            yara_compile_mock.return_value = rules
            received_results = run_yara(self.results, self.upload.pk)

        yara_result = ScannerResult.objects.all()[0]
        assert yara_result.results == []
        # The task should always return the results.
        assert received_results == self.results
        assert incr_mock.called
        assert incr_mock.call_count == 1
        incr_mock.assert_called_with('devhub.yara.success')
Ejemplo n.º 11
0
    def test_run_no_matches(self, incr_mock):
        assert len(ScannerResult.objects.all()) == 0
        # This compiled rule will never match.
        ScannerRule.objects.create(
            name='always_false',
            scanner=YARA,
            definition='rule always_false { condition: false }',
        )

        received_results = run_yara(self.results, self.upload.pk)

        yara_result = ScannerResult.objects.all()[0]
        assert yara_result.results == []
        # The task should always return the results.
        assert received_results == self.results
        assert incr_mock.called
        assert incr_mock.call_count == 1
        incr_mock.assert_called_with('devhub.yara.success')
Ejemplo n.º 12
0
    def test_run_ignores_directories(self):
        upload = self.get_upload('webextension_signed_already.xpi')
        results = {
            **amo.VALIDATOR_SKELETON_RESULTS,
            'metadata': {'is_webextension': True},
        }
        # This compiled rule will match for all files in the xpi.
        rules = yara.compile(source='rule always_true { condition: true }')

        with mock.patch('yara.compile') as yara_compile_mock:
            yara_compile_mock.return_value = rules
            received_results = run_yara(results, upload.pk)

        yara_result = ScannerResult.objects.all()[0]
        assert yara_result.upload == upload
        # The `webextension_signed_already.xpi` fixture file has 1 directory
        # and 3 files.
        assert len(yara_result.results) == 3
        # The task should always return the results.
        assert received_results == results
Ejemplo n.º 13
0
    def test_run_ignores_directories(self):
        upload = self.get_upload('webextension_signed_already.xpi')
        results = {
            **amo.VALIDATOR_SKELETON_RESULTS,
        }
        # This rule will match for all files in the xpi.
        ScannerRule.objects.create(
            name='always_true',
            scanner=YARA,
            definition='rule always_true { condition: true }',
        )

        received_results = run_yara(results, upload.pk)

        yara_result = ScannerResult.objects.all()[0]
        assert yara_result.upload == upload
        # The `webextension_signed_already.xpi` fixture file has 1 directory
        # and 3 files.
        assert len(yara_result.results) == 3
        # The task should always return the results.
        assert received_results == results
Ejemplo n.º 14
0
    def test_run_in_non_binary_mode_with_binary(self):
        self.upload = self.get_upload('webextension_with_image.zip')

        assert len(ScannerResult.objects.all()) == 0
        # This rule will match for all PNG files in the xpi.
        ScannerRule.objects.create(
            name='match_png',
            scanner=YARA,
            definition='rule match_png { '
            'strings: $png = { 89 50 4E 47 0D 0A 1A 0A } '
            'condition: $png at 0 }',
        )

        received_results = run_yara(self.results, self.upload.pk)

        yara_result = ScannerResult.objects.all()[0]
        # We don't match here, as decoding the bytes leads to missing the rule.
        assert yara_result.results == []

        # The task should always return the results.
        assert received_results == self.results
Ejemplo n.º 15
0
    def test_run(self, incr_mock):
        assert len(ScannerResult.objects.all()) == 0
        # This rule will match for all files in the xpi.
        rule = ScannerRule.objects.create(
            name='always_true',
            scanner=YARA,
            definition='rule always_true { condition: true }',
        )

        received_results = run_yara(self.results, self.upload.pk)

        yara_results = ScannerResult.objects.all()
        assert len(yara_results) == 1
        yara_result = yara_results[0]
        assert yara_result.upload == self.upload
        assert len(yara_result.results) == 2
        assert yara_result.results[0] == {
            'rule': rule.name,
            'tags': [],
            'meta': {
                'filename': 'index.js'
            },
        }
        assert yara_result.results[1] == {
            'rule': rule.name,
            'tags': [],
            'meta': {
                'filename': 'manifest.json'
            },
        }
        assert incr_mock.called
        assert incr_mock.call_count == 3
        incr_mock.assert_has_calls([
            mock.call('devhub.yara.has_matches'),
            mock.call(f'devhub.yara.rule.{rule.id}.match'),
            mock.call('devhub.yara.success'),
        ])
        # The task should always return the results.
        assert received_results == self.results
Ejemplo n.º 16
0
    def test_run_is_locale_file(self, incr_mock):
        self.upload = self.get_upload('notify-link-clicks-i18n.xpi')
        assert len(ScannerResult.objects.all()) == 0
        # This rule will match for all _locales/*/messages.json files
        rule = ScannerRule.objects.create(
            name='is_locale_true',
            scanner=YARA,
            # 'is_locale_file' is an external variable we automatically
            # provide.
            definition='rule is_locale_true { condition: is_locale_file }',
        )

        received_results = run_yara(self.results, self.upload.pk)

        yara_results = ScannerResult.objects.all()
        assert len(yara_results) == 1
        yara_result = yara_results[0]
        assert yara_result.upload == self.upload
        assert len(yara_result.results) == 7
        assert yara_result.results[0] == {
            'rule': rule.name,
            'tags': [],
            'meta': {'filename': '_locales/de/messages.json'},
        }
        assert yara_result.results[1] == {
            'rule': rule.name,
            'tags': [],
            'meta': {'filename': '_locales/en/messages.json'},
        }
        assert yara_result.results[2] == {
            'rule': rule.name,
            'tags': [],
            'meta': {'filename': '_locales/ja/messages.json'},
        }
        assert yara_result.results[3] == {
            'rule': rule.name,
            'tags': [],
            'meta': {'filename': '_locales/nb_NO/messages.json'},
        }
        assert yara_result.results[4] == {
            'rule': rule.name,
            'tags': [],
            'meta': {'filename': '_locales/nl/messages.json'},
        }
        assert yara_result.results[5] == {
            'rule': rule.name,
            'tags': [],
            'meta': {'filename': '_locales/ru/messages.json'},
        }
        assert yara_result.results[6] == {
            'rule': rule.name,
            'tags': [],
            'meta': {'filename': '_locales/sv/messages.json'},
        }
        assert incr_mock.called
        assert incr_mock.call_count == 3
        incr_mock.assert_has_calls(
            [
                mock.call('devhub.yara.has_matches'),
                mock.call(f'devhub.yara.rule.{rule.id}.match'),
                mock.call('devhub.yara.success'),
            ]
        )
        # The task should always return the results.
        assert received_results == self.results
Ejemplo n.º 17
0
    def test_calls_statsd_timer(self, timer_mock):
        run_yara(self.results, self.upload.pk)

        assert timer_mock.called
        timer_mock.assert_called_with('devhub.yara')