目录
非持久性 XSS
持久性 XSS
数据验证
数据清理
输出转义
跨站脚本 (XSS) 攻击对 PHP 应用程序的影响是什么?
如何在我的 PHP 应用程序中识别潜在的 XSS 漏洞?
XSS 攻击中使用的一些常见方法是什么?
如何在我的 PHP 应用程序中防止 XSS 攻击?
内容安全策略在防止 XSS 攻击中起什么作用?
存储型 XSS 攻击和反射型 XSS 攻击有什么区别?
如何使用 PHP 的内置函数来防止 XSS 攻击?
HTTPOnly Cookie 在防止 XSS 攻击中起什么作用?
XSS 攻击可以用来绕过 CSRF 保护吗?
有哪些 PHP 框架提供针对 XSS 攻击的内置保护?
首页 后端开发 php教程 跨站点脚本攻击(XSS)

跨站点脚本攻击(XSS)

Feb 27, 2025 am 09:12 AM

Cross-Site Scripting Attacks (XSS)

关键要点

  • 跨站脚本攻击(XSS)是一种常见的代码注入攻击,由于用户数据验证不当(通常通过网络表单插入或操纵超链接)而发生。这可能允许有害的客户端代码保存在服务器上或在用户的浏览器中执行。
  • XSS 攻击可分为两种类型:非持久性 XSS(恶意代码通过服务器传递并呈现给受害者)和持久性 XSS(有害代码绕过验证并存储在网站的数据存储中,在信息显示在网站上时执行)。
  • 防止 XSS 攻击需要永远不要信任来自用户或第三方来源的数据,在输入时验证所有数据,并在输出时对其进行转义。这包括实施数据验证、数据清理和输出转义措施。
  • 尽管许多 PHP 框架提供了内置的安全措施,但使用最新的 XSS 测试向量持续测试验证代码以确保代码仍然不受 XSS 攻击的影响至关重要。

跨站脚本攻击是互联网上每天发生的五大安全攻击之一,您的 PHP 脚本也可能无法幸免。这种攻击也称为 XSS,它基本上是一种代码注入攻击,由于用户数据验证不正确而成为可能,这些数据通常通过 Web 表单或使用更改后的超链接插入到页面中。注入的代码可以是任何恶意的客户端代码,例如 JavaScript、VBScript、HTML、CSS、Flash 等。该代码用于在服务器上保存有害数据或在用户的浏览器中执行恶意操作。不幸的是,跨站脚本攻击主要发生是因为开发人员未能提供安全的代码。每个 PHP 程序员都有责任了解如何对他们的 PHP 脚本进行攻击以利用可能的安全漏洞。阅读本文,您将了解有关跨站脚本攻击的更多信息以及如何在您的代码中防止它们。

通过示例学习

让我们来看下面的代码片段。

<form action="post.php" method="post">
  <input type="text" name="comment" value="">
  <input type="submit" name="submit" value="Submit">
</form>
登录后复制
登录后复制
登录后复制

这里我们有一个简单的表单,其中有一个文本框用于数据输入和一个提交按钮。提交表单后,它将提交数据到 post.php 进行处理。假设 post.php 只输出数据,如下所示:

<?php echo $_POST["comment"]; ?>
登录后复制
登录后复制
登录后复制

没有任何过滤,黑客可以通过表单提交以下内容,这将在浏览器中生成一个带有消息“hacked”的弹出窗口。

alert("hacked")
登录后复制
登录后复制
登录后复制

这个例子,尽管本质上是恶意的,但似乎并没有造成太大危害。但是,想想如果 JavaScript 代码被编写为窃取用户的 cookie 并从中提取敏感信息会发生什么?有比简单的 alert() 调用更糟糕的 XSS 攻击。

跨站脚本攻击可以分为两大类,基于它们传递恶意有效负载的方式:非持久性 XSS 和持久性 XSS。请允许我详细讨论每种类型。

非持久性 XSS

也称为反射型 XSS 攻击,这意味着恶意代码实际上并未存储在服务器上,而是通过服务器传递并呈现给受害者,这是两种传递方法中更流行的 XSS 策略。攻击是从外部来源发起的,例如电子邮件或第三方网站。这是一个简单的搜索结果脚本的一部分示例:

<form action="post.php" method="post">
  <input type="text" name="comment" value="">
  <input type="submit" name="submit" value="Submit">
</form>
登录后复制
登录后复制
登录后复制

