diff --git a/pastepwn/analyzers/__init__.py b/pastepwn/analyzers/__init__.py index 5a94eca..7d2e3e5 100644 --- a/pastepwn/analyzers/__init__.py +++ b/pastepwn/analyzers/__init__.py @@ -28,6 +28,7 @@ from .adobekeyanalyzer import AdobeKeyAnalyzer from .facebookaccesstokenanalyzer import FacebookAccessTokenAnalyzer from .base64analyzer import Base64Analyzer +from .slackwebhookanalyzer import SlackWebhookAnalyzer __all__ = ( 'AlwaysTrueAnalyzer', @@ -57,5 +58,6 @@ 'PrivateKeyAnalyzer', 'EmailPasswordPairAnalyzer', 'FacebookAccessTokenAnalyzer', - 'Base64Analyzer' + 'Base64Analyzer', + 'SlackWebhookAnalyzer' ) diff --git a/pastepwn/analyzers/slackwebhookanalyzer.py b/pastepwn/analyzers/slackwebhookanalyzer.py new file mode 100644 index 0000000..9ba6884 --- /dev/null +++ b/pastepwn/analyzers/slackwebhookanalyzer.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- +from .regexanalyzer import RegexAnalyzer + + +class SlackWebhookAnalyzer(RegexAnalyzer): + """Analyzer to match (likely) Slack Webhook URLs""" + + def __init__(self, action): + """ + Analyzer to match (likely) Slack Webhook URLs + :param action: Single action or list of actions to be executed when a paste matches + """ + + regex = r'https://hooks.slack.com/services/T[a-zA-Z0-9_]{8}/B[a-zA-Z0-9_]{8}/[a-zA-Z0-9_]{24}' + + super().__init__(action, regex) diff --git a/pastepwn/analyzers/tests/slackwebhookanalyzer_test.py b/pastepwn/analyzers/tests/slackwebhookanalyzer_test.py new file mode 100644 index 0000000..b72cadd --- /dev/null +++ b/pastepwn/analyzers/tests/slackwebhookanalyzer_test.py @@ -0,0 +1,63 @@ +# -*- coding: utf-8 -*- +import unittest +from unittest import mock + +from pastepwn.analyzers.slackwebhookanalyzer import SlackWebhookAnalyzer + + +class TestSlackWebhookAnalyzer(unittest.TestCase): + def setUp(self): + self.analyzer = SlackWebhookAnalyzer(None) + self.paste = mock.Mock() + + def test_match_positive(self): + """Test if positives are recognized""" + # slack webhook url (sample) + self.paste.body = "https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX" + self.assertTrue(self.analyzer.match(self.paste)) + + # slack webhook url (manually generated) + self.paste.body = "https://hooks.slack.com/services/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" + self.assertTrue(self.analyzer.match(self.paste)) + + # slack webhook url (randomly generated) + self.paste.body = "https://hooks.slack.com/services/TwLj3Aeic/B2RnzBQQp/7JkqKP9XxuqN3WFDn3tUA8NJ" + self.assertTrue(self.analyzer.match(self.paste)) + + # slack webhook url (randomly generated) + self.paste.body = "https://hooks.slack.com/services/TafdGEj9a/B9BdR2SLM/yJAk3gcguM8YzFEpaPnSvZ4Q" + self.assertTrue(self.analyzer.match(self.paste)) + + # part of a sentence + self.paste.body = "here is the webhook url: The slack webhook key is " \ + "https://hooks.slack.com/services/T00000000/B00000000"\ + "/XXXXXXXXXXXXXXXXXXXXXXXX! how about that!" + self.assertTrue(self.analyzer.match(self.paste)) + + def test_match_negative(self): + """Test if negatives are not recognized""" + self.paste.body = "" + self.assertFalse(self.analyzer.match(self.paste)) + + self.paste.body = None + self.assertFalse(self.analyzer.match(self.paste)) + + # Other Slack URL (api docs) + self.paste.body = "https://api.slack.com/incoming-webhooks" + self.assertFalse(self.analyzer.match(self.paste)) + + # Invalid Character + self.paste.body = "https://hooks.slack.com/services/T00!00000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX" + self.assertFalse(self.analyzer.match(self.paste)) + + # Invalid Length + self.paste.body = "https://hooks.slack.com/services/T00000000/B0000000/XXXXXXXXXXXXXXXXXXXXXXXX" + self.assertFalse(self.analyzer.match(self.paste)) + + # Invalid Format (/services/Z... vs /services/T...) + self.paste.body = "https://hooks.slack.com/services/Z00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX" + self.assertFalse(self.analyzer.match(self.paste)) + + +if __name__ == '__main__': + unittest.main() \ No newline at end of file