# Mother's Secret

{% embed url="<https://tryhackme.com/room/codeanalysis>" %}

The following post by 0xb0b is licensed under [CC BY 4.0<img src="https://mirrors.creativecommons.org/presskit/icons/cc.svg?ref=chooser-v1" alt="" data-size="line"><img src="https://mirrors.creativecommons.org/presskit/icons/by.svg?ref=chooser-v1" alt="" data-size="line">](http://creativecommons.org/licenses/by/4.0/?ref=chooser-v1)

## Recon

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.

<figure><img src="/files/ucPxpqBra66GVL2IhU34" alt=""><figcaption></figcaption></figure>

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.

<figure><img src="/files/tXuPA9VUVxTQKUhrXbxc" alt=""><figcaption></figcaption></figure>

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.

<figure><img src="/files/M2HxkZWEOHV6gRUiQqw0" alt=""><figcaption></figcaption></figure>

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.

<figure><img src="/files/A5bYkGG8f2f8XX8aPGsU" alt=""><figcaption><p>Alien Loader</p></figcaption></figure>

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.

<figure><img src="/files/1AkTtgP1uYDmTGHxkkpm" alt=""><figcaption><p>Pathways</p></figcaption></figure>

The role tile gives us just the role. Currently we are a `Crew Member`.

<figure><img src="/files/x16c1tkrNJrJTYskOs2A" alt=""><figcaption><p>Role</p></figcaption></figure>

And the flag tile might contain a flag value, but it is redacted.

<figure><img src="/files/uOlTMlivG7udKCoMWd8R" alt=""><figcaption><p>Flag</p></figcaption></figure>

### The Source

Looking at the source of the page, we see that a `./index.min.js` JavaScript file is loaded.

<figure><img src="/files/gbcUld4znDxj8UndAMhQ" alt=""><figcaption></figcaption></figure>

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.

<figure><img src="/files/VNO3aZgjfcxkQbZgTL10" alt=""><figcaption></figcaption></figure>

To be able to get some more information and be able to read it better, we use a JavaScript beautifier.

{% embed url="<https://beautifier.io/>" %}

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.

<figure><img src="/files/8fLZPCJsCAcIRWs7DuO1" alt=""><figcaption><p>index.min.js</p></figcaption></figure>

### The Routes

Next, we look at the routes provided by the challenge.&#x20;

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).&#x20;

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.&#x20;

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.

{% code title="routes.txt" lineNumbers="true" %}

```javascript
API ROUTES

------------------------------------------

yaml.js
------------------------------------------

import express from "express";
import yaml from "js-yaml";
import fs from "fs";
import { attachWebSocket } from "../websocket.js";

const Router = express.Router();

const isYaml = (filename) => filename.split(".").pop() === "yaml";

Router.post("/", (req, res) => {
  let file_path = req.body.file_path;
  const filePath = `./public/${file_path}`;

  if (!isYaml(filePath)) {
    res.status(500).json({
      status: "error",
      message: "Not a YAML file path.",
    });
    return;
  }

  fs.readFile(filePath, "utf8", (err, data) => {
    if (err) {
      res.status(500).json({
        status: "error",
        message: "Failed to read the file.",
      });
      return;
    }

    res.status(200).send(yaml.load(data));

    attachWebSocket().of("/yaml").emit("yaml", "YAML data has been processed.");
  });
});

export default Router;
------------------------------------------
´

Nostromo.js
------------------------------------------

import express from "express";
import fs from "fs";
// import { attachWebSocket } from "../../mothers_secret_challenge/websocket.js";
import { attachWebSocket } from "../websocket.js";
import { isYamlAuthenticate } from "./yaml.js";
let isNostromoAuthenticate = false;

const Router = express.Router();

Router.post("/nostromo", (req, res) => {
  let file_path = req.body.file_path;
  const filePath = `./public/${file_path}`;

  fs.readFile(filePath, "utf8", (err, data) => {
    if (err) {
      res.status(500).json({
        status: "error",
        message: "Science Officer Eyes Only",
      });
      return;
    }

    isNostromoAuthenticate = true
    res.status(200).send(data);

    attachWebSocket()
      .of("/nostromo")
      .emit("nostromo", "Nostromo data has been processed.");
  });
});

Router.post("/nostromo/mother", (req, res) => {
 
  let file_path = req.body.file_path;
  const filePath = `./mother/${file_path}`;

  if(!isNostromoAuthenticate || !isYamlAuthenticate){
    res.status(500).json({
      status: "Authentication failed",
      message: "Kindly visit nostromo & yaml route first.",
    });
    return 
  }

  fs.readFile(filePath, "utf8", (err, data) => {
    if (err) {
      res.status(500).json({
        status: "error",
        message: "Science Officer Eyes Only",
      });
      return;
    }

    res.status(200).send(data);

    // attachWebSocket()
    //   .of("/nostromo")
    //   .emit("nostromo", "Nostromo data has been processed.");
  );
});

export default Router;



------------------------------------------
```

