Vulnerabilities & Exploits

What Is a Zero-Day Vulnerability?

HuntRule Team · · 8 min read

An unlit doorway standing open in a plain concrete wall at night with a blank clock face beside the frame
On this page

An operator wrote human2.aspx into C:\MOVEitTransfer\wwwroot\ four days before Progress had a patch to give anyone. CISA's KEV entry for the bug behind it lists CWE-89. SQL injection, the same class taught in the first hour of any web security course. That pairing is the whole point of the term. Zero-day describes what the vendor and the defender knew at the time. It says nothing about how clever the bug was.

Three things share the name

The word gets attached to three separate objects, and arguments about zero-days usually turn out to be two people holding different ones.

  • The vulnerability. A flaw the vendor does not know about, so no patch exists.

  • The exploit. Working code that triggers it reliably.

  • The attack. Use of that exploit in the wild while the first two conditions still hold.

The counter runs on the vendor's clock. Day zero is the day the vendor finds out. The moment a fix ships, the same flaw becomes an n-day and the same exploit becomes an n-day exploit. Nothing in the code changed. Only the distribution of knowledge did. Separating the three matters operationally, because your detection strategy attaches to the third one and your patch strategy attaches to the second.

The timeline, in order

  1. Discovery. Somebody finds the flaw. Could be the vendor, a researcher, a broker, an intrusion crew.

  2. Exploit development. Reliable code against a specific version range.

  3. Exploitation in the wild. For CVE-2023-34362, Mandiant's earliest evidence from incident response was 27 May 2023.

  4. Vendor awareness and disclosure. Progress published its advisory on 31 May 2023.

  5. Patch availability. Fixed builds and interim guidance (block inbound HTTP and HTTPS to the MOVEit interface) came with that advisory.

  6. Patch deployment. Yours. CISA added the CVE to KEV on 2 June 2023 with a federal remediation due date of 23 June 2023.

Only stages one through three are the zero-day. Stage six is the only stage you control, and it is the one most organisations measure worst.

The window you actually own

Mandiant's analysis of 2023 exploitation counted 138 vulnerabilities disclosed as exploited in the wild that year. 97 of them, 70.3%, were exploited as zero-days. The remaining 41 were n-days, exploited only after a patch existed. Average time-to-exploit across the set fell to 5 days, down from 32 in 2021 to 2022. Of the n-days, 12% were exploited within one day of patch release and 56% within one month.

Hold that last figure against your own change window. If an internet-facing appliance waits 30 days for its maintenance slot, more than half of all n-day exploitation happens inside a gap you chose. Nobody chose the zero-day window. That is the reframe: the panic about zero-days is mostly spent on the one stage where no decision of yours was available, while the stage that is entirely yours gets a ticket in a queue.

MOVEit is also the case where this reframe does not save you, so it is worth saying plainly. Mass exploitation ran from 27 May, the advisory landed on 31 May, and the KEV due date of 23 June was three weeks after the data was already gone. When the window you own opens after the actor has finished, patching was never the control that mattered. Detection was.

What the exploitation left behind

You cannot write a signature for a SQL injection you have not seen. You can write one for what happens next, because what happens next is not novel. Reconstructing the chain from Mandiant's report and CISA advisory AA23-158A:

  • POST requests to the legitimate guestaccess.aspx, carrying the injection.

  • A C# page written into the MOVEit web root as human2.aspx or _human2.aspx, sitting one character away from the real human.aspx.

  • csc.exe spawned by w3wp.exe to compile it, producing an App_Web_<8 random chars>.dll.

  • The shell answering only requests that carry an X-siLock-Comment header matching a 36-character GUID fixed at install time. Everything else gets an HTTP 404.

  • Tasking in X-siLock-Step1, X-siLock-Step2 and X-siLock-Step3. It enumerates files, folders and owners, pulls AzureBlobStorageAccount, AzureBlobKey and AzureBlobContainer from the MOVEit application settings, and returns gzip-compressed results over the same HTTP session.

  • Creation and later deletion of a MOVEit user whose LoginName and RealName are both Health Check Service.

Delete FROM users WHERE RealName='Health Check Service'

Every one of those lines except the first is generic. A web server process writing a script file into its own web root. A compiler running as a child of a web server. A page that authenticates on a header and 404s everything else. Mandiant named the shell LEMURLOOT and attributed the cluster (UNC4857, later merged into FIN11) to the CL0P leak site, but none of that naming is load-bearing for detection. The behaviour was in scope for rules written years earlier.

A rule for the stage after the exploit

This is a file event rule, not an exploit rule. It fires on the drop, not the injection.

