跨站脚本攻击 xss_跨站脚本攻击(XSS)

跨站脚本攻击 xss

A cross-site scripting attack is one of the top 5 security attacks carried out on a daily basis across the Internet, and your PHP scripts may not be immune.

跨站点脚本攻击是每天在Internet上进行的前五项安全攻击之一,您PHP脚本可能无法幸免。

Also known as XSS, the attack is basically a type of code injection attack which is made possible by incorrectly validating user data, which usually gets inserted into the page through a web form or using an altered hyperlink. The code injected can be any malicious client-side code, such as JavaScript, VBScript, HTML, CSS, Flash, and others. The code is used to save harmful data on the server or perform a malicious action within the user’s browser.

也称为XSS,这种攻击基本上是一种代码注入攻击,它是通过不正确地验证用户数据(通常是通过Web表单或使用更改的超链接插入到页面中)来实现的。 注入的代码可以是任何恶意的客户端代码,例如JavaScript,VBScript,HTML,CSS,Flash等。 该代码用于将有害数据保存在服务器上或在用户的浏览器中执行恶意操作。

Unfortunately, cross-site scripting attacks occurs mostly, because developers are failing to deliver secure code. Every PHP programmer has the responsibility to understand how attacks can be carried out against their PHP scripts to exploit possible security vulnerabilities. Reading this article, you’ll find out more about cross-site scripting attacks and how to prevent them in your code.

不幸的是,跨站点脚本攻击主要发生在开发人员无法交付安全代码的情况下。 每个PHP程序员都有责任了解如何对他们PHP脚本进行攻击以利用可能的安全漏洞。 阅读本文,您将了解有关跨站点脚本攻击以及​​如何在代码中防止它们的更多信息。

实例学习 (Learning by Example)

Let’s take the following code snippet.

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

<form action="post.php" method="post">
 <input type="text" name="comment" value="">
 <input type="submit" name="submit" value="Submit">
</form>

Here we have a simple form in which there is a text box for data input and a submit button. Once the form is submitted, it will submit the data to post.php for processing. Let’s say all post.php does is output the data like so:

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

<?php
echo $_POST["comment"];

Without any filtering, a hacker could submit the following through the form which will generates a popup in the browser with the message “hacked”.

黑客无需进行任何过滤,就可以通过该表单提交以下内容,该表单将在浏览器中生成一个弹出窗口,并显示消息“被黑客入侵”。

<script>alert("hacked")</script>

This example, despite its being malicious in nature, does not seem to do much harm. But think about what could happen in the JavaScript code was written to steal a user’s cookie and extract sensitive information from it? There are far worse XSS attacks than a simple alert() call.

尽管此示例本质上是恶意的,但似乎并没有造成太大危害。 但是,考虑编写JavaScript代码以窃取用户Cookie并从中提取敏感信息会发生什么情况? 与简单的alert()调用相比,XSS攻击要严重得多。

Cross-site scripting attacks can be grouped in two major categories, based on how they deliver the malicious payload: non-persistent XSS, and persistent XSS. Allow me to discuss each type in detail.

根据跨站点脚本攻击如何传递恶意负载,它们可以分为两大类:非持久XSS和持久XSS。 请允许我详细讨论每种类型。

非持久XSS (Non-persistent XSS)

Also known as reflected XSS attack, meaning that the actual malicious code is not stored on the server but rather gets passed through it and presented to the victim, is the more popular XSS strategy of the two delivery methods. The attack is launched from an external source, such as from an e-mail message or a third-party website.

两种传递方法中比较流行的XSS策略也称为反射XSS攻击,这意味着实际的恶意代码未存储在服务器上,而是通过它传递并呈现给受害者。 该攻击是从外部来源发起的,例如从电子邮件或第三方网站。

Here’s an example of a portion of a simple search result script:

这是一部分简单搜索结果脚本的示例:

<?php
// Get search results based on the query
echo "You searched for: " . $_GET["query"];

// List search results
...

The example can be a very unsecure results page where the search query is displayed back to the user. The problem here is that the $_GET["query"] variable isn’t validated or escaped, therefore an attacker could send the following link to the victim:

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

http://example.com/search.php?query=<script>alert("hacked")</script>

Without validation, the page would contain:

未经验证,该页面将包含:

You searched for: <script>alert("hacked")</script>

持久XSS (Persistent XSS)

