How to Hunt Your Web Server Logs for Path-Normalization Evasion
🛡️ Security Intermediate 5 min read

How to Hunt Your Web Server Logs for Path-Normalization Evasion

Encoded-path bypasses succeed silently and never trip a firewall counter. A practical hunt through server logs for the probes, web shells, and process activity they leave behind.

Published: September 27, 2026 • Updated: September 27, 2026
threat huntinglog analysisdetectionincident responseweb shell

When an attacker defeats a firewallFirewall🌐Security system that monitors and controls network traffic based on predetermined rules. rule by encoding part of the request path, the exploitExploit🛡️Code or technique that takes advantage of a vulnerability to cause unintended behavior, such as gaining unauthorized access. succeeds silently and your block counter never moves. The only durable record that anything happened lives in your web server and application logs, and only if you know what to look for. This is a practical guide to hunting those logs for path-normalization evasion, using the ShinyHunters PeopleSoft campaign as a worked example, so you can find the probes and the follow-on activity whether or not your perimeter caught them.

Start With the Right Log

The first decision is which log to trust. A WAF's own log tells you what the WAF matched, which by definition excludes the requests that bypassed it. The authoritative source is the log written by the component that actually served the request: the web server or application server access log, sitting behind the firewall. For a PeopleSoft deployment that is the WebLogic access log. For a typical stack it is the nginx, Apache, or IIS access log on the origin.

Confirm that this log records the full request path, ideally in its raw, still-encoded form. Some logging configurations write the decoded or rewritten path, which erases exactly the evidence you need. If you can capture both the raw and the normalized path, you gain the single most useful detection in this whole exercise, described below.

Hunt One: Encoded Characters in Plain Paths

Legitimate traffic to a fixed application endpoint almost never arrives percent-encoded. A browser requesting `/PSEMHUB/hub` sends those literal characters; it has no reason to send `/%50SEMHUB/hub`. So the presence of `%` inside a path segment that is normally plain text is your highest-signal indicator.

Search the access log for requests where the raw path contains a percent sign in a location that should hold ordinary letters. In the PeopleSoft case, hunt for any request to a path that decodes to `/PSEMHUB/` but was not spelled that way literally: `%50`, `%53`, mixed-case, or double-encoded forms like `%2550`. If your platform can log both the raw and the decoded path, alert whenever the two differ for a request to a sensitive endpoint. That single comparison catches the entire family of encoding evasions without your having to enumerate each variant, which is precisely the weakness of string matching that we examine in why URL encoding lets attackers slip past string-matching WAF rules.

Hunt Two: The Reconnaissance Signature

Attackers rarely fire the payload blind. In this campaign, Mandiant observed 5 to 15 POST requests to the encoded `/hub` endpoint carrying serialized Java objects, used to confirm a server was exploitable before anything was written to disk. That burst of POSTs to a single administrative endpoint from one source, close together in time, with no corresponding legitimate session, is a recognizable shape.

Look for clusters of POST requests to `/hub` or its encoded equivalents from a single client address, especially where the request bodies are unusually uniform in size. Because these probes deliberately avoid writing files, they will not show up in a file-integrity scan; the log is the only place they appear.

Hunt Three: Requests That Should Never Come From Outside

The next tier of evidence is external requests for resources that only internal tooling should touch. After gaining execution, the operators dropped JSP web shells such as `x.jsp`, `u.jsp`, `tunnel.jsp`, and `tunnel.jspx` into the application directory. Traffic to those files is damning because they are not part of the shipped application.

Query the access log for GET or POST requests to any `.jsp` or `.jspx` file that is not on your known inventory of legitimate application pages, particularly from external addresses. Pair this with a filesystem check of the PSEMHUB.war directory for files that were not part of the deployment. A web shellWeb Shell🛡️A malicious script placed in a web server's content directory that lets an attacker execute commands through HTTP requests. Web shells are a common persistence mechanism after remote code execution and are detected by looking for unexpected files in webapp directories. that lives on disk like these leaves both a file and a log trail; a stealthier attacker may load a shell only into memory, a harder problem we address in how to hunt for in-memory webshells that leave no file on disk.

Hunt Four: Process Lineage on the Host

Logs at the edge tell you about requests; host telemetry tells you what those requests caused. The most reliable host-side signal for a web shell is anomalous process lineageProcess Lineage🛡️The parent-child chain of processes on a host, showing which process launched which. Hunting on lineage catches exploitation because compromised services spawn children they never would in normal operation.: a command interpreter spawned by the web application's runtime. A WebLogic Java process has no legitimate reason to launch `cmd.exe`, `/bin/sh`, or `bash`.

If you have endpoint detection or process auditing, alert on any shell spawned by the application server's Java process, and on that process invoking tools like `base64`, `curl`, `/dev/tcp`, `tasklist`, or `start /b`, which appeared in the observed post-exploitation commands. This is the same living-off-the-land tradecraft covered in how to detect living-off-the-land abuse on network security appliances, applied to an application server.

Turn Findings Into Scope

Once you have a hit, use the timeline to bound the incident. The first encoded probe from a source address marks the earliest suspicious contact; the first successful POST to the vulnerable endpoint marks likely compromise. Everything that service accountService Account🛡️A non-human operating system or application account under which a service runs. Its permissions define the blast radius of any exploit against that service, since attacker code executes with the service account's access to files, secrets, and the network. did after that point is in scope, including reading stored credentials. Preserve the logs before you remediate, because rebuilding the host destroys them, and pivot immediately to rotating every secret the compromised account could read.

Build It In Before You Need It

The reason this hunt is possible at all is that the requests were logged with enough fidelity to reconstruct them. The reason it is often not possible is that logging was configured for troubleshooting, not forensics. Log raw request paths, retain access logs long enough to cover the gap between a vendor advisory and your patch window, and centralize them where they survive a host rebuild. Detection of path-normalization evasion is not exotic; it is ordinary log hygiene applied with the knowledge that your firewall may not have seen what your server did.