1---2name: analyzing-web-server-logs-for-intrusion3description: Parse Apache and Nginx access logs to detect SQL injection attempts, local file inclusion, directory traversal, web scanner fingerprints, and brute-force patterns. Uses regex-based pattern matching against OWASP attack signatures, GeoIP enrichment for source attribution, and statistical anomaly detection for request frequency and response size outliers.4license: Apache-2.05---6
7
8# Analyzing Web Server Logs for Intrusion
9
10
11## When to Use
12
13- When investigating security incidents that require analyzing web server logs for intrusion
14- When building detection rules or threat hunting queries for this domain
15- When SOC analysts need structured procedures for this analysis type
16- When validating security monitoring coverage for related attack techniques
17
18## Detection Gaps & Validation
19
20- **Regex misses encoded SQLi:** `UNION SELECT` and `OR 1=1` are easy, but URL-encoding (`%55NION`), inline comments (`UNI/**/ON SE/**/LECT`), case mixing, and double-encoding bypass naive signatures. Normalize (URL-decode twice, strip comments, lowercase) before matching, and prefer libinjection-style tokenization over literal strings.
21- **POST bodies and headers are invisible in access logs:** Apache/Nginx access logs record only the request line and query string — SQLi/XSS/LFI in POST bodies, cookies, or custom headers won't appear unless mod_security audit logging or body capture is enabled. State this coverage gap explicitly; an empty result over `access.log` is not proof of no attack.
22- **Scanner UA spoofing:** sophisticated actors set a Chrome User-Agent, so `nikto|sqlmap|gobuster` UA matching only catches lazy scans. Add request-rate, 404-ratio, and path-fuzzing-burst heuristics independent of UA.
23- **LFI/traversal evasion:** beyond `../etc/passwd`, test `..%2f`, `..%252f` (double-encode), `....//`, and absolute `/etc/passwd` with no traversal — match `root:.*:0:0:` in responses, not just the request.
24- **Validate the rules fire:** replay a labeled attack log (sqlmap run, dirbuster sweep, a brute-force burst >50 POSTs/5min to `/login`) through the parser and confirm each rule and the GeoIP enrichment populate. **FP tuning:** WAF health checks, search-engine bots, and legitimate apps passing SQL keywords in search fields cause false hits — baseline trusted IPs/paths.
25
26## Prerequisites
27
28- Familiarity with security operations concepts and tools
29- Access to a test or lab environment for safe execution
30- Python 3.8+ with required dependencies installed
31- Appropriate authorization for any testing activities
32
33## Instructions
34
351. Install dependencies: `pip install geoip2 user-agents`
362. Collect web server access logs in Combined Log Format (Apache) or Nginx default format.
373. Parse each log entry extracting: IP, timestamp, method, URI, status code, response size, user-agent, referer.
384. Apply detection rules:
39 - SQL injection: `UNION SELECT`, `OR 1=1`, `' OR '`, hex encoding patterns
40 - LFI/Path traversal: `../`, `/etc/passwd`, `/proc/self`, `php://filter`
41 - XSS: `<script>`, `javascript:`, `onerror=`, `onload=`
42 - Scanner signatures: nikto, sqlmap, dirbuster, gobuster, wfuzz user-agents
43 - Brute force: >50 POST requests to login endpoints from same IP in 5 minutes
445. Enrich with GeoIP data and generate a prioritized findings report.
45
46```bash
47python scripts/agent.py --log-file /var/log/nginx/access.log --geoip-db GeoLite2-City.mmdb --output web_intrusion_report.json
48```
49
50## Examples
51
52### Detect SQLi in URI
53```
54192.168.1.100 - - [15/Jan/2024:10:30:45 +0000] "GET /products?id=1' UNION SELECT username,password FROM users-- HTTP/1.1" 200 4532
55```
56
57### Scanner User-Agent Detection
58```
59Nikto/2.1.6, sqlmap/1.7, DirBuster-1.0-RC1, gobuster/3.1.0
60```