// HackTheBox  ·  writeup

dOOMs Day

HackTheBox Easy tsharkgrepawkWireshark
DFIR

Scenario

In this Sherlock, players will analyze a compromised server that was targeted using the PHP2Shell exploit. The Sherlock focuses on understanding how the exploit works and exploring all the patterns observed in the web logs.

Executive Summary

A single host on the internal network attacked an Apache and PHP web server through index.php. It first flooded the server with stalled multipart uploads until every Apache worker was busy, so the exploit’s later requests all landed on one worker process. It then pushed that worker past the PHP memory limit and read heap addresses back out of an oversized session cookie. Armed with the leak, the chained exploit gave the attacker code execution, and the server opened a reverse shell to the attacker. The shell was used to search the filesystem for database files, and a worker segfault minutes later marked a further exploit attempt.

Artifacts

Timestamp note: The web logs are UTC. The pcap viewer shows UTC+11, so pcap times are eleven hours ahead of the logs. Answer in log time.

Discovery

Q1 — What version of PHP was running on the server?

Apache prints its own startup banner in error.log, and the signature includes the PHP module version. Grep for the AH00163 line near the top of the file rather than reading the 500 MB log.

grep -m1 AH00163 "evidence/dOOMs Day"/logs/error.log
Click flag to reveal 8.4.26

Initial Access

Q2 — At what exact date and time did the attacker send the first request belonging to the exploitation attempt? Provide the timestamp of the earliest anomalous request from the attacker's IP address in the web server logs.

access.log is small enough to triage first: filter out ordinary browser GETs and one source, 192.168.72.1, stands out sending POSTs to index.php at the target 192.168.72.50. error.log confirms it with the mod_dumpio request body, and the first such POST there carries the same second as access.log.

grep 192.168.72.1 "evidence/dOOMs Day"/logs/access.log | head
grep -m1 "POST /index.php" "evidence/dOOMs Day"/logs/error.log

Tip: error.log timestamps carry milliseconds. Drop them to fit the hh:mm:ss format.

Click to reveal answer 2026-10-28 08:42:52
Q3 — To occupy the worker pool, the exploit sent stalled multipart uploads. What is the value of the boundary separator used in these requests?

The mod_dumpio records in error.log show each stalled POST with its Content-Type: multipart/form-data; boundary=... header. Every one of the attacker’s pool-filling requests uses the same boundary and never sends a closing part, which is what keeps the worker waiting.

grep -o "boundary=[A-Za-z0-9]*" "evidence/dOOMs Day"/logs/error.log | sort | uniq -c
Click flag to reveal ZZZZZZZZZZ
Q4 — The exploit deliberately occupied the Apache worker pool with stalled multipart uploads, forcing the exploit's requests to land on the same single worker so that memory is leaked from the same process heap. How many workers did the exploit deliberately occupy?

From Q3 we know the boundary value. Count the dumpio requests carrying it: each one holds a worker. Apache confirms the pool was full with an AH00161 MaxRequestWorkers warning at 08:43:02, right after the last stalled request.

grep -c "boundary=ZZZZZZZZZZ" "evidence/dOOMs Day"/logs/error.log
grep AH00161 "evidence/dOOMs Day"/logs/error.log
Click to reveal answer 149
Q5 — Which two CVEs are chained together to achieve remote code execution?