This type of attack happens when the malicious code has already slipped through the validation process and it is stored in a data store. This could be a comment, log file, notification message, or any other section on the website which required user input at one time. Later, when this particular information is presented on the website, the malicious code gets executed.

当恶意代码已经通过验证过程并且存储在数据存储中时,就会发生这种类型的攻击。 这可能是评论,日志文件,通知消息,或者网站上需要用户一次输入的任何其他部分。 稍后,当此特定信息显示在网站上时,恶意代码将被执行。

Let’s use the following example for a rudimentary file-based comment system. Assuming the same form I presented earlier, let’s say the receiving script simply appends the comment to a data file.

让我们将以下示例用于基本的基于文​​件的注释系统。 假设与我之前介绍的表单相同,则假设接收脚本只是将注释附加到数据文件中。

<?php
file_put_contents("comments.txt", $_POST["comment"], FILE_APPEND);

Elsewhere the contents of comments.txt is shown to visitors:

其他方面的内容comments.txt显示给用户:

<?php
echo file_get_contents("comments.txt");

When a user submit a comment it gets saved to the data file. Then the entire file (thus the entire series of comments) is displayed to the readership. If malicious code is submitted then it will be saved and displayed as is without any validation or escaping.

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

防止跨站点脚本攻击 (Preventing Cross-Site Scripting Attacks)

Fortunately, as easily as an XSS attack can carried out against an unprotected website, protecting against them are just as easy. Prevention must always be in your thoughts, though, even before you write a single line of code.

幸运的是,就像对不受保护的网站进行XSS攻击一样容易,针对它们进行保护同样容易。 但是,即使在编写一行代码之前,预防也必须始终在您的思想中。

The first rule which needs to be “enforced” in any web environment (be it development, staging, or production) is never trust data coming from the user or from any other third party sources. This can’t be emphasized enough. Every bit of data must be validated on input and escaped on output. This is the golden rule of preventing XSS.

在任何Web环境(开发,暂存或生产)中都需要“强制执行”的第一条规则是永远不要信任来自用户或任何其他第三方来源的数据。 这不能足够强调。 数据的每一位都必须在输入时进行验证,并在输出时进行转义。 这是防止XSS的黄金法则。

In order to implement solid security measures which prevents XSS attacks, we should be mindful of data validation, data sanitization, and output escaping.

为了实施防止XSS攻击的可靠安全措施,我们应该注意数据验证,数据清理和输出转义。

资料验证 (Data Validation)

Data validation is the process of ensuring that your application is running with correct data. If your PHP script expects an integer for user input, then any other type of data would be discarded. Every piece of user data must be validated when it is received to ensure it is of the corrected type, and discarded if it doesn’t pass the validation process.

数据验证是确保您的应用程序使用正确的数据运行的过程。 如果您PHP脚本要求用户输入一个整数,那么任何其他类型的数据都将被丢弃。 每条用户数据都必须在接收时进行验证,以确保其类型正确,如果未通过验证过程,则将其丢弃。

If you wanted to validate a phone number, for example, you would discard any strings containing letters, because a phone number should consist of digits only. You should also take the length of the string into consideration. If you wanted to be more permissive, you could allow a limited set of special characters such as plus, parenthesis, and dashes which are often used in formatting phone numbers specific to your intended locale.

例如,如果要验证电话号码,则将丢弃任何包含字母的字符串,因为电话号码应仅由数字组成。 您还应该考虑字符串的长度。 如果希望放宽手法,则可以允许使用有限的一组特殊字符,例如加号,括号和破折号,这些字符通常用于格式化特定于您的预期区域的电话号码。

<?php
// validate a US phone number
if (preg_match('/^((1-)?d{3}-)d{3}-d{4}$/', $phone)) {
    echo $phone . " is valid format.";
}

数据消毒 (Data Sanitization)

Data sanitization focuses on manipulating the data to make sure it is safe by removing any unwanted bits from the data and normalizing it to the correct form. For example, if you are expecting a plain text string as user input, you may want to remove any HTML markup from it.

数据清理的重点是通过从数据中删除任何不需要的位并将其规范化为正确的格式来操纵数据以确保数据安全。 例如,如果期望纯文本字符串作为用户输入,则可能要从中删除任何HTML标记。

<?php
// sanitize HTML from the comment
$comment = strip_tags($_POST["comment"]);

Sometimes, data validation and sanitization/normalization can go hand in hand.

