> For the complete documentation index, see [llms.txt](https://web-sec.gitbook.io/wsa/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://web-sec.gitbook.io/wsa/client-side/cross-site-scripting/index.md).

# 跨站脚本

在本节中，我们将讲解什么是跨站脚本，描述不同类型的跨站脚本漏洞，并阐明如何发现和防范跨站脚本。

## 什么是跨站脚本（XSS）？

跨站脚本（又称为XSS）是一种Web安全漏洞，允许攻击者破坏用户与易受攻击的应用程序的交互。它允许攻击者绕过同源策略，而同源策略旨在将不同的网站彼此隔离。跨站脚本漏洞通常允许攻击者伪装成受害用户，执行用户能够执行的任何操作，并访问用户的任何数据。如果受害用户在应用程序中具有高权限访问权限，那么攻击者或许能够完全控制应用程序的所有功能和数据。

## XSS的工作原理

跨站脚本攻击的工作原理是操纵易受攻击的网站，使其返回恶意JavaScript代码给用户。当恶意代码在受害者的浏览器中执行时，攻击者就可以完全破坏他们与应用程序的交互。

![](/files/VDbyPsXc8fp2Y2qWmzak)

> **Labs**
>
> 如果你已经熟悉XSS漏洞背后的基本概念，并且只想在一些真实的、故意易受攻击的目标上练习利用它们，你可以从下面的链接访问本主题中的所有实验。
>
> * [查看所有XSS实验](https://portswigger.net/web-security/all-labs#cross-site-scripting)

## XSS概念验证

你可以通过注入一个使你自己的浏览器执行某些JavaScript的有效载荷来确认大多数类型的XSS漏洞。长期以来，使用`alert()`函数来实现这个目的一直是常见的做法，因为它简短、无害，成功调用时不容易忽视。事实上，你解决我们大多数XSS实验的方法就是在模拟受害者的浏览器中调用`alert()`。

不幸的是，如果你使用Chrome，会有一个小问题。从92版本开始（2021年7月20日），跨域的iframe被阻止调用`alert()`。由于它被用于构造一些更高级的XSS攻击，因此有时你需要使用一个替代的PoC有效载荷。在这种情况下，我们推荐使用`print()`函数。如果你对这个变化以及我们为什么喜欢`print()`感兴趣，可以查看我们关于该主题的[博客文章](https://portswigger.net/research/alert-is-dead-long-live-print)。

由于实验中的模拟受害者使用的是Chrome，因此我们已经修改了受影响的实验，以便它们也可以使用`print()`来解决。在相关的说明中我们已经指明了这一点。

## XSS攻击有哪些类型？

主要有三种类型的XSS攻击。这些是：

* 反射型XSS，恶意脚本来自当前的HTTP请求。
* 存储型XSS，恶意脚本来自网站的数据库。
* 基于DOM的XSS，漏洞存在于客户端代码而不是服务器端代码。

## 反射型跨站脚本

反射型XSS是最简单的跨站脚本。当应用程序接收HTTP请求中的数据，并以不安全的方式将该数据包含在紧接着的响应中时，就会出现反射型XSS。

以下是一个反射型XSS漏洞的简单示例：

```html
https://insecure-website.com/status?message=All+is+well.
<p>Status: All is well.</p>
```

应用程序不会对数据进行任何其他处理，因此攻击者可以轻松构造如下攻击：

```html
https://insecure-website.com/status?message=<script>/*+Bad+stuff+here...+*/</script>
<p>Status: <script>/* Bad stuff here... */</script></p>
```

如果用户访问攻击者构造的URL，那么攻击者的脚本就会在用户的浏览器中，在该用户与应用程序的会话环境中执行。此时，该脚本可以执行任何操作，并获取用户能访问的任何数据。

> **阅读更多**
>
> * [反射型跨站脚本](/wsa/client-side/cross-site-scripting/reflected.md)
> * [跨站脚本速查表](/wsa/client-side/cross-site-scripting/cheat-sheet.md)

## 存储型跨站脚本

存储型XSS（又称为持久型或二阶XSS）发生在当应用程序从不可信的来源接收数据，并以不安全的方式将这些数据包含在其后续的HTTP响应中时。

涉及的数据可能是通过HTTP请求提交给应用程序的，例如，博客文章上的评论、聊天室中的用户昵称或客户订单上的联系详情。在其他情况下，数据可能来自其他不可信的来源，例如，显示通过SMTP收到的信息的邮箱应用程序、显示社交媒体帖子的营销应用程序或显示网络流量数据包的网络监控应用程序。

以下是一个存储型XSS漏洞的简单示例。一个留言板应用程序让用户提交信息，这些信息会显示给其他用户：

```html
<p>Hello, this is my message!</p>
```

应用程序不会对数据进行任何其他处理，因此攻击者可以轻松发送攻击其他用户的信息：

```html
<p><script>/* Bad stuff here... */</script></p>
```

> **阅读更多**
>
> * [存储型跨站脚本](/wsa/client-side/cross-site-scripting/stored.md)
> * [跨站脚本速查表](/wsa/client-side/cross-site-scripting/cheat-sheet.md)

## 基于DOM的跨站脚本

基于DOM的XSS（又称为DOM型XSS）出现在当应用程序包含一些客户端JavaScript，而这些JavaScript以不安全的方式处理来自不可信源的数据，通常是将数据写回到DOM。

在如下示例中，应用程序使用一些JavaScript从输入字段读取值，并将该值写入一个HTML元素中：

```javascript
var search = document.getElementById('search').value;
var results = document.getElementById('results');
results.innerHTML = 'You searched for: ' + search;
```

如果攻击者可以控制输入字段的值，他们就可以轻松构造一个恶意值，从而执行他们的脚本：

```html
You searched for: <img src=1 onerror='/* Bad stuff here... */'>
```

在一个典型的案例中，输入字段会由HTTP请求的某部分（如URL查询字符串参数）填充，这样便允许攻击者使用恶意URL传递攻击，方式与反射型XSS一样。

> **阅读更多**
>
> * [基于DOM的跨站脚本](/wsa/client-side/cross-site-scripting/dom-based.md)

## XSS可以用来做什么？

利用跨站脚本漏洞的攻击者通常能够：

* 冒充或伪装成受害用户。
* 执行用户能执行的任何操作。
* 读取用户可以访问的任何数据。
* 获取用户的登录凭证。
* 对网站进行虚拟篡改。
* 在网站中注入木马功能。

## XSS漏洞的影响

XSS攻击的实际影响通常取决于应用程序的性质、功能和数据，以及被攻击的用户的状态。例如：

* 在宣传册式应用程序中，所有用户都是匿名的，所有信息都是公开的，影响往往会很小。
* 在包含敏感数据的应用程序中，例如银行交易、电子邮件或医疗记录，影响通常会很严重。
* 如果被攻击的用户在应用程序中具有提升权限，那么通常会造成严重影响，攻击者可以完全控制易受攻击的应用程序，并攻击所有用户及其数据。

> **阅读更多**
>
> * [利用跨站脚本漏洞](/wsa/client-side/cross-site-scripting/exploiting.md)

## 如何发现和测试XSS漏洞

使用Burp Suite的Web漏洞扫描器可以快速可靠地发现绝大多数XSS漏洞。

手动测试反射型和存储型XSS通常涉及向应用程序中的每个入口点提交一些简单独特的输入（如一串简短的字母数字字符串），找到在HTTP响应中返回已提交输入的每一个位置，并对每个位置进行单独测试，以确定是否可以使用适当制作的输入来执行任意JavaScript。通过这种方式，你可以确定发生XSS的上下文，并选择合适的有效载荷加以利用。

手动测试因URL参数导致的DOM型XSS涉及一个类似这样的过程：在参数中放置一些简单独特的输入，使用浏览器的开发者工具在DOM中搜索该输入，并测试每一个位置，以确定其是否可以被利用。不过，其他类型的DOM XSS更难检测。在不是基于URL输入（如`document.cookie`）或不是基于HTML的Sink（如`setTimeout`）中发现基于DOM的漏洞，没有比审查JavaScript代码更好的替代方案，而审查JavaScript代码可能非常耗时。Burp Suite的Web漏洞扫描器结合了JavaScript的静态和动态分析，能够可靠地自动化检测基于DOM的漏洞。

> **阅读更多**
>
> [跨站脚本上下文](/wsa/client-side/cross-site-scripting/contexts/client-side-template-injection.md)

## 内容安全策略

内容安全策略（CSP）是一种浏览器机制，旨在降低跨站脚本和其他一些漏洞的影响。如果采用CSP的应用程序包含类似XSS的行为，那么CSP可能会干扰或阻止漏洞的利用。通常，可以规避CSP以启用对底层漏洞的利用。

> **阅读更多**
>
> * [内容安全策略](/wsa/client-side/cross-site-scripting/content-security-policy.md)

## 悬空标记注入

悬空标记注入是一种用于在，由于输入过滤或其他防御措施而无法实现完整的跨站脚本利用的情况下跨域捕获数据的技术。这种技术通常可以被利用来捕获其他用户可见的敏感信息，包括可用于代表用户执行未授权操作的CSRF令牌。

> **阅读更多**
>
> * [悬空标记注入](/wsa/client-side/cross-site-scripting/dangling-markup.md)

## 如何防范XSS攻击

在某些情况下，防范跨站脚本是非常简单的，但根据应用程序的复杂性以及它处理用户可控数据的方式，情况可能会变得更加复杂。

一般而言，有效防止XSS漏洞可能需要结合以下措施：

* **在输入到达时进行过滤。** 在接收用户输入时，根据预期或有效的输入尽可能严格地进行过滤。
* **在数据输出时进行编码。** 在HTTP响应中输出用户可控数据时，对输出进行编码以防止其被解释为活动内容。根据输出上下文，这可能需要应用HTML、URL、JavaScript和CSS编码的组合。
* **使用适当的响应标头。** 为了防止在不打算包含任何HTML或JavaScript的HTTP响应中XSS，你可以使用`Content-Type`和`X-Content-Type-Options`标头来确保浏览器按照你的意图解释响应。
* **内容安全策略。** 作为最后一道防线，你可以使用内容安全策略（CSP）来降低任何仍然发生的XSS漏洞的严重性。

> **阅读更多**
>
> * [如何防范XSS](/wsa/client-side/cross-site-scripting/preventing.md)
> * [使用Burp Suite的Web漏洞扫描器发现XSS漏洞](https://portswigger.net/burp/vulnerability-scanner)

## 有关跨站脚本的常见问题

**XSS漏洞有多常见？** XSS漏洞非常常见，XSS可能是最常出现的Web安全漏洞。

**XSS攻击有多常见？** 很难获取关于真实世界XSS攻击的可靠数据，但它被利用的频率可能低于其他漏洞。

**XSS和CSRF的区别？** XSS涉及使网站返回恶意JavaScript，而CSRF涉及诱导受害用户执行他们并不打算执行的操作。

**XSS和SQL注入的区别？** XSS是一种客户端漏洞，针对的是其他应用程序用户，而SQL注入是一种服务器端漏洞，针对的是应用程序的数据库。

**如何在PHP中预防XSS？** 使用允许字符的白名单过滤输入，并使用类型提示或类型转换。在HTML上下文中使用`htmlentities`和`ENT_QUOTES`对输出进行转义，或在JavaScript上下文中使用JavaScript Unicode转义。

**如何在Java中预防XSS？** 使用允许字符的白名单过滤输入，在HTML上下文中使用诸如Google Guava之类的库对输出进行HTML编码，或在JavaScript上下文中使用JavaScript Unicode转义。


---

# 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:

```
GET https://web-sec.gitbook.io/wsa/client-side/cross-site-scripting/index.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
