This example shows a server-layer triage workflow.
The goal is not to exploit one specific web server. The goal is to learn how we move from a normal web application finding into server-aware impact.
We use the same process against NGINX, Apache, and IIS:
fingerprint
-> enumerate hosts and paths
-> identify server behavior
-> locate config and logs
-> map handlers and upload paths
-> test server-specific weaknesses
-> document remediation and detection
Step 1: Fingerprint
Start with headers and behavior.
curl -i http://target/
curl -i http://target/does-not-exist
curl -I http://target/
whatweb http://target/
nikto -h http://target/
Record:
- Status codes
- Server header
- Redirect behavior
- Error page style
- Cookies
- Interesting headers
- Default pages
- Technology fingerprints
Do not trust the Server header by itself. Reverse proxies and load balancers can hide the origin server.
Step 2: Enumerate Virtual Hosts
If the target is an IP address or a known hostname, test host routing.
ffuf -u http://TARGET_IP/ -H "Host: FUZZ.example.local" \
-w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt
Findings to watch for:
- Different response length
- Different title
- Different redirect
- Different cookie
- Different error page
- New admin or staging app
Virtual hosts often expose the real application surface.
Step 3: Enumerate Content
Run a first-pass directory sweep.
gobuster dir -u http://target/ \
-w /usr/share/seclists/Discovery/Web-Content/common.txt
Then test extensions that match the suspected stack.
Apache/PHP:
gobuster dir -u http://target/ \
-w /usr/share/seclists/Discovery/Web-Content/common.txt \
-x php,txt,bak,old,zip
IIS/ASP.NET:
gobuster dir -u http://target/ \
-w /usr/share/seclists/Discovery/Web-Content/common.txt \
-x aspx,ashx,asmx,config,txt,bak,zip
NGINX depends on the upstream application, so choose extensions based on observed behavior.
Step 4: Check Server-Specific Paths
Apache:
/server-status
/server-info
/cgi-bin/
/.htaccess
/.htpasswd
NGINX:
/nginx_status
/stub_status
/status
/uploads/
/static/
IIS:
/aspnet_client/
/trace.axd
/elmah.axd
/web.config
/App_Data/
/bin/
We are looking for misconfiguration, not just version banners.
Step 5: If LFI Exists, Read The Map
Local file read changes the workflow. Instead of guessing, read configuration and logs.
Apache targets:
/etc/apache2/apache2.conf
/etc/apache2/sites-enabled/000-default.conf
/var/log/apache2/access.log
/var/log/apache2/error.log
NGINX targets:
/etc/nginx/nginx.conf
/etc/nginx/sites-enabled/default
/etc/nginx/conf.d/default.conf
/var/log/nginx/access.log
/var/log/nginx/error.log
IIS targets:
C:\inetpub\wwwroot\web.config
C:\Windows\System32\inetsrv\config\applicationHost.config
C:\inetpub\logs\LogFiles\
Use these files to answer:
- What is the real webroot?
- Which upload directory is active?
- Which extensions execute?
- Are there aliases or virtual directories?
- Are there internal upstreams?
- Are there admin paths protected only by the web server?
Step 6: Log Poisoning Reasoning
Log poisoning is a chain, not a standalone bug.
Required conditions:
controlled request data reaches a log
+ local file include reads that log
+ the runtime interprets the included log as code
Safe marker:
curl -A "ootw-log-marker" http://target/
Then read the likely log through the file-read primitive.
Expected finding:
ootw-log-marker appears in access.log
That proves write influence over the log. It does not prove code execution by itself.
For PHP applications, the dangerous version appears when the application uses include, require, or similar behavior on a path we control.
Step 7: Upload And Handler Reasoning
File uploads become server bugs when the server executes the uploaded file.
Check:
- Where does the file land?
- Is the directory under the webroot?
- Which extensions are allowed?
- Which extensions execute?
- Can a per-directory config file change handlers?
- Can the file be requested directly?
Apache-specific risk:
.htaccess can remap extensions when AllowOverride allows it.
IIS-specific risk:
web.config can change directory behavior when upload and permissions allow it.
NGINX-specific risk:
global PHP-FPM rules may execute uploaded .php files unless uploads are blocked from script handling.
Step 8: IIS Tilde Enumeration
If the server is IIS, test whether short-name behavior leaks file names.
Use a scanner in labs:
IIS-ShortName-Scanner
shortscan
sns
Follow-up logic:
1. Find a short name such as ADMINI~1.
2. Generate likely full names.
3. Fuzz those names with IIS extensions.
4. Confirm whether the resource is reachable.
This is enumeration. It leaks names; it does not directly read file contents.
Step 9: Report The Finding Correctly
Good server findings describe the broken boundary.
Weak report:
The target runs Apache.
Better report:
The Apache virtual host allows directory listing on /uploads/. The directory contains backup PHP files and old database exports. Disable Indexes for this directory and remove backup files from the webroot.
Weak report:
The access log is readable.
Better report:
The application LFI can read /var/log/nginx/access.log. Request headers controlled by the client are written into that file. If a PHP include sink is reachable, this can become log poisoning. Restrict file reads to an allowlist and prevent application users from reading server logs.
Detection
Monitor for:
- Large bursts of 404s and 403s
- Requests for
.git,.env, backups, and config files - Requests for
.htaccess,.htpasswd,web.config,applicationHost.config - Requests containing
../, encoded traversal, or double encoding - Requests containing
~1,*~1*, or other IIS short-name patterns - Unusual HTTP verbs such as
PUT,PROPFIND,MOVE,COPY,DELETE - User agents containing code-like strings
- Repeated probes against
/server-status,/nginx_status,/trace.axd,/elmah.axd - Uploads followed by direct requests to the uploaded path
Server logs are not only evidence after compromise. They are also where early reconnaissance becomes visible.