title: Server-Side Script Written to Web Root by IIS Worker Process
id: 7b8f2c41-6d3e-4a19-9c5b-0f2ad84e61c7
status: experimental
description: |
    Detects w3wp.exe writing a server-side script file to disk. An IIS worker
    process that authors its own pages is the file-system trace left by most
    ASPX web shells, including the LEMURLOOT drop that followed exploitation
    of CVE-2023-34362 in MOVEit Transfer.
references:
    - https://cloud.google.com/blog/topics/threat-intelligence/zero-day-moveit-data-theft
    - https://www.cisa.gov/news-events/cybersecurity-advisories/aa23-158a
author: HuntRule
date: 2026-07-31
tags:
    - attack.persistence
    - attack.t1505.003
    - attack.initial-access
    - attack.t1190
logsource:
    category: file_event
    product: windows
detection:
    selection_image:
        Image|endswith: '\w3wp.exe'
    selection_extension:
        TargetFilename|endswith:
            - '.asax'
            - '.ashx'
            - '.asmx'
            - '.asp'
            - '.aspx'
            - '.cshtml'
    filter_compilation_cache:
        TargetFilename|contains:
            - '\Temporary ASP.NET Files\'
            - '\inetpub\temp\'
            - '\Microsoft.NET\Framework64\'
    condition: all of selection_* and not 1 of filter_*
falsepositives:
    - Application deployments and in-place upgrades performed under the app pool identity
    - Self-updating web applications and CMS plugin installers
    - Custom error page generation by some frameworks
level: high

The companion signal on the same host is process ancestry. SigmaHQ already ships a generic version of this as Suspicious Process By Web Server Process (id 8202070f-edeb-4d31-a010-a26c72ac5600), tagged attack.t1505.003 and attack.t1190. Add the compiler to your local copy if it is not there:

detection:
    parent_webserver:
        ParentImage|endswith: '\w3wp.exe'
    child_compiler:
        Image|endswith:
            - '\csc.exe'
            - '\vbc.exe'
    condition: parent_webserver and child_compiler

On a MOVEit Transfer host that pairing is worth a page. MOVEit ships precompiled, so runtime C# compilation under the app pool has no routine cause there. On a general IIS box hosting classic ASP.NET applications with dynamic compilation, csc.exe under w3wp.exe is normal traffic and this fragment is noise. Scope it per host role, not globally. Rule scoping by asset class is the boring half of detection engineering and the half that decides whether anyone reads the alert.

What the rule does not give you

  • No coverage of the vulnerability. The SQL injection into guestaccess.aspx happens before the first event this rule sees. If the actor only reads data over the injection and never drops a file, the rule stays silent for the entire intrusion.

  • No coverage of memory-only implants. A shell loaded reflectively into the worker process leaves no TargetFilename.

  • No coverage of non-IIS stacks. Tomcat, nginx with PHP-FPM and Node need parallel rules with different parent images and different extensions.

  • Dependence on your Sysmon config. This needs FileCreate (Event ID 11) actually logging these extensions. Check your include and exclude rule groups rather than assuming, because several stock configurations trim file events aggressively for volume.

  • A gap on overwrite-in-place. An actor appending to an existing legitimate page instead of creating a new one may not produce a FileCreate at all.

  • Nothing on exfiltration. The data left over the same HTTPS session the shell was tasked on, which looks like ordinary MOVEit traffic in flow logs.

The rule above is written from public reporting on the MOVEit intrusions, not from telemetry of our own. Validate it against your Sysmon build and your IIS estate before you promote it out of a hunting query.

ATT&CK mapping

Technique

ID

Covered here

Exploit Public-Facing Application

T1190

No. Pre-drop, and specific to the CVE.

Server Software Component: Web Shell

T1505.003

Yes, by the file event rule.

Obfuscated Files or Information: Compile After Delivery

T1027.004

Yes, by the process ancestry fragment.

Exfiltration Over C2 Channel

T1041

No. Needs application-layer or volume analytics.

Summary

Zero-day is a knowledge claim, not a difficulty claim. CVE-2023-34362 was a SQL injection, and it worked because nobody outside the operator knew about it for four days. The stage you cannot detect is short and the stage you can detect starts immediately afterwards, which is why behavioural coverage of web shell drops, unexpected child processes and new privileged accounts pays out regardless of which CVE opened the door. Patch fast, but stop treating the patch as the detection. Browse the catalog for coverage on this stage at /rules?q=webshell and for the surrounding host behaviour at /rules?domain=windows.

Collect these before you need them:

Sysmon EID 1   Process creation, with ParentImage (w3wp.exe children)
Sysmon EID 11  FileCreate, extensions .asp .aspx .ashx .asmx .asax .cshtml
Sysmon EID 3   Network connect, outbound from w3wp.exe
Security 4720  A user account was created
Security 4728  Member added to a security-enabled global group
IIS logs       cs-uri-stem, cs-method, sc-status, c-ip, time-taken

Related articles