■ ■ ■ ■ ■ ■
rtspbrute/modules/attack.py
| skipped 15 lines |
16 | 16 | | DUMMY_ROUTE = "/0x8b6c42" |
17 | 17 | | MAX_SCREENSHOT_TRIES = 2 |
18 | 18 | | |
| 19 | + | # 401, 403: credentials are wrong but the route might be okay. |
| 20 | + | # 404: route is incorrect but the credentials might be okay. |
| 21 | + | # 200: stream is accessed successfully. |
| 22 | + | ROUTE_OK_CODES = ["RTSP/1.0 200", "RTSP/1.0 401", "RTSP/1.0 403", |
| 23 | + | "RTSP/2.0 200", "RTSP/2.0 401", "RTSP/2.0 403"] |
| 24 | + | CREDENTIALS_OK_CODES = ["RTSP/1.0 200", "RTSP/1.0 404", |
| 25 | + | "RTSP/2.0 200", "RTSP/2.0 404"] |
| 26 | + | |
19 | 27 | | logger = logging.getLogger() |
20 | 28 | | logger_is_enabled = logger.isEnabledFor(logging.DEBUG) |
21 | 29 | | |
| skipped 38 lines |
60 | 68 | | |
61 | 69 | | |
62 | 70 | | def attack_route(target: RTSPClient): |
63 | | - | # If it's a 401 or 403, it means that the credentials are wrong but the route might be okay. |
64 | | - | # If it's a 200, the stream is accessed successfully. |
65 | | - | ok_codes = ["200", "401", "403"] |
66 | | - | |
67 | 71 | | # If the stream responds positively to the dummy route, it means |
68 | 72 | | # it doesn't require (or respect the RFC) a route and the attack |
69 | 73 | | # can be skipped. |
70 | 74 | | for port in PORTS: |
71 | 75 | | ok = attack(target, port=port, route=DUMMY_ROUTE) |
72 | | - | if ok and any(code in target.data for code in ok_codes): |
| 76 | + | if ok and any(code in target.data for code in ROUTE_OK_CODES): |
73 | 77 | | target.port = port |
74 | 78 | | target.routes.append("/") |
75 | 79 | | return target |
| skipped 3 lines |
79 | 83 | | ok = attack(target, port=port, route=route) |
80 | 84 | | if not ok: |
81 | 85 | | break |
82 | | - | if any(code in target.data for code in ok_codes): |
| 86 | + | if any(code in target.data for code in ROUTE_OK_CODES): |
83 | 87 | | target.port = port |
84 | 88 | | target.routes.append(route) |
85 | 89 | | return target |
| skipped 11 lines |
97 | 101 | | _log_working_stream() |
98 | 102 | | return target |
99 | 103 | | |
100 | | - | # If it's a 404, it means that the route is incorrect but the credentials might be okay. |
101 | | - | # If it's a 200, the stream is accessed successfully. |
102 | | - | ok_codes = ["200", "404"] |
103 | | - | |
104 | 104 | | # If stream responds positively to no credentials, it means |
105 | 105 | | # it doesn't require them and the attack can be skipped. |
106 | 106 | | ok = attack(target, credentials=":") |
107 | | - | if ok and any(code in target.data for code in ok_codes): |
| 107 | + | if ok and any(code in target.data for code in CREDENTIALS_OK_CODES): |
108 | 108 | | _log_working_stream() |
109 | 109 | | return target |
110 | 110 | | |
| skipped 2 lines |
113 | 113 | | ok = attack(target, credentials=cred) |
114 | 114 | | if not ok: |
115 | 115 | | break |
116 | | - | if any(code in target.data for code in ok_codes): |
| 116 | + | if any(code in target.data for code in CREDENTIALS_OK_CODES): |
117 | 117 | | target.credentials = cred |
118 | 118 | | _log_working_stream() |
119 | 119 | | return target |
| skipped 1 lines |
121 | 121 | | |
122 | 122 | | def _is_video_stream(stream): |
123 | 123 | | return ( |
124 | | - | stream.profile is not None |
125 | | - | and stream.start_time is not None |
126 | | - | and stream.codec_context.format is not None |
| 124 | + | stream.profile is not None |
| 125 | + | and stream.start_time is not None |
| 126 | + | and stream.codec_context.format is not None |
127 | 127 | | ) |
128 | 128 | | |
129 | 129 | | |
130 | 130 | | def get_screenshot(rtsp_url: str, tries=1): |
131 | 131 | | try: |
132 | 132 | | with av.open( |
133 | | - | rtsp_url, |
134 | | - | options={ |
135 | | - | "rtsp_transport": "tcp", |
136 | | - | "rtsp_flags": "prefer_tcp", |
137 | | - | "stimeout": "3000000", |
138 | | - | }, |
139 | | - | timeout=60.0, |
| 133 | + | rtsp_url, |
| 134 | + | options={ |
| 135 | + | "rtsp_transport": "tcp", |
| 136 | + | "rtsp_flags": "prefer_tcp", |
| 137 | + | "stimeout": "3000000", |
| 138 | + | }, |
| 139 | + | timeout=60.0, |
140 | 140 | | ) as container: |
141 | 141 | | stream = container.streams.video[0] |
142 | 142 | | if _is_video_stream(stream): |
| skipped 46 lines |