此示例可能是一个非常不安全的成果页面,其中搜索查询会显示回用户。这里的问题是,$_GET["query"] 变量未经验证或转义,因此攻击者可以向受害者发送以下链接:

<?php echo $_POST["comment"]; ?>
登录后复制
登录后复制
登录后复制

无需验证,页面将包含:

alert("hacked")
登录后复制
登录后复制
登录后复制

持久性 XSS

当恶意代码已经通过验证过程并存储在数据存储中时,就会发生这种类型的攻击。这可能是评论、日志文件、通知消息或网站上任何其他需要用户输入的部分。稍后,当此特定信息显示在网站上时,恶意代码就会执行。让我们使用以下示例来创建一个基本的基于文件的评论系统。假设我前面介绍的相同表单,假设接收脚本只是将评论附加到数据文件。

<?php // 根据查询获取搜索结果
echo "You searched for: " . $_GET["query"];

// 列出搜索结果
...
登录后复制
登录后复制

在其他地方,comments.txt 的内容显示给访问者:

http://example.com/search.php?query=alert(&quot;hacked&quot;)
登录后复制
登录后复制

当用户提交评论时,它会被保存到数据文件中。然后,整个文件(因此是整个评论系列)将显示给读者。如果提交了恶意代码,则它将被保存并按原样显示,没有任何验证或转义。

防止跨站脚本攻击

幸运的是,与对不受保护的网站进行 XSS 攻击一样容易,防止它们也同样容易。但是,即使在编写一行代码之前,预防也必须始终铭记在心。任何 Web 环境(无论是开发、暂存还是生产)都需要“强制执行”的第一条规则是永远不要信任来自用户或任何其他第三方来源的数据。这怎么强调都不为过。必须验证每一位数据输入,并在输出时进行转义。这是防止 XSS 的黄金法则。为了实施防止 XSS 攻击的可靠安全措施,我们应该注意数据验证、数据清理和输出转义。

数据验证

数据验证是确保应用程序使用正确数据运行的过程。如果您的 PHP 脚本期望用户输入整数,则任何其他类型的数据都将被丢弃。接收到的每条用户数据都必须经过验证,以确保其类型正确,如果未通过验证过程,则将其丢弃。例如,如果您想验证电话号码,您将丢弃包含字母的任何字符串,因为电话号码应仅包含数字。您还应考虑字符串的长度。如果您想更宽松一些,您可以允许有限的一组特殊字符,例如加号、括号和破折号,这些字符通常用于格式化特定于您目标区域设置的电话号码。

<form action="post.php" method="post">
  <input type="text" name="comment" value="">
  <input type="submit" name="submit" value="Submit">
</form>
登录后复制
登录后复制
登录后复制

数据清理

数据清理侧重于操作数据以确保其安全,方法是从数据中删除任何不需要的位并将其规范化为正确的形式。例如,如果您期望纯文本字符串作为用户输入,您可能希望从中删除任何 HTML 标记。

<?php echo $_POST["comment"]; ?>
登录后复制
登录后复制
登录后复制

有时,数据验证和清理/规范化可以同时进行。

alert("hacked")
登录后复制
登录后复制
登录后复制

输出转义

为了保护显示/输出数据的完整性,您应该在将数据呈现给用户时对其进行转义。这可以防止浏览器对可能找到的任何特殊字符序列应用任何意外的含义。

<?php // 根据查询获取搜索结果
echo "You searched for: " . $_GET["query"];

// 列出搜索结果
...
登录后复制
登录后复制

现在一起!

为了更好地理解数据处理的三个方面,让我们再次查看前面基于文件的评论系统,并对其进行修改以确保其安全。代码中的潜在漏洞源于这样一个事实,即 $_POST["comment"] 被盲目地附加到 comments.txt 文件中,然后直接显示给用户。为了确保其安全,应在将 $_POST["comment"] 值添加到文件之前对其进行验证和清理,并且在将文件内容显示给用户时应对其进行转义。

http://example.com/search.php?query=alert(&quot;hacked&quot;)
登录后复制
登录后复制

