role_escalation_test
Test for privilege escalation vulnerabilities by sending requests with manipulated role cookies and JSON body fields to identify unauthorized access opportunities.
Instructions
Test cookie/parameter-based role escalation.
Sends requests with various role cookie values (Admin=true, roleid=2, etc.) and checks for privilege escalation. Also tests JSON body field manipulation for profile update endpoints.
Returns: {"baseline": dict, "results": [{"value": str, "status": int, "length": int, "escalated": bool}], "escalation_candidates": [str]}.
Side effects: If json_body is set, sends POST/PUT requests that may modify state.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | Protected URL to access, e.g. https://target/admin or https://target/api/users | |
| cookie_name | Yes | Cookie name for role control, e.g. 'admin', 'role', 'is_admin' | |
| cookie_values | Yes | Values to test, e.g. ['true','1','admin','2','yes'] | |
| extra_cookies | No | Additional cookies to include, e.g. 'session=abc123; logged_in=true' | |
| json_body | No | JSON body for POST-based role escalation, e.g. '{"roleid":2}'. Will test each value substituted | |
| json_field | No | JSON field to manipulate in json_body, e.g. 'roleid' |
Implementation Reference
- src/tools/accesscontrol.ts:157-329 (handler)The tool `role_escalation_test` is registered and implemented here. It takes a URL, cookie name, and various values, then performs curl requests with different cookies to test for privilege escalation based on HTTP status code changes or response length discrepancies.
server.tool( "role_escalation_test", "Test cookie/parameter-based role escalation.\n\nSends requests with various role cookie values (Admin=true, roleid=2, etc.) and checks for privilege escalation. Also tests JSON body field manipulation for profile update endpoints.\n\nReturns: {\"baseline\": dict, \"results\": [{\"value\": str, \"status\": int, \"length\": int, \"escalated\": bool}], \"escalation_candidates\": [str]}.\n\nSide effects: If json_body is set, sends POST/PUT requests that may modify state.", { url: z .string() .describe( "Protected URL to access, e.g. https://target/admin or https://target/api/users" ), cookie_name: z .string() .describe( "Cookie name for role control, e.g. 'admin', 'role', 'is_admin'" ), cookie_values: z .array(z.string()) .min(1) .max(20) .describe( "Values to test, e.g. ['true','1','admin','2','yes']" ), extra_cookies: z .string() .optional() .describe( "Additional cookies to include, e.g. 'session=abc123; logged_in=true'" ), json_body: z .string() .optional() .describe( "JSON body for POST-based role escalation, e.g. '{\"roleid\":2}'. Will test each value substituted" ), json_field: z .string() .optional() .describe( "JSON field to manipulate in json_body, e.g. 'roleid'" ), }, async ({ url, cookie_name, cookie_values, extra_cookies, json_body, json_field, }) => { requireTool("curl"); // Baseline without the role cookie const baselineArgs = [ "-sk", "-o", "-", "-w", "\n__META__%{http_code}:%{size_download}", ]; if (extra_cookies) { baselineArgs.push("-b", extra_cookies); } baselineArgs.push(url); const baselineRes = await runCmd("curl", baselineArgs); let baseBody = baselineRes.stdout; const baseMetaMarker = baseBody.lastIndexOf("__META__"); let baseStatus = 0; let baseLength = 0; if (baseMetaMarker !== -1) { const meta = baseBody.slice(baseMetaMarker + 8).trim(); const parts = meta.split(":"); baseStatus = parts[0] ? parseInt(parts[0], 10) : 0; baseLength = parts[1] ? parseInt(parts[1], 10) : 0; } const results: Array<{ cookie_value: string; status: number; length: number; escalated: boolean; response_snippet: string; }> = []; const escalationCandidates: string[] = []; for (const value of cookie_values) { let cookieStr = `${cookie_name}=${value}`; if (extra_cookies) { cookieStr = `${extra_cookies}; ${cookieStr}`; } let curlArgs: string[]; if (json_body && json_field) { // POST/PUT with modified JSON body let modifiedBody = json_body; try { const bodyDict = JSON.parse(json_body); bodyDict[json_field] = value; modifiedBody = JSON.stringify(bodyDict); } catch { modifiedBody = json_body; } curlArgs = [ "-sk", "-o", "-", "-w", "\n__META__%{http_code}:%{size_download}", "-X", "POST", "-H", "Content-Type: application/json", "-d", modifiedBody, "-b", cookieStr, url, ]; } else { curlArgs = [ "-sk", "-o", "-", "-w", "\n__META__%{http_code}:%{size_download}", "-b", cookieStr, url, ]; } const res = await runCmd("curl", curlArgs); let resBody = res.stdout; const metaMarker = resBody.lastIndexOf("__META__"); let status = 0; let length = 0; if (metaMarker !== -1) { const meta = resBody.slice(metaMarker + 8).trim(); const parts = meta.split(":"); status = parts[0] ? parseInt(parts[0], 10) : 0; length = parts[1] ? parseInt(parts[1], 10) : 0; resBody = resBody.slice(0, metaMarker); } const escalated = (status === 200 && [401, 403, 302].includes(baseStatus)) || (Math.abs(length - baseLength) > 100 && status === 200); const entry = { cookie_value: value, status, length, escalated, response_snippet: resBody.slice(0, 500), }; results.push(entry); if (escalated) { escalationCandidates.push(value); } } const result = { baseline: { status: baseStatus, length: baseLength }, cookie_name, results, escalation_candidates: escalationCandidates, hint: escalationCandidates.length > 0 ? `Role escalation possible with ${cookie_name}=${JSON.stringify(escalationCandidates)}` : "No escalation detected. Try different cookie names or values.", }; return { content: [{ type: "text", text: JSON.stringify(result) }] };