LetsDefend: ICS FuelStation — finding the attack in the packet capture
This week I tackled ICS FuelStation. One tool, three Wireshark filters, and an incident response report at the end. Here is exactly how I worked through it.
Weekly challenge solved!
This week I tackled ICS FuelStation on the LetsDefend platform. Industrial control systems, one packet capture, and a question: what actually happened here?
Tools used
- Wireshark — that was the whole toolkit for this one.
Filters used
tcp.flags.syn == 1
tcp.flags.ack == 1
tcp.port == [enter number]Three filters. That is genuinely it. Let me explain why those three, and why in that order — because the order is the actual lesson here.
Why ICS traffic is a good place to start
Industrial control networks are wonderfully boring.
A fuel station's control network does roughly the same thing all day, every day. Which means anything unusual has nowhere to hide — as long as you know how to ask the capture the right question.
Step 1: who was knocking?
My instinct with a big capture used to be to scroll it. Don't do that. Filter it.
tcp.flags.syn == 1This shows every connection attempt. If one host is working its way across a range of ports, that is a scan — and the ports it walks tell you what the attacker was hoping to find before they found anything.
Step 2: what answered?
tcp.flags.ack == 1This shows the traffic that got a response.
The gap between those two filters is where the story lives. Hundreds of SYNs and only a handful of ACKs means most of that scan hit closed ports — and the small set that came back is where they actually got in.
Step 3: follow the one that matters
tcp.port == [enter number]Once a port stands out, pivot straight to it. Now the scan noise is gone and you are looking only at the conversation that mattered. Follow the stream and read what was exchanged.
The mistake I nearly made
It is very tempting to skip to step 3 as soon as you have a hunch.
I nearly did. Don't.
Filtering by flags first means the capture tells you which port is interesting. Going straight to a port means you confirm your hunch and miss the second, quieter connection somewhere else — and finding one thing and stopping is the most common way a real incident ends up under-scoped.
Then I wrote it up
Solving it is only half the job. The last thing I did was put together an incident response report covering:
- The artefacts I found — hosts, ports, timestamps, and where in the capture each one came from. Somebody else should be able to reproduce every finding.
- The threat actor's steps, in order — reconnaissance through to whatever they achieved. A timeline, not a pile of observations.
This is the part almost everyone skips while practising, and I think that is a mistake. Writing the report is what turns "I found the flag" into "I can explain what happened to someone who was not there". Only one of those is a job skill.
What did we learn?
- TCP flag filtering is the cheapest triage there is in Wireshark.
syn == 1finds the attempts.ack == 1finds what answered. The gap is the story.- Only pivot to
tcp.portonce the capture has told you which port matters. - ICS traffic is regular, so anomalies stand out — use that.
- Write the report. Every time.
That three-step pattern will orient you in an unfamiliar capture in about a minute, and it works well beyond ICS.
Keep practising!
References
- LetsDefend — where this challenge lives
- Wireshark TCP filter reference — every TCP field you can filter on