Post

TryHackMe — Snort Challenge - The Basics

TryHackMe — Snort Challenge - The Basics

Practical follow-up to the Snort Room in the SOC Level 1 path. Instead of reading about concepts, this room is about writing actual rules and testing them against PCAP files. Eight tasks covering different scenarios — from basic ICMP rules through FTP analysis to Log4Shell exploitation traffic.

FieldDetails
PlatformTryHackMe
Room/MachineSnort Challenge - The Basics
DifficultyMedium
Tagssnort, ids, rule-writing, ftp, pcap, log4j, eternalblue

Task 2 — Simple Rules

The starting point: writing ICMP rules and running them against a PCAP. The basic structure was familiar from the Snort room:

1
alert icmp any any -> any any (msg:"ICMP Packet Found"; sid:1000001; rev:1;)

What turned out to be less straightforward: getting useful output. Snort doesn’t print alerts to stdout by default — they go into a log file. The approach that worked: run Snort with -A full -l . to generate an alert file, then read that file directly:

1
grep -a "FTP login" alert | wc -l

grep on the alert file returns the number of matched alerts

This became the standard pattern for the rest of the room.


Task 3 — FTP

Bidirectional Rules and Port Placement

My first attempt used any 21 <> any 21 — which seemed logical for FTP traffic. That rule produced no alerts. A bidirectional rule written that way only matches packets where both endpoints use port 21, which doesn’t happen in practice. The correct approach:

1
alert tcp any any <> any 21 (...)

This matches both directions — client requests going to port 21 and server responses coming from port 21.

Content Filters for Login Scenarios

1
2
3
4
5
6
7
8
9
10
11
# Failed login (530 User)
alert tcp any 21 -> any any (msg:"Failed FTP login detected!"; flow:established,from_server; content:"530 User"; sid:100002; rev:1;)

# Successful login (230 User)
alert tcp any 21 -> any any (msg:"Successful FTP login detected!"; flow:established,from_server; content:"230 User"; sid:100003; rev:1;)

# No password provided (331 Password)
alert tcp any 21 -> any any (msg:"Failed FTP login detected! No password provided."; flow:established,from_server; content:"331 Password"; sid:100004; rev:1;)

# Admin login without password
alert tcp any 21 -> any any (msg:"Failed FTP ADMIN login detected! No password provided."; flow:established,from_server; content:"331 Password"; content:"Administrator"; sid:100005; rev:1;)

local.rules for Task 3 showing FTP rules


Task 4 — PNG and GIF

My first approach was to filter by file extension — looking for .png or .gif in the traffic. That produced nothing useful.

Magic Bytes as a Reliable Signature

FormatMagic Bytes (Hex)
PNG89 50 4E 47
GIF47 49 46 38
1
2
alert tcp any any <> any any (msg:"Found PNG file."; content:"|89 50 4E 47|"; sid:100001; rev:1;)
alert tcp any any <> any any (msg:"Found GIF file."; content:"|47 49 46 38|"; sid:100002; rev:1;)

local.rules for Task 4 with magic byte rules

Alert output showing detected GIF files


Task 5 — Torrent Metafiles

1
alert tcp any any <> any any (msg:"Torrent file detected!"; content:".torrent"; nocase; sid:100001; rev:1;)

Running Snort with -vde made the full payload readable — the MIME type application/x-bittorrent and client name were both visible.

Snort verbose output showing torrent payload


Task 6 — Rule Debugging

Most common issues:

  • : instead of ; as the option separator
  • Missing msg option
  • Duplicate sid values
  • <- doesn’t exist — only -> and <>
1
2
3
4
5
# Broken — missing source port field
alert icmp any -> any any (msg: "Troubleshooting 2"; sid:1000001; rev:1;)

# Fixed
alert icmp any any -> any any (msg:"Troubleshooting 2"; sid:1000001; rev:1;)

Broken rule — missing source port field

Fixed rule with complete syntax


Task 7 — EternalBlue (MS17-010)

CVE-2017-0144, CVSS v2: 9.3.

1
sudo snort -c ./local.rules -r ms-17-010.pcap -vde -A full -l .

Filtering for IPC$ — Escape Sequence Problem

A single \ in a content string throws bad escape sequence. Fix:

1
content:"\\IPC$";

Reading the first ten packets from the generated log:

1
sudo snort -r snort.log.1772573153 -vde -n 10

Task 8 — Log4Shell (CVE-2021-44228)

CVE-2021-44228, CVSS v2: 9.3.

Packet Size Rule

1
alert tcp any any <> any any (msg:"Matching packet size.(770<>855)"; dsize:770<>855; sid:1000001; rev:1;)

dsize rule resulting in 41 alerts

Finding the Encoding Algorithm

The early packets were full of % characters — I assumed percent-encoding. Wrong. Further into the payload, Base64 appeared as plain text inside the attack string.

Hex dump of Log4Shell payload

Base64 visible in the Snort log payload


Tools Used

ToolPurpose
SnortRule engine — PCAP analysis, alert generation
grep + wc -lParsing alert files
CyberChefBase64 decoding
NVDCVSS scores for CVE-2017-0144 and CVE-2021-44228

Lessons Learned

Port placement matters in bidirectional rules. any 21 <> any 21 matches nothing useful. The monitored port goes on the right side only: any any <> any 21.

File extensions are unreliable as detection signatures. Magic bytes are more reliable — the first bytes identify a file’s format regardless of its name.

Snort output doesn’t pipe the way I expected. Run with -A full -l . and work with the generated files.

Double backslash for a literal backslash in content strings. \\IPC$ is the correct syntax.

Read more of the payload before guessing. Base64 only appeared further down in the Task 8 payload — committing to percent-encoding based on the first visible characters cost a wrong attempt.

Defensive Takeaways

This room is focused on detection, so the “what would have prevented this?” question sits one layer above the Snort rules themselves. The two vulnerabilities covered — EternalBlue and Log4Shell — have very different prevention stories.

EternalBlue (MS17-010): patch, then segment. Microsoft released MS17-010 in March 2017, over a month before WannaCry. Organisations that were hit had simply not patched. The first line of defence here is patch management — applying security updates promptly, especially for critical vulnerabilities. Beyond patching, network segmentation limits lateral movement: SMB (port 445) should not be reachable from untrusted network segments, and firewall rules should restrict it to hosts that actually need it.

Log4Shell (CVE-2021-44228): update the library, validate input. The vulnerability exists in Log4j’s JNDI lookup feature, which resolves attacker-controlled URLs from log messages. The immediate fix was updating to a patched version of Log4j. The deeper fix is input validation: user-controlled data that ends up in log messages should be sanitised before logging, which would have made the injection string harmless even on an unpatched system. Disabling JNDI lookups entirely (log4j2.formatMsgNoLookups=true) was the recommended workaround before the patch was available.

Snort as a detection layer, not a prevention layer. Writing a Snort rule that catches EternalBlue or Log4Shell traffic is useful — it surfaces active exploitation attempts. But detection alone is not sufficient if the underlying vulnerability is present and unpatched. The rule catches the attack happening; patching prevents it from succeeding.


References

This post is licensed under CC BY 4.0 by the author.