Mother's Secret
Exploit flaws found in Mother's code to reveal its secrets. - by melmols
Last updated
Exploit flaws found in Mother's code to reveal its secrets. - by melmols
Last updated
The following post by 0xb0b is licensed under CC BY 4.0
Even though the room description states that there is only a web server running on port 80, we hit up Nmap and scanned our target machine. We have two open ports: an HTTP server running on port 80 and an SSH server running on port 22.
Next, we run Gobuster to enumerate some directories; on the first try, we get an error; to overcome this, we exclude the length of 42, but did not find anything of interest.
To check out what's happening, we visit a custom route. We get the status :"You just hit the wrong route."
. Ok, let's head to the index of the page.
We are presented in a menu-like window with the status above about crew membership. We can navigate through the tiles using our UP and DOWN keys. The first tile states something about an Alien Loader. A YAML loader to parse and load YAML data. This loader holds the truth to unveil the hidden paths - Ok.
The second tile gives us some big hints for later use. That there are secrets beyond the intended boundaries and that those might be reachable using relative file paths.
The role tile gives us just the role. Currently we are a Crew Member
.
And the flag tile might contain a flag value, but it is redacted.
Looking at the source of the page, we see that a ./index.min.js
JavaScript file is loaded.
By trying to investigate it, we see it is minified (as the name states) and also obfuscated using non-readable function names and renaming those in variables.
To be able to get some more information and be able to read it better, we use a JavaScript beautifier.
Here, we can see that there are several functions. Some authentication takes place in yamlSocket
. We get the path /yaml
at line 34 for the YAML socket. The data is being modified depending on the values of authNostormo and authYaml. Those variables are preset to false using the statement ![]
and set by the sockets. Line 96 holds a bunch of HTML code. Beginning at line 102, key navigation is implemented.
Next, we look at the routes provided by the challenge.
In routes.txt
, there are three functions defined on how to respond to HTTP POST requests on the root path "/"
(in the yaml.js section, beginning at line 17), the /nostromo
path, and the /nostromo/mother
path in the Nostromo.js
section (at lines 60 and 82).
In the yaml.js
section, there is an isYaml
function defined that takes a filename as a parameter and checks whether the given filename has a .yaml
extension. If so, it returns true.
To reach a successful response on the path "/"
root, a filename in the request body has to be provided in the variable file_path
, which is a file ending with .yaml
, and be present in the directory of the machine at ./public
. If we are able to provide this file, it gets loaded and sent. By providing the wrong file, we should get the response "Not a YAML file path."
.
To reach a successful response on the /nostromo
path, there has to be a filename provided that is present in the ./public
folder of the machine, but this time it does not have to be a .yaml
file. Upon successful response, the variable isNostromoAuthenticate
is set to true, and the data from the provided file is loaded and sent. By providing the wrong file, we should get the response "Science Officer Eyes Only"
.
To reach a successful response on the /nostromo/mother
path, there has to be a filename provided that is present in ./mother
of the machine, and the variables isNostromoAuthenticate
and isYamlAuthenticate
set to true. It gives the hint to visit the nostromo and yaml routes first to set those variables to true. The variable isYamlAuthenticate
is imported from yaml.js
. By providing the wrong file, we should get the response "Science Officer Eyes Only"
.
The input for of file_path
does not get sanitized in any of the request handlers. This may result in a path traversal vulnerability and allow us to read arbitrary files on the system.
The route /yaml
was found by analyzing index.min.js
. It is the root path. We craft a simple POST request to check if that path is correct, and we get the response "Not a YAML file path."
. We are on the right track.
While we are at it, we try to check for the nostromo path; unfortunately, with our first guess of just hitting on /nostromo
we get the status "You just hit the wrong route."
.
We remember a hint or a question in the challenge if we can guess the secret at /api/nostromo/mother/secret.txt
.
We use the route /api/nostromo
and get the status message "Science Officer Eyes Only"
. Next, we try to check for /api/nostromo/mother
and get the hint to visit both routes mentioned before. So, we are on the right track, we have the correct path, but we are missing out on the correct or existing filenames we have to provide. That we have to pass filenames, we know from the analysis of the routes file.
We head to the first question and have to provide the number of the emergency command override. In the room description, there is an operation manual in which the number is directly mentioned. The manual states we have to use it when accessing the Alien Loaders.
Below are some sequences and operations to get you started. Use the following to unlock information and navigate Mother:
Emergency command override is 100375. Use it when accessing Alien Loaders.
Download the task files to learn about Mother's routes.
Hitting the routes in the right order makes Mother confused, it might think you are a Science Officer!
It is 100375
.
So, we have the order number and know that we have to use it on the Alien Loaders aka YAML Loader. This file might be located at ./public.
We hit up cURL and made a POST request on /yaml
.
To provide a file, we use the -d
tag. The file does not have to be in our directory. First, we test with an example file. If it is not present, we get the same error.
Upon using 100375
as the filename, adding .yaml
to it, (see Recon: The Routes ) we are able to retrieve some information. The orders are stored in a txt
file, and a rerouting to /api/nostromo
takes place, a hint to guide us to /api/nostromo
.
We get the same results when providing the route /api/nostromo
. Both are accessing the file from ./public
. The name of the txt
file contains the special order number.
To retrieve the hidden flag in the nostromo route, we request the txt
file mentioned in 100375.yaml
.
Now, that we have visited the /yaml
and /nostromo
paths with a successful response, the authentication values are set. Next, we just call modifyData()
in the console to load the data as the authenticated user, and we are able to retrieve the name of the science officer in the role tile. It is not necessary to set the parameters; just calling modifyData()
reveals the information.
As we are already authenticated as the officer, we are also able to retrieve the flag from the classified flag box.
Another way to retrieve the science officer's name and the classified flag is to analyze the source code further. We just have to look at the contents of the variable _0x491022
at line 96. By replacing the encoded spaces \x20
in hex with spaces, it is easier to read. For this we are using cyberchef. In there, we are able to retrieve the science officer name in clear text and the flag encoded in base64
.
Now, we just have to get the Mother's Secret. The room description challenges us to guess the mother's secret and provides us an api path we already know from our discoveries before:
We just try to access this secret mentioned in the room description, maybe it leads us to more information. And we get a hit, the secret.txt
contains the location of the mother's secret. It is in a location not in ./public
or ./mother
.
Recalling the Pathways tile from the page and the missing sanitization in the request handlers of the provided routes file, we should be able to get beyond this boundary using relative paths.
We make use of the relative path to access the file mentioned in secret.txt
and are able to retrieve the final flag.
Out of interest, we checked for users in /etc/passwd
, and we have only ubuntu
and root
as users able to log in identified.
We were able to access the /etc/shadow
file, but we see that the accounts are disabled for logging in and no passwords are present.
We were also able to identify two public keys, stored in ./.ssh/authorized_keys of
each user's home directory.
But trying to access the corresponding private keys on, for example, /root/.ssh/id_rsa
or /home/ubuntu/.ssh/id_rsa
unfortunately fails.