tryassay 0.33.1 → 0.33.2
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/dist/cli.js +2 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/hunt.d.ts +2 -0
- package/dist/commands/hunt.js +58 -7
- package/dist/commands/hunt.js.map +1 -1
- package/dist/hunt/__tests__/finding-to-template.test.d.ts +1 -0
- package/dist/hunt/__tests__/finding-to-template.test.js +213 -0
- package/dist/hunt/__tests__/finding-to-template.test.js.map +1 -0
- package/dist/hunt/__tests__/parse-utils.test.js +28 -1
- package/dist/hunt/__tests__/parse-utils.test.js.map +1 -1
- package/dist/hunt/__tests__/taint-analysis.test.d.ts +1 -0
- package/dist/hunt/__tests__/taint-analysis.test.js +556 -0
- package/dist/hunt/__tests__/taint-analysis.test.js.map +1 -0
- package/dist/hunt/__tests__/templates.test.js +2 -2
- package/dist/hunt/__tests__/templates.test.js.map +1 -1
- package/dist/hunt/deep-dive.d.ts +2 -2
- package/dist/hunt/deep-dive.js +4 -4
- package/dist/hunt/deep-dive.js.map +1 -1
- package/dist/hunt/discovery.js +2 -2
- package/dist/hunt/discovery.js.map +1 -1
- package/dist/hunt/finding-to-template.d.ts +47 -0
- package/dist/hunt/finding-to-template.js +288 -0
- package/dist/hunt/finding-to-template.js.map +1 -0
- package/dist/hunt/orchestrator.d.ts +3 -0
- package/dist/hunt/orchestrator.js +20 -5
- package/dist/hunt/orchestrator.js.map +1 -1
- package/dist/hunt/taint-analysis.d.ts +49 -0
- package/dist/hunt/taint-analysis.js +429 -0
- package/dist/hunt/taint-analysis.js.map +1 -0
- package/dist/hunt/templates/csv-injection.d.ts +2 -0
- package/dist/hunt/templates/csv-injection.js +148 -0
- package/dist/hunt/templates/csv-injection.js.map +1 -0
- package/dist/hunt/templates/django-misconfig.d.ts +2 -0
- package/dist/hunt/templates/django-misconfig.js +172 -0
- package/dist/hunt/templates/django-misconfig.js.map +1 -0
- package/dist/hunt/templates/express-misconfig.d.ts +2 -0
- package/dist/hunt/templates/express-misconfig.js +156 -0
- package/dist/hunt/templates/express-misconfig.js.map +1 -0
- package/dist/hunt/templates/file-upload.d.ts +2 -0
- package/dist/hunt/templates/file-upload.js +131 -0
- package/dist/hunt/templates/file-upload.js.map +1 -0
- package/dist/hunt/templates/graphql-abuse.d.ts +2 -0
- package/dist/hunt/templates/graphql-abuse.js +161 -0
- package/dist/hunt/templates/graphql-abuse.js.map +1 -0
- package/dist/hunt/templates/hardcoded-credentials.d.ts +2 -0
- package/dist/hunt/templates/hardcoded-credentials.js +109 -0
- package/dist/hunt/templates/hardcoded-credentials.js.map +1 -0
- package/dist/hunt/templates/idor.d.ts +2 -0
- package/dist/hunt/templates/idor.js +102 -0
- package/dist/hunt/templates/idor.js.map +1 -0
- package/dist/hunt/templates/index.d.ts +2 -2
- package/dist/hunt/templates/index.js +38 -5
- package/dist/hunt/templates/index.js.map +1 -1
- package/dist/hunt/templates/insecure-deserialization.d.ts +2 -0
- package/dist/hunt/templates/insecure-deserialization.js +131 -0
- package/dist/hunt/templates/insecure-deserialization.js.map +1 -0
- package/dist/hunt/templates/mass-assignment.d.ts +2 -0
- package/dist/hunt/templates/mass-assignment.js +101 -0
- package/dist/hunt/templates/mass-assignment.js.map +1 -0
- package/dist/hunt/templates/nextjs-misconfig.d.ts +2 -0
- package/dist/hunt/templates/nextjs-misconfig.js +127 -0
- package/dist/hunt/templates/nextjs-misconfig.js.map +1 -0
- package/dist/hunt/templates/postmessage.d.ts +2 -0
- package/dist/hunt/templates/postmessage.js +180 -0
- package/dist/hunt/templates/postmessage.js.map +1 -0
- package/dist/hunt/templates/race-condition.d.ts +2 -0
- package/dist/hunt/templates/race-condition.js +138 -0
- package/dist/hunt/templates/race-condition.js.map +1 -0
- package/dist/hunt/templates/spring-misconfig.d.ts +2 -0
- package/dist/hunt/templates/spring-misconfig.js +177 -0
- package/dist/hunt/templates/spring-misconfig.js.map +1 -0
- package/dist/hunt/templates/xxe.d.ts +2 -0
- package/dist/hunt/templates/xxe.js +187 -0
- package/dist/hunt/templates/xxe.js.map +1 -0
- package/dist/hunt/triage.d.ts +2 -2
- package/dist/hunt/triage.js +4 -4
- package/dist/hunt/triage.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
export const hardcodedCredentials = {
|
|
2
|
+
id: 'hardcoded-credentials',
|
|
3
|
+
name: 'Hardcoded Credentials',
|
|
4
|
+
cwe: 'CWE-798',
|
|
5
|
+
filePatterns: ['config', 'env', 'secret', 'credential', 'api-key', 'password', 'token', 'connection', 'auth', 'key'],
|
|
6
|
+
negativePatterns: ['test', 'fixture', 'example', 'sample', 'mock', 'stub', '__tests__', 'spec'],
|
|
7
|
+
triagePrompt: `You are a security researcher hunting for hardcoded credentials in source code.
|
|
8
|
+
|
|
9
|
+
Analyze the code for secrets that should never be committed to a repository. Focus on:
|
|
10
|
+
1. API keys — look for strings matching known provider formats (AWS: AKIA..., Stripe: sk_live_..., GitHub: ghp_..., Slack: xoxb-...)
|
|
11
|
+
2. Passwords in connection strings — postgres://user:PASSWORD@host, mongodb+srv://user:PASSWORD@host, redis://:PASSWORD@host
|
|
12
|
+
3. JWT signing secrets — hardcoded strings passed to jwt.sign(), jsonwebtoken.verify(), or HMAC functions
|
|
13
|
+
4. OAuth client secrets — client_secret, app_secret, consumer_secret assigned to string literals
|
|
14
|
+
5. Private keys — BEGIN RSA PRIVATE KEY, BEGIN EC PRIVATE KEY, BEGIN OPENSSH PRIVATE KEY embedded as strings
|
|
15
|
+
6. Base64-encoded tokens — long base64 strings (40+ chars) assigned to auth-related variables
|
|
16
|
+
7. Cloud provider credentials — AWS_SECRET_ACCESS_KEY, AZURE_CLIENT_SECRET, GCP_SERVICE_ACCOUNT_KEY as string literals
|
|
17
|
+
|
|
18
|
+
DETECTION PATTERNS:
|
|
19
|
+
- Variable names: password, passwd, pwd, secret, token, apiKey, api_key, apiSecret, authToken, accessToken, privateKey
|
|
20
|
+
- String assignments: const API_KEY = "sk-..." or export const SECRET = "..."
|
|
21
|
+
- Config objects: { password: "literal", apiKey: "literal" }
|
|
22
|
+
- Template literals with secrets: \`Bearer \${hardcodedToken}\`
|
|
23
|
+
- Environment variable fallbacks: process.env.SECRET || "hardcoded-fallback"
|
|
24
|
+
|
|
25
|
+
FALSE POSITIVE FILTERS:
|
|
26
|
+
- process.env.VARIABLE_NAME (reading from env is correct — not a finding)
|
|
27
|
+
- Placeholder values: "YOUR_API_KEY_HERE", "changeme", "xxx", "TODO"
|
|
28
|
+
- Schema definitions or type annotations that mention "password" as a field name
|
|
29
|
+
- Documentation strings or comments explaining credential formats
|
|
30
|
+
- Test files using obviously fake values (unless they look like real rotated keys)
|
|
31
|
+
|
|
32
|
+
KNOWN BYPASS TECHNIQUES:
|
|
33
|
+
- Obfuscated secrets: Buffer.from('base64secret', 'base64').toString()
|
|
34
|
+
- Split strings: const key = 'sk-' + 'live_' + 'abc123...'
|
|
35
|
+
- Reversed strings: const key = '...321cba_evil_ks'.split('').reverse().join('')
|
|
36
|
+
- Hex-encoded: const key = Buffer.from('736b2d6c697665', 'hex').toString()
|
|
37
|
+
- Config files committed but in .gitignore (still in git history)
|
|
38
|
+
|
|
39
|
+
RELEVANT SPECIFICATIONS:
|
|
40
|
+
- OWASP Top 10 2021 A07: Identification and Authentication Failures
|
|
41
|
+
- CWE-798: Use of Hard-coded Credentials
|
|
42
|
+
- CWE-259: Use of Hard-coded Password
|
|
43
|
+
- NIST SP 800-63B: Digital Identity Guidelines (credential storage)
|
|
44
|
+
|
|
45
|
+
For each finding, cite the EXACT line number and the credential pattern matched. Rate severity based on:
|
|
46
|
+
- Critical: Production API keys, database passwords, signing secrets with real-looking values
|
|
47
|
+
- High: OAuth secrets, cloud credentials, private keys
|
|
48
|
+
- Medium: Internal service tokens, development-only credentials in production code
|
|
49
|
+
- Low: Placeholder values that hint at poor credential hygiene`,
|
|
50
|
+
deepDivePrompt: `You are an expert security researcher writing a bug bounty report for hardcoded credentials.
|
|
51
|
+
|
|
52
|
+
Given the hypothesis below, verify whether the credentials are real and exploitable.
|
|
53
|
+
|
|
54
|
+
VERIFICATION STEPS:
|
|
55
|
+
1. Is the credential a real secret or a placeholder? Check:
|
|
56
|
+
- Length and entropy — real API keys have high entropy, placeholders are short/obvious
|
|
57
|
+
- Format match — does it match a known provider's key format exactly?
|
|
58
|
+
- Context — is it in production code or genuinely test-only code?
|
|
59
|
+
2. What does the credential grant access to?
|
|
60
|
+
- Database: full read/write? specific schema only?
|
|
61
|
+
- API: billing access? admin access? read-only?
|
|
62
|
+
- Cloud: IAM role privileges? metadata access?
|
|
63
|
+
3. Is the credential still valid?
|
|
64
|
+
- Check git history — was it rotated? Is the current value different?
|
|
65
|
+
- Look for rotation logic — is there a key rotation mechanism?
|
|
66
|
+
4. What is the blast radius?
|
|
67
|
+
- Can an attacker pivot from this credential to other systems?
|
|
68
|
+
- Does the database contain PII, payment data, or auth tokens?
|
|
69
|
+
|
|
70
|
+
PROVIDER-SPECIFIC KEY FORMATS:
|
|
71
|
+
- AWS Access Key: AKIA[0-9A-Z]{16}
|
|
72
|
+
- AWS Secret Key: [A-Za-z0-9/+=]{40}
|
|
73
|
+
- GitHub PAT: ghp_[A-Za-z0-9]{36}
|
|
74
|
+
- Stripe Live: sk_live_[A-Za-z0-9]{24,}
|
|
75
|
+
- Stripe Test: sk_test_[A-Za-z0-9]{24,} (lower severity but still a finding)
|
|
76
|
+
- Slack Bot Token: xoxb-[0-9]{10,}-[A-Za-z0-9]{24,}
|
|
77
|
+
- Google API Key: AIza[A-Za-z0-9_-]{35}
|
|
78
|
+
- SendGrid: SG.[A-Za-z0-9_-]{22}.[A-Za-z0-9_-]{43}
|
|
79
|
+
- Twilio: SK[a-f0-9]{32}
|
|
80
|
+
|
|
81
|
+
PROOF-OF-CONCEPT:
|
|
82
|
+
- For API keys: show which API endpoint the key authenticates to
|
|
83
|
+
- For database creds: show the connection string that would grant access
|
|
84
|
+
- For signing secrets: show how an attacker could forge JWTs or HMACs
|
|
85
|
+
- Do NOT actually use the credential — demonstrate the attack path only
|
|
86
|
+
|
|
87
|
+
RELEVANT SPECIFICATIONS:
|
|
88
|
+
- CWE-798: Use of Hard-coded Credentials — hardcoded values that grant authentication
|
|
89
|
+
- OWASP Testing Guide v4: OTG-AUTHN-007 (Testing for Weak or Unenforced Password Policy)
|
|
90
|
+
|
|
91
|
+
Cite exact file paths, line numbers, and the credential pattern. Redact the actual secret value in your report (show first 4 and last 4 characters only).`,
|
|
92
|
+
knownBypasses: [
|
|
93
|
+
'Base64-encoded secrets: Buffer.from(encoded, "base64")',
|
|
94
|
+
'String concatenation to split the secret across lines',
|
|
95
|
+
'Hex-encoded credential values',
|
|
96
|
+
'Environment variable fallback: process.env.KEY || "hardcoded"',
|
|
97
|
+
'Config file committed but listed in .gitignore (still in git history)',
|
|
98
|
+
'Reversed string reassembled at runtime',
|
|
99
|
+
'Credential in build output / bundled JS not in source',
|
|
100
|
+
],
|
|
101
|
+
specReferences: [
|
|
102
|
+
'CWE-798 (Use of Hard-coded Credentials)',
|
|
103
|
+
'CWE-259 (Use of Hard-coded Password)',
|
|
104
|
+
'OWASP Top 10 2021 A07 (Identification and Authentication Failures)',
|
|
105
|
+
'NIST SP 800-63B (Digital Identity Guidelines)',
|
|
106
|
+
],
|
|
107
|
+
severityRange: ['medium', 'critical'],
|
|
108
|
+
};
|
|
109
|
+
//# sourceMappingURL=hardcoded-credentials.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hardcoded-credentials.js","sourceRoot":"","sources":["../../../src/hunt/templates/hardcoded-credentials.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,oBAAoB,GAA0B;IACzD,EAAE,EAAE,uBAAuB;IAC3B,IAAI,EAAE,uBAAuB;IAC7B,GAAG,EAAE,SAAS;IACd,YAAY,EAAE,CAAC,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,SAAS,EAAE,UAAU,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,KAAK,CAAC;IACpH,gBAAgB,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,CAAC;IAC/F,YAAY,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+DA0C+C;IAE7D,cAAc,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;0JAyCwI;IAExJ,aAAa,EAAE;QACb,wDAAwD;QACxD,uDAAuD;QACvD,+BAA+B;QAC/B,+DAA+D;QAC/D,uEAAuE;QACvE,wCAAwC;QACxC,uDAAuD;KACxD;IACD,cAAc,EAAE;QACd,yCAAyC;QACzC,sCAAsC;QACtC,oEAAoE;QACpE,+CAA+C;KAChD;IACD,aAAa,EAAE,CAAC,QAAQ,EAAE,UAAU,CAAC;CACtC,CAAC"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
export const idor = {
|
|
2
|
+
id: 'idor',
|
|
3
|
+
name: 'Insecure Direct Object Reference',
|
|
4
|
+
cwe: 'CWE-639',
|
|
5
|
+
filePatterns: ['user', 'account', 'profile', 'admin', 'permission', 'role', 'access', 'owner', 'tenant', 'organization'],
|
|
6
|
+
negativePatterns: [],
|
|
7
|
+
triagePrompt: `You are a security researcher hunting for Insecure Direct Object Reference (IDOR) vulnerabilities. This is the #1 bounty-paying vulnerability class on HackerOne.
|
|
8
|
+
|
|
9
|
+
Analyze the code for endpoints or functions where a user can access or modify resources belonging to another user by changing an identifier. Focus on:
|
|
10
|
+
1. Missing ownership checks — does the code verify the requesting user owns the resource before returning it?
|
|
11
|
+
2. Predictable identifiers — are resources keyed by auto-incrementing integers, sequential IDs, or guessable UUIDs?
|
|
12
|
+
3. Parameter tampering — can a user change userId, accountId, orderId in the request to access other users' data?
|
|
13
|
+
4. Horizontal privilege escalation — can user A access user B's data at the same privilege level?
|
|
14
|
+
5. Vertical privilege escalation — can a regular user access admin-only resources by guessing the endpoint/ID?
|
|
15
|
+
6. Multi-tenancy leaks — in SaaS apps, can tenant A access tenant B's data by changing organizationId?
|
|
16
|
+
|
|
17
|
+
CRITICAL PATTERNS TO FIND:
|
|
18
|
+
- GET /api/users/:id — returns user data without checking if requester IS that user
|
|
19
|
+
- PUT /api/orders/:orderId — updates order without checking if order belongs to requester
|
|
20
|
+
- DELETE /api/documents/:docId — deletes document without ownership validation
|
|
21
|
+
- GraphQL resolvers that take an ID argument and query directly without auth context filtering
|
|
22
|
+
- Supabase/Firebase queries that don't use RLS or filter by auth.uid()
|
|
23
|
+
- SQL queries: SELECT * FROM orders WHERE id = $1 (no AND user_id = $currentUser)
|
|
24
|
+
|
|
25
|
+
OWNERSHIP VALIDATION PATTERNS (what CORRECT code looks like):
|
|
26
|
+
- SQL: WHERE id = $1 AND user_id = $currentUser
|
|
27
|
+
- Supabase RLS: CREATE POLICY ... USING (auth.uid() = user_id)
|
|
28
|
+
- ORM: .where({ id, userId: req.user.id })
|
|
29
|
+
- Middleware: requireOwnership(req.user, resource)
|
|
30
|
+
|
|
31
|
+
WHAT MAKES THIS EXPLOITABLE:
|
|
32
|
+
- The resource contains PII (names, emails, addresses, phone numbers)
|
|
33
|
+
- The resource contains financial data (balances, transactions, payment methods)
|
|
34
|
+
- The resource can be modified (not just read — write IDOR is higher severity)
|
|
35
|
+
- The resource controls access (changing role, permissions, group membership)
|
|
36
|
+
|
|
37
|
+
RELEVANT SPECIFICATIONS:
|
|
38
|
+
- OWASP Top 10 2021 A01: Broken Access Control
|
|
39
|
+
- OWASP ASVS V4.0 Section 4: Access Control
|
|
40
|
+
- CWE-639: Authorization Bypass Through User-Controlled Key
|
|
41
|
+
|
|
42
|
+
For each finding, cite the EXACT endpoint/function, the parameter that can be tampered with, and what data is exposed. Show the code path from request parameter to database query.`,
|
|
43
|
+
deepDivePrompt: `You are an expert security researcher writing a bug bounty report for an IDOR vulnerability.
|
|
44
|
+
|
|
45
|
+
Given the hypothesis below, verify whether the vulnerability is real and exploitable.
|
|
46
|
+
|
|
47
|
+
BUILD THE FULL ATTACK SCENARIO:
|
|
48
|
+
1. Identify the vulnerable endpoint and HTTP method (GET/POST/PUT/DELETE)
|
|
49
|
+
2. Identify the parameter being tampered (path param, query param, JSON body field)
|
|
50
|
+
3. Trace the parameter from request intake through to the database query
|
|
51
|
+
4. Confirm NO ownership check exists between parameter receipt and data access
|
|
52
|
+
5. Determine what data is exposed or what action can be performed
|
|
53
|
+
6. Assess the impact: PII leak? financial data? privilege escalation?
|
|
54
|
+
|
|
55
|
+
PROOF-OF-CONCEPT:
|
|
56
|
+
Provide two curl commands:
|
|
57
|
+
1. Legitimate request: User A accessing their own resource
|
|
58
|
+
2. Attack request: User A accessing User B's resource (same request, different ID)
|
|
59
|
+
|
|
60
|
+
Show that the response to request #2 contains User B's data.
|
|
61
|
+
|
|
62
|
+
SEVERITY ASSESSMENT:
|
|
63
|
+
- Critical: Write IDOR on financial resources (transfer money, change payment method)
|
|
64
|
+
- Critical: Admin-level vertical privilege escalation
|
|
65
|
+
- High: Read IDOR exposing PII (emails, addresses, SSNs, medical records)
|
|
66
|
+
- High: Write IDOR on any user-owned resource (modify profile, delete data)
|
|
67
|
+
- Medium: Read IDOR on non-sensitive data (preferences, settings)
|
|
68
|
+
- Medium: IDOR on resources with UUID identifiers (harder to enumerate but still exploitable)
|
|
69
|
+
- Low: IDOR that requires additional preconditions or reveals minimal data
|
|
70
|
+
|
|
71
|
+
COMMON BYPASS TECHNIQUES:
|
|
72
|
+
- UUID bruteforce: if other endpoints leak UUIDs (user lists, public profiles, error messages)
|
|
73
|
+
- Parameter pollution: sending userId in both path and body, one gets validated, other gets used
|
|
74
|
+
- HTTP method switching: GET is protected but PUT/PATCH isn't
|
|
75
|
+
- JSON nesting: top-level userId checked but nested object's userId used for query
|
|
76
|
+
- GraphQL aliasing: request same field multiple times with different IDs in one query
|
|
77
|
+
- Batch endpoints: /api/users/batch accepts array of IDs, only first is validated
|
|
78
|
+
|
|
79
|
+
RELEVANT SPECIFICATIONS:
|
|
80
|
+
- OWASP Testing Guide: OTG-AUTHZ-004 (Testing for IDOR)
|
|
81
|
+
- CWE-639: Authorization Bypass Through User-Controlled Key
|
|
82
|
+
- CWE-284: Improper Access Control
|
|
83
|
+
|
|
84
|
+
Cite exact file paths, line numbers, and the missing authorization check.`,
|
|
85
|
+
knownBypasses: [
|
|
86
|
+
'Parameter pollution: userId in path validated, userId in body used for query',
|
|
87
|
+
'HTTP method switching: GET protected but PUT/PATCH unprotected',
|
|
88
|
+
'UUID leakage from other endpoints enabling enumeration',
|
|
89
|
+
'GraphQL aliasing to request multiple IDs in one query',
|
|
90
|
+
'Batch endpoint validates first ID only, processes all',
|
|
91
|
+
'JSON nesting: outer userId checked, inner userId.nested used',
|
|
92
|
+
'Array index manipulation: /api/users/0 vs /api/users/1',
|
|
93
|
+
],
|
|
94
|
+
specReferences: [
|
|
95
|
+
'OWASP Top 10 2021 A01 (Broken Access Control)',
|
|
96
|
+
'OWASP ASVS V4.0 Section 4 (Access Control)',
|
|
97
|
+
'CWE-639 (Authorization Bypass Through User-Controlled Key)',
|
|
98
|
+
'CWE-284 (Improper Access Control)',
|
|
99
|
+
],
|
|
100
|
+
severityRange: ['medium', 'critical'],
|
|
101
|
+
};
|
|
102
|
+
//# sourceMappingURL=idor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"idor.js","sourceRoot":"","sources":["../../../src/hunt/templates/idor.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,IAAI,GAA0B;IACzC,EAAE,EAAE,MAAM;IACV,IAAI,EAAE,kCAAkC;IACxC,GAAG,EAAE,SAAS;IACd,YAAY,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,cAAc,CAAC;IACxH,gBAAgB,EAAE,EAAE;IACpB,YAAY,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oLAmCoK;IAElL,cAAc,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;0EAyCwD;IAExE,aAAa,EAAE;QACb,8EAA8E;QAC9E,gEAAgE;QAChE,wDAAwD;QACxD,uDAAuD;QACvD,uDAAuD;QACvD,8DAA8D;QAC9D,wDAAwD;KACzD;IACD,cAAc,EAAE;QACd,+CAA+C;QAC/C,4CAA4C;QAC5C,4DAA4D;QAC5D,mCAAmC;KACpC;IACD,aAAa,EAAE,CAAC,QAAQ,EAAE,UAAU,CAAC;CACtC,CAAC"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { VulnerabilityTemplate } from '../../types.js';
|
|
2
|
-
export declare function getAllTemplates(): VulnerabilityTemplate[];
|
|
3
|
-
export declare function getTemplateById(id: string): VulnerabilityTemplate | undefined;
|
|
2
|
+
export declare function getAllTemplates(projectRoot?: string): VulnerabilityTemplate[];
|
|
3
|
+
export declare function getTemplateById(id: string, projectRoot?: string): VulnerabilityTemplate | undefined;
|
|
@@ -8,7 +8,25 @@ import { injection } from './injection.js';
|
|
|
8
8
|
import { openRedirect } from './open-redirect.js';
|
|
9
9
|
import { prototypePollution } from './prototype-pollution.js';
|
|
10
10
|
import { timingAttack } from './timing-attack.js';
|
|
11
|
-
|
|
11
|
+
// New generic templates
|
|
12
|
+
import { hardcodedCredentials } from './hardcoded-credentials.js';
|
|
13
|
+
import { idor } from './idor.js';
|
|
14
|
+
import { massAssignment } from './mass-assignment.js';
|
|
15
|
+
import { insecureDeserialization } from './insecure-deserialization.js';
|
|
16
|
+
import { fileUpload } from './file-upload.js';
|
|
17
|
+
import { raceCondition } from './race-condition.js';
|
|
18
|
+
import { xxe } from './xxe.js';
|
|
19
|
+
import { graphqlAbuse } from './graphql-abuse.js';
|
|
20
|
+
import { csvInjection } from './csv-injection.js';
|
|
21
|
+
import { postmessage } from './postmessage.js';
|
|
22
|
+
// Framework-specific templates
|
|
23
|
+
import { nextjsMisconfig } from './nextjs-misconfig.js';
|
|
24
|
+
import { expressMisconfig } from './express-misconfig.js';
|
|
25
|
+
import { djangoMisconfig } from './django-misconfig.js';
|
|
26
|
+
import { springMisconfig } from './spring-misconfig.js';
|
|
27
|
+
// Learned templates
|
|
28
|
+
import { loadLearnedTemplates } from '../finding-to-template.js';
|
|
29
|
+
const builtInTemplates = [
|
|
12
30
|
csrfBypass,
|
|
13
31
|
ssrf,
|
|
14
32
|
weakRandom,
|
|
@@ -19,11 +37,26 @@ const templates = [
|
|
|
19
37
|
openRedirect,
|
|
20
38
|
prototypePollution,
|
|
21
39
|
timingAttack,
|
|
40
|
+
hardcodedCredentials,
|
|
41
|
+
idor,
|
|
42
|
+
massAssignment,
|
|
43
|
+
insecureDeserialization,
|
|
44
|
+
fileUpload,
|
|
45
|
+
raceCondition,
|
|
46
|
+
xxe,
|
|
47
|
+
graphqlAbuse,
|
|
48
|
+
csvInjection,
|
|
49
|
+
postmessage,
|
|
50
|
+
nextjsMisconfig,
|
|
51
|
+
expressMisconfig,
|
|
52
|
+
djangoMisconfig,
|
|
53
|
+
springMisconfig,
|
|
22
54
|
];
|
|
23
|
-
export function getAllTemplates() {
|
|
24
|
-
|
|
55
|
+
export function getAllTemplates(projectRoot) {
|
|
56
|
+
const learned = loadLearnedTemplates(projectRoot);
|
|
57
|
+
return [...builtInTemplates, ...learned];
|
|
25
58
|
}
|
|
26
|
-
export function getTemplateById(id) {
|
|
27
|
-
return
|
|
59
|
+
export function getTemplateById(id, projectRoot) {
|
|
60
|
+
return getAllTemplates(projectRoot).find(t => t.id === id);
|
|
28
61
|
}
|
|
29
62
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/hunt/templates/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/hunt/templates/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,wBAAwB;AACxB,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;AACxE,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAC/B,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,+BAA+B;AAC/B,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,oBAAoB;AACpB,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAEjE,MAAM,gBAAgB,GAA4B;IAChD,UAAU;IACV,IAAI;IACJ,UAAU;IACV,UAAU;IACV,aAAa;IACb,aAAa;IACb,SAAS;IACT,YAAY;IACZ,kBAAkB;IAClB,YAAY;IACZ,oBAAoB;IACpB,IAAI;IACJ,cAAc;IACd,uBAAuB;IACvB,UAAU;IACV,aAAa;IACb,GAAG;IACH,YAAY;IACZ,YAAY;IACZ,WAAW;IACX,eAAe;IACf,gBAAgB;IAChB,eAAe;IACf,eAAe;CAChB,CAAC;AAEF,MAAM,UAAU,eAAe,CAAC,WAAoB;IAClD,MAAM,OAAO,GAAG,oBAAoB,CAAC,WAAW,CAAC,CAAC;IAClD,OAAO,CAAC,GAAG,gBAAgB,EAAE,GAAG,OAAO,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,EAAU,EAAE,WAAoB;IAC9D,OAAO,eAAe,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;AAC7D,CAAC"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
export const insecureDeserialization = {
|
|
2
|
+
id: 'insecure-deserialization',
|
|
3
|
+
name: 'Insecure Deserialization',
|
|
4
|
+
cwe: 'CWE-502',
|
|
5
|
+
filePatterns: ['serialize', 'deserialize', 'pickle', 'yaml', 'xml', 'marshal', 'json', 'parse', 'unserialize', 'decode', 'unmarshal'],
|
|
6
|
+
negativePatterns: [],
|
|
7
|
+
triagePrompt: `You are a security researcher hunting for insecure deserialization vulnerabilities.
|
|
8
|
+
|
|
9
|
+
Analyze the code for places where untrusted data is deserialized using functions that can instantiate arbitrary objects or execute code during parsing. Focus on:
|
|
10
|
+
|
|
11
|
+
LANGUAGE-SPECIFIC DANGEROUS FUNCTIONS:
|
|
12
|
+
Python:
|
|
13
|
+
- pickle.loads(), pickle.load() — arbitrary code execution via __reduce__
|
|
14
|
+
- yaml.load() without Loader=SafeLoader — arbitrary Python object instantiation
|
|
15
|
+
- marshal.loads() — code execution
|
|
16
|
+
- shelve.open() with untrusted data
|
|
17
|
+
- jsonpickle.decode() — object instantiation
|
|
18
|
+
|
|
19
|
+
JavaScript/Node.js:
|
|
20
|
+
- node-serialize unserialize() — code execution via IIFE in serialized functions
|
|
21
|
+
- js-yaml load() without safe option — can instantiate JS objects
|
|
22
|
+
- eval(JSON.parse(...)) or new Function(deserialized) — indirect RCE
|
|
23
|
+
- cryo.parse() — object instantiation
|
|
24
|
+
- serialize-javascript with user input feeding eval context
|
|
25
|
+
|
|
26
|
+
Java:
|
|
27
|
+
- ObjectInputStream.readObject() — gadget chain RCE
|
|
28
|
+
- XMLDecoder — arbitrary method calls
|
|
29
|
+
- XStream.fromXML() without allowlist
|
|
30
|
+
- Fastjson JSON.parseObject() with autoType — RCE
|
|
31
|
+
|
|
32
|
+
PHP:
|
|
33
|
+
- unserialize() — magic method exploitation (__wakeup, __destruct)
|
|
34
|
+
- phar:// deserialization — unserialize via Phar metadata
|
|
35
|
+
|
|
36
|
+
Ruby:
|
|
37
|
+
- YAML.load() (pre-Psych 4.0) — arbitrary Ruby object creation
|
|
38
|
+
- Marshal.load() — arbitrary object instantiation
|
|
39
|
+
|
|
40
|
+
WHAT MAKES THIS EXPLOITABLE:
|
|
41
|
+
- User-controlled input reaches the deserialization function
|
|
42
|
+
- The application has classes with dangerous side effects in constructors/destructors/magic methods
|
|
43
|
+
- The serialized format supports object types (not just primitive data)
|
|
44
|
+
- No type allowlist restricts what classes can be instantiated
|
|
45
|
+
|
|
46
|
+
SAFE ALTERNATIVES (not vulnerable):
|
|
47
|
+
- JSON.parse() for plain data (no object instantiation in standard JSON)
|
|
48
|
+
- yaml.safe_load() / yaml.load(Loader=SafeLoader) in Python
|
|
49
|
+
- Protocol Buffers, MessagePack, FlatBuffers (schema-defined, no arbitrary types)
|
|
50
|
+
- Java: ObjectInputFilter (JEP 290) with strict allowlist
|
|
51
|
+
- PHP: json_decode() instead of unserialize()
|
|
52
|
+
|
|
53
|
+
KNOWN BYPASS TECHNIQUES:
|
|
54
|
+
- Gadget chains: combining benign classes to achieve RCE (ysoserial for Java)
|
|
55
|
+
- Polyglot payloads: valid in multiple formats (JSON that's also valid YAML)
|
|
56
|
+
- Nested deserialization: outer format is safe but contains inner serialized payload
|
|
57
|
+
- Content-type confusion: server expects JSON but processes YAML/XML based on Content-Type header
|
|
58
|
+
- Cookie/session deserialization: serialized objects in cookies parsed server-side
|
|
59
|
+
|
|
60
|
+
RELEVANT SPECIFICATIONS:
|
|
61
|
+
- OWASP Top 10 2021 A08: Software and Data Integrity Failures
|
|
62
|
+
- CWE-502: Deserialization of Untrusted Data
|
|
63
|
+
- CWE-1321: Improperly Controlled Modification of Object Prototype Attributes
|
|
64
|
+
|
|
65
|
+
For each finding, cite the EXACT deserialization call, what user input reaches it, and what language-specific exploit primitive applies.`,
|
|
66
|
+
deepDivePrompt: `You are an expert security researcher writing a bug bounty report for an insecure deserialization vulnerability.
|
|
67
|
+
|
|
68
|
+
Given the hypothesis below, verify whether the vulnerability is real and exploitable.
|
|
69
|
+
|
|
70
|
+
VERIFICATION STEPS:
|
|
71
|
+
1. Confirm user-controlled input reaches the deserialization function
|
|
72
|
+
- Trace from HTTP request/cookie/message queue to the deserialize call
|
|
73
|
+
- Check if any sanitization or type filtering occurs before deserialization
|
|
74
|
+
2. Identify the deserialization function and its capabilities
|
|
75
|
+
- Can it instantiate arbitrary classes? (pickle, Java ObjectInputStream, PHP unserialize)
|
|
76
|
+
- Can it execute code during parsing? (YAML anchors, node-serialize IIFE)
|
|
77
|
+
- Is it limited to primitive types? (plain JSON.parse is generally safe)
|
|
78
|
+
3. Identify available gadget classes
|
|
79
|
+
- What libraries are in the dependency tree?
|
|
80
|
+
- Are there classes with dangerous __reduce__, __destruct, readObject methods?
|
|
81
|
+
4. Build the attack chain
|
|
82
|
+
- What object instantiation leads to code execution?
|
|
83
|
+
- What is the payload format?
|
|
84
|
+
|
|
85
|
+
PROOF-OF-CONCEPT:
|
|
86
|
+
Python pickle RCE:
|
|
87
|
+
\`\`\`python
|
|
88
|
+
import pickle, os
|
|
89
|
+
class Exploit:
|
|
90
|
+
def __reduce__(self):
|
|
91
|
+
return (os.system, ('id',))
|
|
92
|
+
payload = pickle.dumps(Exploit())
|
|
93
|
+
# Send payload to vulnerable endpoint
|
|
94
|
+
\`\`\`
|
|
95
|
+
|
|
96
|
+
Node.js node-serialize:
|
|
97
|
+
\`\`\`javascript
|
|
98
|
+
{"rce":"_$$ND_FUNC$$_function(){require('child_process').exec('id')}()"}
|
|
99
|
+
\`\`\`
|
|
100
|
+
|
|
101
|
+
SEVERITY ASSESSMENT:
|
|
102
|
+
- Critical: Remote Code Execution via deserialization (pickle, Java gadgets, PHP magic methods)
|
|
103
|
+
- Critical: Arbitrary file read/write via deserialization side effects
|
|
104
|
+
- High: Server-Side Request Forgery via deserialized URL fetchers
|
|
105
|
+
- High: Denial of Service via resource-exhausting deserialization (billion laughs, deep nesting)
|
|
106
|
+
- Medium: Object injection that modifies application state without RCE
|
|
107
|
+
|
|
108
|
+
RELEVANT SPECIFICATIONS:
|
|
109
|
+
- CWE-502: Deserialization of Untrusted Data
|
|
110
|
+
- OWASP Deserialization Cheat Sheet
|
|
111
|
+
- Java JEP 290: Filter Incoming Serialization Data
|
|
112
|
+
|
|
113
|
+
Cite exact file paths, line numbers, the deserialization function, and the input source.`,
|
|
114
|
+
knownBypasses: [
|
|
115
|
+
'Gadget chains: combining benign library classes to achieve RCE (ysoserial)',
|
|
116
|
+
'Polyglot payloads: data valid in multiple serialization formats simultaneously',
|
|
117
|
+
'Nested deserialization: safe outer format wrapping dangerous inner payload',
|
|
118
|
+
'Content-Type confusion: server parses YAML/XML when JSON expected',
|
|
119
|
+
'Cookie/session deserialization: serialized objects stored in client-side cookies',
|
|
120
|
+
'Phar deserialization in PHP: unserialize triggered via phar:// stream wrapper',
|
|
121
|
+
'YAML anchors and aliases: billion laughs DoS or object instantiation',
|
|
122
|
+
],
|
|
123
|
+
specReferences: [
|
|
124
|
+
'CWE-502 (Deserialization of Untrusted Data)',
|
|
125
|
+
'OWASP Top 10 2021 A08 (Software and Data Integrity Failures)',
|
|
126
|
+
'OWASP Deserialization Cheat Sheet',
|
|
127
|
+
'Java JEP 290 (Filter Incoming Serialization Data)',
|
|
128
|
+
],
|
|
129
|
+
severityRange: ['high', 'critical'],
|
|
130
|
+
};
|
|
131
|
+
//# sourceMappingURL=insecure-deserialization.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"insecure-deserialization.js","sourceRoot":"","sources":["../../../src/hunt/templates/insecure-deserialization.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,uBAAuB,GAA0B;IAC5D,EAAE,EAAE,0BAA0B;IAC9B,IAAI,EAAE,0BAA0B;IAChC,GAAG,EAAE,SAAS;IACd,YAAY,EAAE,CAAC,WAAW,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,WAAW,CAAC;IACrI,gBAAgB,EAAE,EAAE;IACpB,YAAY,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yIA0DyH;IAEvI,cAAc,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yFA+CuE;IAEvF,aAAa,EAAE;QACb,4EAA4E;QAC5E,gFAAgF;QAChF,4EAA4E;QAC5E,mEAAmE;QACnE,kFAAkF;QAClF,+EAA+E;QAC/E,sEAAsE;KACvE;IACD,cAAc,EAAE;QACd,6CAA6C;QAC7C,8DAA8D;QAC9D,mCAAmC;QACnC,mDAAmD;KACpD;IACD,aAAa,EAAE,CAAC,MAAM,EAAE,UAAU,CAAC;CACpC,CAAC"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
export const massAssignment = {
|
|
2
|
+
id: 'mass-assignment',
|
|
3
|
+
name: 'Mass Assignment',
|
|
4
|
+
cwe: 'CWE-915',
|
|
5
|
+
filePatterns: ['assign', 'merge', 'update', 'body', 'request', 'params', 'create', 'schema', 'spread', 'extend'],
|
|
6
|
+
negativePatterns: ['prisma', 'drizzle', 'typeorm'],
|
|
7
|
+
triagePrompt: `You are a security researcher hunting for mass assignment vulnerabilities.
|
|
8
|
+
|
|
9
|
+
Analyze the code for places where user-controlled input (req.body, request payload, form data) is directly spread or merged into database model updates without an explicit allowlist of permitted fields. Focus on:
|
|
10
|
+
1. Object spread: User.update({ ...req.body }) — attacker can set ANY field including role, isAdmin, balance
|
|
11
|
+
2. Object.assign: Object.assign(user, req.body) — same problem, all user-supplied fields are assigned
|
|
12
|
+
3. Lodash/underscore merge: _.merge(model, userInput) — deep merge can set nested fields
|
|
13
|
+
4. ORM create/update from raw body: Model.create(req.body), Model.findByIdAndUpdate(id, req.body)
|
|
14
|
+
5. Mongoose: doc.set(req.body) without specifying allowed paths
|
|
15
|
+
6. Sequelize: Model.update(req.body, { where: ... }) without specifying fields option
|
|
16
|
+
7. Framework-level mass assignment: Rails strong_parameters bypassed, Django form.save() without fields
|
|
17
|
+
|
|
18
|
+
CRITICAL FIELDS TO ESCALATE VIA MASS ASSIGNMENT:
|
|
19
|
+
- role, isAdmin, is_admin, admin, permissions, privilege — privilege escalation
|
|
20
|
+
- balance, credits, quota — financial manipulation
|
|
21
|
+
- email, emailVerified, email_verified — account takeover
|
|
22
|
+
- password, passwordHash, password_hash — account takeover
|
|
23
|
+
- organizationId, tenantId, org_id — cross-tenant access
|
|
24
|
+
- subscriptionTier, plan, isPremium — feature flag bypass
|
|
25
|
+
- approved, verified, active, status — state manipulation
|
|
26
|
+
|
|
27
|
+
CORRECT PATTERNS (not vulnerable):
|
|
28
|
+
- Explicit field picking: { name: req.body.name, email: req.body.email }
|
|
29
|
+
- Allowlist: pick(req.body, ['name', 'email', 'bio'])
|
|
30
|
+
- DTO/schema validation: Zod/Joi schema that only allows specific fields
|
|
31
|
+
- ORM with explicit fields: Model.update(data, { fields: ['name', 'email'] })
|
|
32
|
+
- GraphQL input types that restrict allowed fields at the schema level
|
|
33
|
+
|
|
34
|
+
KNOWN BYPASS TECHNIQUES:
|
|
35
|
+
- Nested objects: { "profile": { "role": "admin" } } if profile is spread into user
|
|
36
|
+
- Array fields: { "roles": ["admin"] } if roles array is directly assigned
|
|
37
|
+
- Prototype pollution via mass assignment: { "__proto__": { "isAdmin": true } }
|
|
38
|
+
- JSON field names with dots: { "user.role": "admin" } if flattened by middleware
|
|
39
|
+
- Extra fields in multipart form data alongside file uploads
|
|
40
|
+
|
|
41
|
+
RELEVANT SPECIFICATIONS:
|
|
42
|
+
- OWASP Top 10 2021 A04: Insecure Design
|
|
43
|
+
- OWASP API Security Top 10: API6 Mass Assignment
|
|
44
|
+
- CWE-915: Improperly Controlled Modification of Dynamically-Determined Object Attributes
|
|
45
|
+
|
|
46
|
+
For each finding, cite the EXACT line where user input is spread/merged into a model, and list which dangerous fields could be set.`,
|
|
47
|
+
deepDivePrompt: `You are an expert security researcher writing a bug bounty report for a mass assignment vulnerability.
|
|
48
|
+
|
|
49
|
+
Given the hypothesis below, verify whether the vulnerability is real and exploitable.
|
|
50
|
+
|
|
51
|
+
VERIFICATION STEPS:
|
|
52
|
+
1. Trace the data flow from request body to database write
|
|
53
|
+
2. Confirm no field allowlist or DTO validation exists between input and storage
|
|
54
|
+
3. Identify the database model/table schema — what fields exist that shouldn't be user-settable?
|
|
55
|
+
4. Determine the highest-impact field an attacker could set
|
|
56
|
+
5. Check if any middleware (Zod, Joi, class-validator) filters fields before the vulnerable line
|
|
57
|
+
|
|
58
|
+
BUILD THE ATTACK:
|
|
59
|
+
1. Show the legitimate request: POST /api/users with { name: "Alice", bio: "..." }
|
|
60
|
+
2. Show the attack request: POST /api/users with { name: "Alice", bio: "...", role: "admin" }
|
|
61
|
+
3. Prove the role field persists to the database
|
|
62
|
+
4. Show what the attacker gains (admin access, balance increase, etc.)
|
|
63
|
+
|
|
64
|
+
PROOF-OF-CONCEPT:
|
|
65
|
+
Provide a curl command showing the malicious payload:
|
|
66
|
+
\`\`\`
|
|
67
|
+
curl -X PUT /api/profile \\
|
|
68
|
+
-H "Content-Type: application/json" \\
|
|
69
|
+
-H "Authorization: Bearer <user-token>" \\
|
|
70
|
+
-d '{"name": "attacker", "role": "admin", "isVerified": true}'
|
|
71
|
+
\`\`\`
|
|
72
|
+
|
|
73
|
+
SEVERITY ASSESSMENT:
|
|
74
|
+
- Critical: Can set role/admin/permissions fields (privilege escalation)
|
|
75
|
+
- Critical: Can set financial fields (balance, credits, subscription)
|
|
76
|
+
- High: Can set email/password fields (account takeover path)
|
|
77
|
+
- High: Can set organizationId (cross-tenant access)
|
|
78
|
+
- Medium: Can set non-critical profile fields of other users
|
|
79
|
+
- Low: Can set fields that have no security impact
|
|
80
|
+
|
|
81
|
+
RELEVANT SPECIFICATIONS:
|
|
82
|
+
- CWE-915: Improperly Controlled Modification of Dynamically-Determined Object Attributes
|
|
83
|
+
- OWASP API Security Top 10: API6 Mass Assignment
|
|
84
|
+
|
|
85
|
+
Cite exact file paths, line numbers, and the specific dangerous fields that can be set.`,
|
|
86
|
+
knownBypasses: [
|
|
87
|
+
'Nested object injection: { "profile": { "role": "admin" } }',
|
|
88
|
+
'Array field replacement: { "roles": ["admin"] }',
|
|
89
|
+
'Prototype pollution via mass assignment: { "__proto__": { "isAdmin": true } }',
|
|
90
|
+
'Dot-notation keys flattened by middleware: { "user.role": "admin" }',
|
|
91
|
+
'Multipart form data extra fields alongside file uploads',
|
|
92
|
+
'JSON merge patch (RFC 7396) setting unexpected fields',
|
|
93
|
+
],
|
|
94
|
+
specReferences: [
|
|
95
|
+
'CWE-915 (Improperly Controlled Modification of Dynamically-Determined Object Attributes)',
|
|
96
|
+
'OWASP API Security Top 10 API6 (Mass Assignment)',
|
|
97
|
+
'OWASP Top 10 2021 A04 (Insecure Design)',
|
|
98
|
+
],
|
|
99
|
+
severityRange: ['medium', 'critical'],
|
|
100
|
+
};
|
|
101
|
+
//# sourceMappingURL=mass-assignment.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mass-assignment.js","sourceRoot":"","sources":["../../../src/hunt/templates/mass-assignment.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,cAAc,GAA0B;IACnD,EAAE,EAAE,iBAAiB;IACrB,IAAI,EAAE,iBAAiB;IACvB,GAAG,EAAE,SAAS;IACd,YAAY,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC;IAChH,gBAAgB,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,SAAS,CAAC;IAClD,YAAY,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oIAuCoH;IAElI,cAAc,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;wFAsCsE;IAEtF,aAAa,EAAE;QACb,6DAA6D;QAC7D,iDAAiD;QACjD,+EAA+E;QAC/E,qEAAqE;QACrE,yDAAyD;QACzD,uDAAuD;KACxD;IACD,cAAc,EAAE;QACd,0FAA0F;QAC1F,kDAAkD;QAClD,yCAAyC;KAC1C;IACD,aAAa,EAAE,CAAC,QAAQ,EAAE,UAAU,CAAC;CACtC,CAAC"}
|