{% endcode %}

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.

<figure><img src="/files/tDb3teD0k0rYrR7GC6e5" alt=""><figcaption></figcaption></figure>

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."`.&#x20;

<figure><img src="/files/cwrZ9vR1bASXGa0QR7ul" alt=""><figcaption></figcaption></figure>

We remember a hint or a question in the challenge if we can guess the secret at `/api/nostromo/mother/secret.txt`.

<figure><img src="/files/xXaASghp66gWzN9v66X1" alt=""><figcaption></figcaption></figure>

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.

<figure><img src="/files/0cDY4EGbQMXinkKrbVIZ" alt=""><figcaption></figcaption></figure>

## Emergency Command Override

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:<br>
>
> * Emergency command override is 100375. Use it when accessing *Alien Loaders*.&#x20;
> * 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`.

## Special Order Number

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`.

<figure><img src="/files/QCmQIvt1klJnUs1Jr0ZH" alt=""><figcaption></figcaption></figure>

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.

```bash
┌──(0xb0b㉿kali)-[~/Documents/tryhackme/Mother's Secret]
└─$ curl -X POST -H "Content-Type: application/json" -d '{"file_path": "test.yaml"}' http://10.10.71.12/yaml
```

Upon using `100375` as the filename, adding `.yaml` to it, (see [Recon: The Routes ](#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`.

<figure><img src="/files/pPYKJ7639TMNKQts0Nst" alt=""><figcaption></figcaption></figure>

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.

<figure><img src="/files/PRzkrUctS8FdBXwWCTde" alt=""><figcaption></figcaption></figure>

## Hidden Flag In The Nostromo Route

To retrieve the hidden flag in the nostromo route, we request the `txt` file mentioned in `100375.yaml`.

<figure><img src="/files/W0Q6ytVyuOnOZKsORgvL" alt=""><figcaption></figcaption></figure>

## Name Of The Science Officer

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.

<figure><img src="/files/7LQMPXyFxGsG6oaoWi1K" alt=""><figcaption></figcaption></figure>

## Classified Flag

As we are already authenticated as the officer, we are also able to retrieve the flag from the classified flag box.

<figure><img src="/files/Td6ZyIUtDpT97XBon1ga" alt=""><figcaption></figcaption></figure>

## Alternative Way To Science Officer's Name and Classified Flag

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](https://gchq.github.io/CyberChef/). In there, we are able to retrieve the science officer name in clear text and the flag encoded in `base64`.<br>

<figure><img src="/files/821ViiPqPvs3DbnCCHgp" alt=""><figcaption></figcaption></figure>

## Mother's Secret

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:

<figure><img src="/files/E0TF15XsP4WxheKzFrD8" alt=""><figcaption></figcaption></figure>

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`.&#x20;

<figure><img src="/files/TbjWU49Tj5CE4ZTBKz87" alt=""><figcaption></figcaption></figure>

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.

<figure><img src="/files/q2lqdcyslndLViCmsKTA" alt=""><figcaption></figcaption></figure>

We make use of the relative path to access the file mentioned in `secret.txt` and are able to retrieve the final flag.

<figure><img src="/files/oeWZGKyDfdW4iMNGhzIC" alt=""><figcaption></figcaption></figure>

## Trying To Go Further

Out of interest, we checked for users in `/etc/passwd`, and we have only `ubuntu` and `root` as users able to log in identified.&#x20;

<figure><img src="/files/QC6XsvJ3wJNWyn1dSImC" alt=""><figcaption></figcaption></figure>

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.&#x20;

<figure><img src="/files/WbxKhegT4qtxxMVKpODm" alt=""><figcaption></figcaption></figure>

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.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://0xb0b.gitbook.io/writeups/tryhackme/2023/mothers-secret.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