Reference knowledge, not log evidence. The exploit behaviour in the logs (worker exhaustion, out-of-memory, heap leak through a cookie) matches the Red Hat security bulletin RHSB-2026-013 (https://access.redhat.com/security/vulnerabilities/RHSB-2026-013), which names the two chained CVEs. The answer is in ascending order.

Click flag to reveal CVE-2026-109618, CVE-2026-109619

Execution

Q6 — The exploit used the Out of Memory (OOM) primitive during exploitation. What was the PHP memory limit, in bytes, that the exploit exhausted to trigger the out-of-memory vulnerability?

PHP logs a fatal error when a script exceeds memory_limit. Search error.log for the exhausted-memory message; it states the limit in bytes.

grep -m1 "Allowed memory size" "evidence/dOOMs Day"/logs/error.log
Click to reveal answer 134217728
Q7 — The exploit leaks heap memory from the server to retrieve a heap address value, which is then used to facilitate the remote code execution process. What is the name of the cookie through which this leaked data is delivered to the attacker?

Look at the server’s responses to the attacker in the pcap, after the OOM. One response sets a cookie whose value is a long run of padding bytes followed by raw pointer bytes: those are the leaked heap addresses. Follow that TCP stream (the attacker’s client port is 49339) and read the Set-Cookie header.

tshark -r Capture.pcap -Y "http.set_cookie" -T fields -e frame.number -e tcp.stream -e http.set_cookie
Click flag to reveal PHPSESSID
Q8 — What is the size of this leaked cookie according to the logs?

The question says logs, so use the mod_dumpio output side in error.log, not the pcap or access.log. The dumpio_out entry for the leak response (client port 49339) logs the write of the Set-Cookie header with its byte count.

grep dumpio_out "evidence/dOOMs Day"/logs/error.log | grep "49339" | grep -i "set-cookie"

Gotcha: Three other sizes are close and all wrong: the access.log response byte count, the URL-decoded cookie length, and the encoded value length measured from the pcap. Only the mod_dumpio byte count for the Set-Cookie write counts.

Click to reveal answer 773518
Q9 — When did the attacker achieve remote code execution capability?

The first outbound connection from the web server to the attacker is the point where the payload ran. In the pcap the server sends a SYN to 192.168.72.1 on port 4444 at 08:43:02, the same second the worker pool filled. This ties execution to the end of the heap-leak sequence from Q7 and Q8.

tshark -r Capture.pcap -Y "ip.src==192.168.72.50 && tcp.flags.syn==1 && tcp.flags.ack==0 && ip.dst==192.168.72.1" -t ud

Gotcha: The pcap viewer is UTC+11, so the raw frame time reads 19:43:02. Convert to log time (UTC).

Click flag to reveal 2026-10-28 08:43:02

Command and Control

Q10 — What port was used for the remote code execution shell?

The SYN from Q9 shows the destination port. Following that stream (stream 810) shows an interactive shell talking to the attacker on 4444.

tshark -r Capture.pcap -q -z follow,tcp,ascii,810
Click to reveal answer 4444

Execution (post-exploitation)

Q11 — When did the exploit cause a second crash of an Apache worker process?

Worker crashes are logged by Apache as AH00052 child segfaults. There are two: the first at 08:46:16, the second at 08:47:42. The later one is the answer.

grep AH00052 "evidence/dOOMs Day"/logs/error.log
Click flag to reveal 2026-10-28 08:47:42

Discovery (post-exploitation)

Q12 — What is the command executed to find database files on the compromised server?

Follow the reverse shell stream on port 4444 from Q10. The attacker types a find across the whole filesystem for common SQLite and database extensions, discarding errors.

tshark -r Capture.pcap -q -z follow,tcp,ascii,810
Click to reveal answer find / -type f \( -name "*.sqlite" -o -name "*.sqlite3" -o -name "*.db" -o -name "*.db3" -o -name "*.s3db" -o -name "*.sl3" \) 2>/dev/null

Attack Summary

PhaseAction
Initial AccessAttacker at 192.168.72.1 starts POSTing to index.php on the target
Impact149 stalled multipart uploads fill the Apache worker pool
ExecutionA memory-exhausting request pushes a worker past the 128 MB PHP limit
ExecutionHeap pointers leak back to the attacker in an oversized PHPSESSID cookie
ExecutionThe chained CVEs give code execution; the server calls back to the attacker
Command and ControlReverse shell on port 4444
ImpactA worker segfaults again as the exploit continues
Discoveryfind across the filesystem for database files

IOCs

TypeValue
Attacker IP192.168.72[.]1
Target192.168.72[.]50 (Apache 2.4.69, PHP 8.4.26)
Multipart boundaryZZZZZZZZZZ
Reverse shell port4444
CVEsCVE-2026-109618, CVE-2026-109619

MITRE ATT&CK

TechniqueIDDescription
Exploit Public-Facing ApplicationT1190Chained PHP CVEs against index.php
Endpoint Denial of Service: OS Exhaustion FloodT1499.001Stalled uploads fill the Apache worker pool
Command and Scripting Interpreter: Unix ShellT1059.004Shell commands run through the reverse shell
Non-Application Layer ProtocolT1095Raw TCP shell on port 4444
File and Directory DiscoveryT1083find for database files

Defender Takeaways

Alert on worker-pool exhaustion. An AH00161 MaxRequestWorkers warning with no matching traffic spike means requests are being held open. Alert on it and on many incomplete multipart POSTs from one source, which is the setup step of this exploit.

Treat PHP out-of-memory fatals as security events. Allowed memory size exhausted followed by an oversized Set-Cookie is not normal application noise. Forward both to the SIEM and correlate them with the source IP.

Repeated child segfaults are exploitation, not instability. Two AH00052 crashes minutes apart on a web worker deserve an incident, not a restart. Patch the two chained CVEs from the vendor bulletin.

Block web servers from initiating outbound connections. The server opened a TCP session to an arbitrary host on 4444. Egress filtering on the web tier would have cut the shell off even after code execution.

Be careful with mod_dumpio in production. It made this investigation possible, but it also writes request and response bodies, cookies included, to a 500 MB log. Use it for incident capture, and protect the log.

Conclusion

The attacker turned a PHP memory-handling flaw pair into a working shell by controlling which worker handled the exploit, then used it to look for databases. The server’s own logs recorded every stage; the signal was in the worker-pool and memory warnings that preceded the shell.