# 【juice-shop】★★★★ HTTP-Header XSS：通过 HTTP 头部进行存储型 XSS 攻击


# 【juice-shop】★★★★ HTTP-Header XSS：通过 HTTP 头部进行存储型 XSS 攻击

## 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>
使用 <code>&lt;iframe src="javascript:alert(`xss`)"&gt;</code> 代码通过 HTTP 头部进行存储型 XSS 攻击。
</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. 寻找可能显示在 HTTP 头部中的信息是这一挑战的一部分。<br>
2. 你可能需要研究一些不常见甚至专有的 HTTP 头部字段，才能找到突破点。<br>
3. 雪上加霜的是，你需要的 HTTP 头信息永远不会由应用程序自行发送。
</blockquote>

---

### HTTP 头部注入

某些应用会将 HTTP 请求头部的值存储到数据库，如果没有进行适当的验证和转义，就可能导致 XSS 攻击。

**常见容易被滥用的头部：**

| 头部 | 说明 |
|------|------|
| `X-Forwarded-For` | 代理转发的原始客户端 IP |
| `True-Client-IP` | 真实客户端 IP（某些 CDN 使用） |
| `X-Client-IP` | 客户端 IP |
| `User-Agent` | 用户代理信息 |
| `Referer` | 来源页面 |

## 步骤1：注册账户并登录

1. 访问应用首页
2. 注册一个新账户
3. 使用该账户登录

![注册和登录界面](../../../../../../public/p/juice-shop-http-header-xss通过-http-头部进行存储型-xss-攻击/assets/Pastedimage20260416141826.png)

## 步骤2：使用 Burp Suite 抓包分析

1. 打开 Burp Suite 的 Proxy 模块
2. 登录账户
3. 在 HTTP 历史记录中查找与登录相关的请求

**关键发现：** 存在一个 `/rest/saveLoginIp` 端点，用于记录用户登录时的 IP 地址。

![saveLoginIp 请求](../../../../../../public/p/juice-shop-http-header-xss通过-http-头部进行存储型-xss-攻击/assets/Pastedimage20260416142336.png)

## 步骤3：测试 X-Forwarded-For 头部

在 Burp Suite 的 Repeater 模块中：

1. 选择 `/rest/saveLoginIp` 请求
2. 添加 `X-Forwarded-For` 头部：
   ```
   X-Forwarded-For: 1.2.3.4
   ```
3. 发送请求

**结果：** 登录后查看用户资料，IP 地址没有更新。

![X-Forwarded-For 测试](../../../../../../public/p/juice-shop-http-header-xss通过-http-头部进行存储型-xss-攻击/assets/Pastedimage20260416142606.png)

![测试结果](../../../../../../public/p/juice-shop-http-header-xss通过-http-头部进行存储型-xss-攻击/assets/Pastedimage20260416142857.png)

**分析：** 应用可能不识别 `X-Forwarded-For` 头部。

### 步骤4：测试 True-Client-IP 头部

尝试使用 `True-Client-IP` 头部：

```
True-Client-IP: 1.2.3.4
```

**结果：** 登录后查看用户资料，IP 地址成功更新为 `1.2.3.4`！

![True-Client-IP 测试](../../../../../../public/p/juice-shop-http-header-xss通过-http-头部进行存储型-xss-攻击/assets/Pastedimage20260416143405.png)

![测试成功](../../../../../../public/p/juice-shop-http-header-xss通过-http-头部进行存储型-xss-攻击/assets/Pastedimage20260416143219.png)

**关键发现：** 应用正在读取 `True-Client-IP` 头部并将其存储到数据库。

### 步骤5：构造 XSS Payload

既然应用会存储 `True-Client-IP` 头部的值，我们可以注入恶意代码。

**Payload：**
```html
<iframe src="javascript:alert(`xss`)">
```

### 步骤6：执行存储型 XSS 攻击

1. **先退出账户**
2. 找到 `/rest/saveLoginIp` 请求
3. 修改 `True-Client-IP` 头部为恶意 Payload：
   ```
   True-Client-IP: <iframe src="javascript:alert(`xss`)">
   ```
4. 发送请求

![注入 XSS Payload](../../../../../../public/p/juice-shop-http-header-xss通过-http-头部进行存储型-xss-攻击/assets/Pastedimage20260416143751.png)

### 步骤7：触发 XSS 攻击

1. 重新登录账户
2. 进入用户个人资料页面
3. 查看"最后登录 IP"字段

**结果：** 浏览器执行了 iframe 中的 JavaScript 代码，弹窗显示 `xss`，挑战完成！

![XSS 弹窗](../../../../../../public/p/juice-shop-http-header-xss通过-http-头部进行存储型-xss-攻击/assets/Pastedimage20260416143813.png)

## 参考

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