有时,数据验证和消毒/规范化可以并驾齐驱。

<?php
// normalize and validate a US phone number
$phone = preg_replace('/[^d]/', "", $phone);
$len = strlen($phone);
if ($len == 7 || $len == 10 || $len == 11) {
    echo $phone . " is valid format.";
}

输出转义 (Output Escaping)

In order to protect the integrity of displayed/output data, you should escape the data when presenting it to the user. This prevents the browser from applying any unintended meaning to any special sequence of characters that may be found.

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

<?php
// escape output sent to the browser
echo "You searched for: " . htmlspecialchars($_GET["query"]);

现在都在一起了! (All Together Now!)

To better understand the three aspects of data processing, let’s take another look at the file-based comment system from earlier and modify it to make sure it’s secure. The potential vulnerabilities in the code stem from the fact that $_POST["comment"] is blindly appended to the comments.txt file which is then displayed directly to the user. To secure it, the $_POST["comment"] value should be validated and sanitized before it is added to the file, and the file’s contents should be escaped when displayed to the user.

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

<?php
// validate comment
$comment = trim($_POST["comment"]);
if (empty($comment)) {
    exit("must provide a comment");
}

// sanitize comment
$comment = strip_tags($comment);

// comment is now safe for storage
file_put_contents("comments.txt", $comment, FILE_APPEND);

// escape comments before display
$comments = file_get_contents("comments.txt");
echo htmlspecialchars($comments);

The script first validates the incoming comment to make sure a non-zero length string as been provided by the user. After all, a blank comment isn’t very interesting.

该脚本首先验证传入的注释,以确保用户提供的字符串长度不为零。 毕竟,空白评论不是很有趣。

Data validation needs to happen within a well defined context, meaning that if I expect an integer back from the user, then I validate it accordingly by converting the data into an integer and handle it as an integer. If this results in invalid data, then simply discard it and let the user know about it.

数据验证需要在定义良好的上下文中进行,这意味着如果我希望用户返回一个整数,则可以通过将数据转换为整数并将其作为整数进行处理来进行相应的验证。 如果这导致无效数据,则只需丢弃它并让用户知道。

Then the script sanitizes the comment by removing any HTML tags it may contain.

然后,脚本通过删除注释中可能包含的所有HTML标记来清除注释。

And finally, the comments are retrieved, filtered, and displayed.

最后,评论被检索,过滤和显示。

Generally the htmlspecialchars() function is sufficient for filtering output intended for viewing in a browser. If you’re using a character encoding in your web pages other than ISO-8859-1 or UTF-8, though, then you’ll want to use htmlentities(). For more information on the two functions, read their respective write-ups in the official PHP documentation.

通常, htmlspecialchars()函数足以过滤要在浏览器中查看的输出。 但是,如果您在ISO-8859-1或UTF-8之外的网页中使用字符编码,则需要使用htmlentities() 。 有关这两个函数的更多信息,请阅读官方PHP文档中它们各自的内容。

Bear in mind that no single solution exists that is 100% secure on a constantly evolving medium like the Web. Test your validation code thoroughly with the most up to date XSS test vectors. Using the test data from the following sources should reveal if your code is still prone to XSS attacks.

请记住,在像Web这样不断发展的媒体上,没有哪个解决方案可以100%安全地存在。 使用最新的XSS测试向量全面测试您的验证代码。 使用来自以下来源的测试数据应该可以揭示您的代码是否仍然容易受到XSS攻击。

摘要 (Summary)

Hopefully this article gave you a good explanation of what cross-site scripting attacks are and how you can prevent them from happening to your code. Never trust data coming from the user or from any other third party sources. You can protect yourself by validating the incoming values in a well defined context, sanitizing the data to protect your code, and escaping output to protect your users. After you’ve written your code, be sure your efforts work correctly by testing the code as thoroughly as you can.

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

Image via Inge Schepers / Shutterstock

图片来自Inge Schepers / Shutterstock

And if you enjoyed reading this post, you’ll love Learnable; the place to learn fresh skills and techniques from the masters. Members get instant access to all of SitePoint’s ebooks and interactive online courses, like Jump Start PHP.

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

Comments on this article are closed. Have a question about PHP? Why not ask it on our forums?

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

翻译自: https://www.sitepoint.com/php-security-cross-site-scripting-attacks-xss/

跨站脚本攻击 xss

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值