Skip to content
This repository was archived by the owner on Dec 28, 2025. It is now read-only.

Commit 9b2fee2

Browse files
authored
Merge pull request #189 from d-Rickyy-b/dev
fix: recognize ipv6 error messages
2 parents f91a0ff + b810c44 commit 9b2fee2

File tree

9 files changed

+132
-7
lines changed

9 files changed

+132
-7
lines changed

CHANGELOG.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
## [1.3.1] - 2020-06-20
11+
### Fixed
12+
- The PastebinScraper could not recognize error messages with IPv6 addresses.
13+
14+
### Docs
15+
- Started adding some readme files for the subfolders to explain certain parts of the code better
16+
1017
## [1.3.0] - 2020-03-03
1118
### Added
1219
- Implemented base64analyzer, which matches if a found base64 string decodes to valid ascii ([b535781](https://github.com/d-Rickyy-b/pastepwn/commit/b535781d7e1760c7f846432d7ef87b97784e2d49))
@@ -158,7 +165,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
158165
## [1.0.8] - 2018-10-22
159166
First stable release
160167

161-
[unreleased]: https://github.com/d-Rickyy-b/pastepwn/compare/v1.3.0...HEAD
168+
[unreleased]: https://github.com/d-Rickyy-b/pastepwn/compare/v1.3.1...HEAD
169+
[1.3.1]: https://github.com/d-Rickyy-b/pastepwn/compare/v1.3.0...v1.3.1
162170
[1.3.0]: https://github.com/d-Rickyy-b/pastepwn/compare/v1.2.0...v1.3.0
163171
[1.2.0]: https://github.com/d-Rickyy-b/pastepwn/compare/v1.1.0...v1.2.0
164172
[1.1.0]: https://github.com/d-Rickyy-b/pastepwn/compare/v1.0.16...v1.1.0

pastepwn/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,6 @@
88
from .core.scrapinghandler import ScrapingHandler
99
from .core.actionhandler import ActionHandler
1010

11-
__author__ = "d-Rickyy-b (pastepwn@rickyy.de)"
11+
__author__ = "d-Rickyy-b (pastepwn@rico-j.de)"
1212

1313
__all__ = ['PastePwn', 'Paste', 'PasteDispatcher', 'ScrapingHandler', 'ActionHandler']

pastepwn/analyzers/README.md

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# Analyzers
2+
This directory contains all the analyzers for pastepwn. An analyzer is a class that extends the [BasicAnalyzer]() class (or any other subclass of that) and overrides at least the `match` function.
3+
4+
The match function gets passed a paste object.
5+
The job of an analyzer is to check if a paste matches certain criteria. If it matches, pastepwn will execute the action(s), that is stored in the analyzer.
6+
7+
8+
## Example analyzers
9+
Analyzers can check for multiple things.
10+
A paste contains a certain, previously defined string.
11+
Or the paste matches a certain regex.
12+
Or the paste's syntax is set to `java`.
13+
And many other things.
14+
15+
Check a few selected examples to get an idea:
16+
- [RegexAnalyzer](https://github.com/d-Rickyy-b/pastepwn/blob/master/pastepwn/analyzers/regexanalyzer.py) - Foundation for most other analyzers. Checks a
17+
paste against a regex
18+
- [SteamKeyAnalyzer](https://github.com/d-Rickyy-b/pastepwn/blob/master/pastepwn/analyzers/steamkeyanalyzer.py) - Checks if a paste contains a Steam Key
19+
- [IBANAnalyzer](https://github.com/d-Rickyy-b/pastepwn/blob/master/pastepwn/analyzers/ibananalyzer.py) - Checks if a paste contains an IBAN
20+
21+
22+
## Create own analyzer
23+
Check out the implementations of a few analyzers and you'll get an idea on how to get started.
24+
25+
```python
26+
# -*- coding: utf-8 -*-
27+
from .basicanalyzer import BasicAnalyzer
28+
29+
30+
class MyAnalyzer(BasicAnalyzer):
31+
name = "MyAnalyzer"
32+
33+
def __init__(self, actions, regex, flags=0, blacklist=None):
34+
# We need co call the init of super, to initialize some settings in the basicanalyzer
35+
super().__init__(actions, self.name)
36+
37+
# We can do some custom setup stuff to initialize e.g. blacklists
38+
self.blacklist = blacklist or []
39+
40+
def match(self, paste):
41+
# Here our pastes get matched. We can access all fields of the paste object
42+
paste_title = paste.title or ""
43+
44+
# We can for example check if the paste title contains a certain string
45+
return "Secret" in paste_title
46+
```
47+
48+
## Combining analyzers
49+
To combine multiple analyzers and hence multiple conditions, you can use bitwise operators.
50+
Those bitwise operators act as a logical operators by creating a new `MergedAnalyzer` class that handles the individual analyzers internally.
51+
52+
`&` - bitwise AND for combining analyzers with a logical AND
53+
`|` - bitwise OR for combining analyzers with a logical OR
54+
55+
```python
56+
analyzer1 = SomeAnalyzer(...)
57+
analyzer2 = SomeOtherAnalyzer(...)
58+
analyzer3 = ThirdAnalyzer(...)
59+
60+
realAnalyzer = (analyzer1 & analyzer2) | analyzer3
61+
```
62+
63+
The `realAnalyzer` only matches if either `analyzer1` and `analyzer2` both match, or if `analyzer3` matches.
64+

pastepwn/analyzers/basicanalyzer.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,10 @@ def __repr__(self):
6666

6767

6868
class MergedAnalyzer(BasicAnalyzer):
69-
"""Basic analyzer class"""
69+
"""
70+
Combination class to combine multiple analyzers into a single one
71+
Doesn't need to be created manually - use the binary operators (& and |) to combine multiple analyzers.
72+
"""
7073
name = "MergedAnalyzer"
7174

7275
def __init__(self, base_analyzer, and_analyzer=None, or_analyzer=None):

pastepwn/core/pastepwn.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ def add_scraper(self, scraper, restart_scraping=False):
7171
def add_analyzer(self, analyzer):
7272
"""
7373
Adds a new analyzer to the list of analyzers
74-
:param analyzer: Instance of an BasicAnalyzer
74+
:param analyzer: Instance of a BasicAnalyzer
7575
:return: None
7676
"""
7777

pastepwn/scraping/pastebin/exceptions/ipnotregisterederror.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44

55
class IPNotRegisteredError(Exception):
6+
"""Exception class indicating that your IP is not witelisted on pastebin"""
67

78
def __init__(self, body):
89
ip = re.search("YOUR IP: (.*?) DOES NOT HAVE ACCESS", body).group(1)

pastepwn/scraping/pastebin/pastebinscraper.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,9 @@ def __init__(self, paste_queue=None, exception_event=None, api_hit_rate=None):
3737

3838
def _check_error(self, body, key=None):
3939
"""Checks if an error occurred and raises an exception if it did"""
40-
pattern = r"YOUR IP: \d{1,3}.\d{1,3}.\d{1,3}.\d{1,3} DOES NOT HAVE ACCESS\.\s+VISIT: https:\/\/pastebin\.com\/doc_scraping_api TO GET ACCESS!"
40+
pattern = r"^YOUR IP: ((\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3})|((([0-9A-Fa-f]{1,4}:){7})([0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,6}:)(([0-9A-Fa-f]{1,4}:){0,4})([0-9A-Fa-f]{1,4}))) DOES NOT HAVE ACCESS\.\s+VISIT: https:\/\/pastebin\.com\/doc_scraping_api TO GET ACCESS!"
4141

42-
if 107 >= len(body) >= 99 and re.match(pattern, body):
42+
if 131 >= len(body) and re.match(pattern, body):
4343
self._exception_event.set()
4444
raise IPNotRegisteredError(body)
4545

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# -*- coding: utf-8 -*-
2+
import unittest
3+
from pastepwn.scraping.pastebin import PastebinScraper
4+
from pastepwn.scraping.pastebin.exceptions import IPNotRegisteredError, PasteDeletedException, PasteNotReadyException, PasteEmptyException
5+
6+
7+
class TestPastebinscraper(unittest.TestCase):
8+
9+
def setUp(self) -> None:
10+
self.pastebinscraper = PastebinScraper()
11+
12+
def test_empty(self):
13+
with self.assertRaises(PasteEmptyException):
14+
self.pastebinscraper._check_error("")
15+
16+
def test_not_ready(self):
17+
with self.assertRaises(PasteNotReadyException):
18+
self.pastebinscraper._check_error("File is not ready for scraping yet. Try again in 1 minute.")
19+
20+
def test_deleted(self):
21+
with self.assertRaises(PasteDeletedException):
22+
self.pastebinscraper._check_error("Error, we cannot find this paste.")
23+
24+
def _check_ip_not_registered(self, ip_list):
25+
shell = "YOUR IP: {} DOES NOT HAVE ACCESS. VISIT: https://pastebin.com/doc_scraping_api TO GET ACCESS!"
26+
for ip in ip_list:
27+
with self.assertRaises(IPNotRegisteredError):
28+
self.pastebinscraper._check_error(shell.format(ip))
29+
print("The following IP was not detected: {}".format(ip))
30+
31+
def test_ipv4_not_registered(self):
32+
"""Test if the _check_error method detects different IPv4 addresses. It's okay to also detect invalid addresses where an octed is > 255)"""
33+
ipv4_test = ["1.1.1.1", "10.1.5.6", "1.10.5.6", "1.1.50.6", "1.1.5.60", "1.1.50.60", "1.10.50.60", "10.10.50.60", "10.10.50.255", "10.10.255.255",
34+
"10.255.255.255", "255.255.255.255", "333.333.333.333"]
35+
36+
self._check_ip_not_registered(ipv4_test)
37+
38+
def test_ipv6_not_registered(self):
39+
ipv6_test = ["fe80::21d8:f50:c295:c4be", "2001:cdba:0000:0000:0000:0000:3257:9652", "2001:cdba:0:0:0:0:3257:9652", "2001:cdba::3257:9652",
40+
"2001:cdba::1222", "21DA:D3:0:2F3B:2AA:FF:FE28:9C5A", "2001:cdba::1:2:3:3257:9652", "FE80::8329", "FE80::FFFF:8329",
41+
"FE80::B3FF:FFFF:8329", "FE80::0202:B3FF:FFFF:8329", "FE80:0000:0000:0000:0202:B3FF:FFFF:8329"]
42+
# TODO: IPv6 addresses with double colon AND full zero groups (of 16 bits) are currently not recognized by the used regex. An example address would
43+
# be: `FE80::0000:0000:0202:B3FF:FFFF:8329`
44+
45+
self._check_ip_not_registered(ipv6_test)
46+
47+
48+
if __name__ == '__main__':
49+
unittest.main()

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ def requirements():
4747
long_description_content_type='text/markdown',
4848
url='https://github.com/d-Rickyy-b/pastepwn',
4949
author='d-Rickyy-b',
50-
author_email='pastepwn@rickyy.de',
50+
author_email='pastepwn@rico-j.de',
5151
license='MIT',
5252
packages=packages,
5353
include_package_data=True,

0 commit comments

Comments
 (0)