In this easy-difficulty scenario, Sherlock, our digital landscape may currently be under threat. The source of this potential risk is a recent Common Vulnerabilities and Exposures (CVE) announcement related to the MOVEit software. We may have overlooked this amidst the flurry of news articles.
Our Windows server, which we suspect to be vulnerable, might have already been compromised. You have been tasked with the analysis of artifacts provided in the triage.
Your mission is to understand the specifics of this particular exploit, confirm the activities of the potential attacker, and extract valuable details that can be incorporated into our Security Operations Center (SOC) environment. Your responsibility will include analyzing the artifacts, answering relevant questions regarding the exploitation of one of our vulnerable, yet critical, hosts, and interpreting these details to help improve our SOC environment.
An external host scanned a MOVEit Transfer server with Nmap, then exploited the MOVEit SQL injection (CVE-2023-34362) with a Ruby-based exploit that identified itself in the web logs. The attacker first dropped a classic ASP webshell that never worked, then reset the password of the MOVEit service account, logged in over RDP and pulled down a working ASPX webshell with a PowerShell download into the web root. The shell was then driven from a Firefox user agent. The MOVEit database, IIS logs, the MFT, Windows event logs and a memory image together recover the whole chain, including the new service-account password.
u_ex230712.log → read with grep. W3C format, spaces in the user agent are written as +moveit.sql → read with grep/sed. The log table records MOVEit’s own view of each request.evtx files from the triage → parse with EvtxECmd, filter the CSV with PythonMFTECmdConsoleHost_history.txt for the users on the host → read with cat.vmem → strings and grep (UTF-16 and ASCII)Timestamp note: Several questions want
DD/MM/YYYY HH:MM:SS. All times in this page are UTC and the activity falls on 12 July 2023.
The IIS log is the earliest record of the attacker. Around 10:11 a burst of requests carries a user agent that names the scanner outright, an NSE-driven probe of the web server.
grep -i 'nmap' u_ex230712.log | head
The c-ip field on the scanner requests, and on every request that follows to the MOVEit endpoints, is the same address. It is the only external-looking source touching /guestaccess.aspx and /moveitisapi. The IP also matches the later RDP logon and the download host in the PowerShell history.
grep -E 'guestaccess|moveitisapi' u_ex230712.log | awk '{print $9}' | sort | uniq -c
The exploit traffic is the run of requests to /guestaccess.aspx and the /moveitisapi handler. Its user agent is a Ruby HTTP client, and the same string shows up as AgentBrand in the log table of moveit.sql.
grep -E 'guestaccess.aspx|moveitisapi' u_ex230712.log
Gotcha: The Nmap user agent from Q6 hits the server earlier. That is reconnaissance; the exploitation comes from the other agent.
The MOVEit database dump keeps its own request log. Check the log table schema first, then pull the rows where the Guest user posted a message with the Ruby agent from Q3. The InstID on those rows identifies the attacker’s session.
sed -n '/CREATE TABLE `log`/,/;/p' moveit.sql
grep -i 'msg_post' moveit.sql | grep -i 'ruby'
An .asp shell does nothing on a server that only runs ASPX handlers, which is why this one failed. Parse the $MFT and look for the moveit.asp entry in the web root. Defender event 1116 also flags the same file, which confirms it was a real detection and not a stray name.
MFTECmd -f '$MFT' --csv work/mft --csvf mft.csv
grep -i 'moveit.asp,' work/mft/mft.csv
Parse the event logs and filter the CSV for Security 4724, an attempt to reset an account’s password, targeting moveitsvc.
EvtxECmd -d <Triage evtx dir> --csv work/evtx
python3 -I -c "import csv,sys; [print(r['TimeCreated'],r['EventId'],r['PayloadData1']) for r in csv.DictReader(open('work/evtx/all.csv')) if r['EventId']=='4724']"
Tip: The answer format is
DD/MM/YYYY; EvtxECmd prints ISO dates, so reorder the date before submitting.
A reset through net user leaves the command line in memory. Run strings on the .vmem in both ASCII and UTF-16LE (-el) and grep for the account name. The command line shows the new password in clear text.
strings -el <image>.vmem | grep -i 'net user'
Gotcha: An ASCII-only pass over the image misses Windows command lines stored as UTF-16. Run both encodings.
The PSReadLine history for the account used on the host shows a download into C:\MOVEitTransfer\wwwroot, and the $MFT has the same filename created in that directory.
cat <Triage>/Users/*/AppData/Roaming/Microsoft/Windows/PowerShell/PSReadLine/ConsoleHost_history.txt
grep -ri 'move.aspx' work/mft/mft.csv
From Q1 we know the filename. The $MFT creation timestamp for the file in the web root is the moment it landed on disk.
grep -i 'move.aspx' work/mft/mft.csv | cut -d, -f1-12
Filter the IIS log for requests to the shell from Q1. The attacker POSTs to it from a Firefox on Linux agent, which differs from the Ruby exploit agent in Q3.
grep 'move.aspx' u_ex230712.log | grep POST
Tip: The answer mask uses
+for spaces, exactly as IIS writes it. Copy the field as it appears in the log.
The shell’s HTML is still in memory. Grep the image for <title> tags and pick the one that belongs to the webshell, not to a MOVEit page.
grep -a -o '<title>[^<]*</title>' <image>.vmem | sort | uniq -c | sort -rn
The PSReadLine history from Q1 holds the exact line: a PowerShell wget alias pulling the shell from a web server on the attacker’s address and writing it into the web root.
grep -i 'wget' ConsoleHost_history.txt
Terminal Services Remote Connection Manager event 1149 and Security 4624 with LogonType 10 both record a remote interactive logon from the attacker address in Q2. Logon type 10 is RemoteInteractive, which is RDP.
python3 -I -c "import csv; [print(r['TimeCreated'],r['EventId'],r['RemoteHost']) for r in csv.DictReader(open('work/evtx/all.csv')) if r['EventId'] in ('1149','4624','21')]"
Three events describe the same logon at slightly different moments: the RDP connection event 1149 at 11:11:16, the Security 4624 logon type 10 at 11:11:18, and the session-logon event 21 at 11:11:19. The 4624 is the authentication record and is the one that matched. It follows the password reset from Q7 by under two minutes.
python3 -I -c "import csv; [print(r['TimeCreated'],r['EventId']) for r in csv.DictReader(open('work/evtx/all.csv')) if r['EventId']=='4624' and 'LogonType: 10' in r['PayloadData2']]"
Gotcha: The 1149 and 21 events bracket the logon by a few seconds. Use the Security 4624 time.
| Phase | Action |
|---|---|
| Reconnaissance | Nmap scripting engine scans the MOVEit web server |
| Initial Access | Ruby-based exploit hits guestaccess.aspx and moveitisapi with the MOVEit SQL injection |
| Persistence | A classic ASP webshell is dropped and fails to run |
| Persistence | Password of the moveitsvc service account is reset |
| Lateral Movement | Attacker logs in over RDP from the same address |
| Command and Control | PowerShell wget pulls the ASPX webshell into the web root |
| Persistence | Webshell is driven with a Firefox user agent |
| Timestamp (UTC) | Event |
|---|---|
| 2023-07-12 10:11 | Nmap scripting engine requests in the IIS log |
| 2023-07-12 11:09:27 | moveitsvc password reset (Security 4724) |
| 2023-07-12 11:11:16 | RDP connection event 1149 from the attacker |
| 2023-07-12 11:11:18 | Logon type 10 recorded (Security 4624) |
| 2023-07-12 11:11:19 | Terminal Services session logon event 21 |
| 2023-07-12 11:24:30 | move.aspx created in the MOVEit web root |
| Type | Value |
|---|---|
| IP | 10.255.254[.]3 |
| URL | hxxp[://]10[.]255[.]254[.]3:9001/move.aspx |
| File (working webshell) | move.aspx |
| File (failed webshell) | moveit.asp (1362 bytes) |
| User agent (exploit) | Ruby |
| User agent (webshell) | Mozilla/5.0+(X11;+Linux+x86_64;+rv:102.0)+Gecko/20100101+Firefox/102.0 |
| Account | moveitsvc (password reset) |
| Webshell title | awen asp.net webshell |
| Technique | ID | Description |
|---|---|---|
| Active Scanning: Vulnerability Scanning | T1595.002 | Nmap scripting engine against the MOVEit server |
| Exploit Public-Facing Application | T1190 | MOVEit Transfer SQL injection, CVE-2023-34362 |
| Server Software Component: Web Shell | T1505.003 | moveit.asp and move.aspx in the web root |
| Ingress Tool Transfer | T1105 | PowerShell wget of the shell from the attacker’s web server |
| Account Manipulation | T1098 | Service account password reset with net user |
| Remote Services: Remote Desktop Protocol | T1021.001 | RDP logon from the attacker address |
Patch internet-facing MOVEit as an emergency change. The exploit arrived through the unauthenticated guestaccess.aspx and moveitisapi paths, so the only reliable control is the vendor patch. The Ruby user agent in the IIS log is a cheap interim alert for those two paths.
Scanner user agents are free early warning. The Nmap scripting engine announced itself in the IIS log an hour before the password reset. Alerting on scanner strings against the web tier would have given a head start.
Watch the web root for new script files. Both webshells were written into wwwroot, and Defender flagged the ASP one (event 1116). File creation of .asp or .aspx by anything but the deployment process should alert, and the working shell was only caught later by hand.
Service account resets and RDP from new sources are high-signal. A 4724 on moveitsvc followed within two minutes by a type 10 logon from the scanning address is a clear chain. Restrict RDP to a management network and alert on service-account password changes outside change windows.
Memory and PSReadLine keep what the logs drop. The new password and the shell’s HTML title only survived in the memory image, and the download command in PowerShell history. Collect both during triage.
The attacker went from scan to exploit to an RDP session and a working ASPX webshell in about 75 minutes, and the only thing that stopped the first webshell was that it was the wrong script type. The evidence was spread across five sources, so a defender needs web, authentication and endpoint logs together to see the whole chain.