该脚本首先验证传入的评论,以确保用户已提供非零长度字符串。毕竟,空白评论不是很有趣。数据验证需要在一个定义良好的上下文中进行,这意味着如果我期望从用户那里获得一个整数,那么我会通过将数据转换为整数并将其作为整数处理来相应地对其进行验证。如果这导致无效数据,则只需将其丢弃并让用户知道。然后,脚本通过删除可能包含的任何 HTML 标记来清理评论。最后,检索、过滤和显示评论。通常,htmlspecialchars() 函数足以过滤打算在浏览器中查看的输出。但是,如果您在网页中使用的字符编码不是 ISO-8859-1 或 UTF-8,那么您可能需要使用 htmlentities()。有关这两个函数的更多信息,请阅读官方 PHP 文档中的各自说明。请记住,在像 Web 这样不断发展的媒介上,不存在 100% 安全的单一解决方案。使用最新的 XSS 测试向量彻底测试您的验证代码。使用以下来源的测试数据应该可以揭示您的代码是否仍然容易受到 XSS 攻击。

  • RSnake XSS cheatsheet(您可以用来测试代码的相当全面的 XSS 向量列表)
  • Zend Framework 的 XSS 测试数据
  • XSS cheatsheet(使用 HTML5 功能)

总结

希望本文对您很好地解释了跨站脚本攻击是什么以及如何防止它们发生在您的代码中。永远不要信任来自用户或任何其他第三方来源的数据。您可以通过在一个定义良好的上下文中验证传入的值、清理数据以保护您的代码以及转义输出以保护您的用户来保护自己。编写代码后,请确保您的工作正常,方法是尽可能彻底地测试代码。

(图片来自 Inge Schepers / Shutterstock)

如果喜欢这篇文章,您会喜欢 Learnable;从大师那里学习新技能和技巧的地方。会员可以立即访问所有 SitePoint 的电子书和交互式在线课程,例如 Jump Start PHP。

本文的评论已关闭。对 PHP 有疑问?为什么不在我们的论坛上提问呢?

关于 PHP 安全性和跨站脚本攻击 (XSS) 的常见问题 (FAQ)

跨站脚本 (XSS) 攻击对 PHP 应用程序的影响是什么?

跨站脚本 (XSS) 攻击会对 PHP 应用程序产生重大影响。它们可能导致数据盗窃、会话劫持、网站损毁,甚至将恶意代码分发给用户。XSS 攻击利用 Web 应用程序中的漏洞来注入恶意脚本,然后由用户的浏览器执行。这可能会危及用户与应用程序的交互,并可能泄露敏感信息。

如何在我的 PHP 应用程序中识别潜在的 XSS 漏洞?

识别 PHP 应用程序中潜在的 XSS 漏洞需要结合手动代码审查和自动化测试。查找代码中用户输入直接包含在输出中而没有适当清理或验证的区域。像 XSS 扫描器这样的自动化工具还可以通过测试各种 XSS 攻击向量来帮助识别潜在的漏洞。

XSS 攻击中使用的一些常见方法是什么?

XSS 攻击通常涉及将恶意脚本注入其他用户查看的网页。这可以通过多种方法完成,例如将脚本嵌入 URL 参数、表单输入甚至 cookie 中。然后,恶意脚本可以代表用户执行操作,例如窃取其会话 cookie 或操作网页内容。

如何在我的 PHP 应用程序中防止 XSS 攻击?

防止 PHP 应用程序中的 XSS 攻击涉及验证和清理用户输入、编码输出以及使用适当的 HTTP 标头。始终将用户输入视为不受信任,并根据可接受值的允许列表对其进行验证。清理输入以删除任何可能存在危害的字符或代码。编码输出以确保任何可能存在危害的字符都变得无害。使用 HTTP 标头(如内容安全策略)来限制脚本和其他资源的来源。

内容安全策略在防止 XSS 攻击中起什么作用?

内容安全策略 (CSP) HTTP 标头在防止 XSS 攻击中起着至关重要的作用。它允许您指定浏览器应认为是可执行脚本有效来源的域。这意味着,即使攻击者可以将脚本注入您的网页,浏览器也不会运行它,除非脚本的来源在您的 CSP 中列入白名单。

存储型 XSS 攻击和反射型 XSS 攻击有什么区别?

存储型 XSS 攻击涉及注入永久存储在目标服务器上的恶意脚本。然后,当用户查看某些页面时,脚本就会提供给用户。另一方面,反射型 XSS 攻击涉及通过 URL 或表单输入注入脚本,然后服务器立即在响应中返回该脚本并由用户的浏览器执行。

如何使用 PHP 的内置函数来防止 XSS 攻击?

PHP 提供了一些内置函数,可以帮助防止 XSS 攻击。例如,htmlspecialchars() 函数可用于编码用户输入中的特殊字符,从而使潜在的脚本无害。filter_input() 函数可用于清理用户输入,删除或编码有害字符。

HTTPOnly Cookie 是一种无法通过客户端脚本访问的 Cookie。这意味着,即使攻击者可以将脚本注入您的网页,他们也无法使用该脚本读取或修改 HTTPOnly Cookie。这可以帮助保护敏感信息(例如会话标识符)不被 XSS 攻击窃取。

XSS 攻击可以用来绕过 CSRF 保护吗?

是的,XSS 攻击可能会用来绕过跨站点请求伪造 (CSRF) 保护。如果攻击者可以将脚本注入您的网页,他们可以使用该脚本代表用户执行操作,从而可能绕过您已实施的任何 CSRF 保护。这就是为什么保护免受 XSS 和 CSRF 攻击都很重要的原因。

有哪些 PHP 框架提供针对 XSS 攻击的内置保护?

是的,许多 PHP 框架都提供针对 XSS 攻击的内置保护。例如,Laravel 会自动编码输出以防止 XSS 攻击。其他框架(如 Symfony 和 CodeIgniter)也提供用于清理用户输入和编码输出的功能。但是,必须记住,没有哪个框架可以提供完全的保护,您仍然应该遵循防止 XSS 攻击的最佳实践。

以上是跨站点脚本攻击(XSS)的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

在PHP API中说明JSON Web令牌(JWT)及其用例。 在PHP API中说明JSON Web令牌(JWT)及其用例。 Apr 05, 2025 am 12:04 AM

JWT是一种基于JSON的开放标准,用于在各方之间安全地传输信息,主要用于身份验证和信息交换。1.JWT由Header、Payload和Signature三部分组成。2.JWT的工作原理包括生成JWT、验证JWT和解析Payload三个步骤。3.在PHP中使用JWT进行身份验证时,可以生成和验证JWT,并在高级用法中包含用户角色和权限信息。4.常见错误包括签名验证失败、令牌过期和Payload过大,调试技巧包括使用调试工具和日志记录。5.性能优化和最佳实践包括使用合适的签名算法、合理设置有效期、

会话如何劫持工作,如何在PHP中减轻它? 会话如何劫持工作,如何在PHP中减轻它? Apr 06, 2025 am 12:02 AM

会话劫持可以通过以下步骤实现:1.获取会话ID,2.使用会话ID,3.保持会话活跃。在PHP中防范会话劫持的方法包括:1.使用session_regenerate_id()函数重新生成会话ID,2.通过数据库存储会话数据,3.确保所有会话数据通过HTTPS传输。

描述扎实的原则及其如何应用于PHP的开发。 描述扎实的原则及其如何应用于PHP的开发。 Apr 03, 2025 am 12:04 AM

SOLID原则在PHP开发中的应用包括:1.单一职责原则(SRP):每个类只负责一个功能。2.开闭原则(OCP):通过扩展而非修改实现变化。3.里氏替换原则(LSP):子类可替换基类而不影响程序正确性。4.接口隔离原则(ISP):使用细粒度接口避免依赖不使用的方法。5.依赖倒置原则(DIP):高低层次模块都依赖于抽象,通过依赖注入实现。

在PHPStorm中如何进行CLI模式的调试? 在PHPStorm中如何进行CLI模式的调试? Apr 01, 2025 pm 02:57 PM

在PHPStorm中如何进行CLI模式的调试?在使用PHPStorm进行开发时,有时我们需要在命令行界面(CLI)模式下调试PHP�...

如何在系统重启后自动设置unixsocket的权限? 如何在系统重启后自动设置unixsocket的权限? Mar 31, 2025 pm 11:54 PM

如何在系统重启后自动设置unixsocket的权限每次系统重启后,我们都需要执行以下命令来修改unixsocket的权限:sudo...

解释PHP中的晚期静态绑定(静态::)。 解释PHP中的晚期静态绑定(静态::)。 Apr 03, 2025 am 12:04 AM

静态绑定(static::)在PHP中实现晚期静态绑定(LSB),允许在静态上下文中引用调用类而非定义类。1)解析过程在运行时进行,2)在继承关系中向上查找调用类,3)可能带来性能开销。

如何用PHP的cURL库发送包含JSON数据的POST请求? 如何用PHP的cURL库发送包含JSON数据的POST请求? Apr 01, 2025 pm 03:12 PM

使用PHP的cURL库发送JSON数据在PHP开发中,经常需要与外部API进行交互,其中一种常见的方式是使用cURL库发送POST�...

See all articles