在 PHP Web 应用程序中防止 JavaScript 注入

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3295291/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-25 00:46:26  来源:igfitidea点击:

Preventing JavaScript Injections in a PHP Web Application

phpjavascriptjavascript-injection

提问by Alerty

What are the measures needed to prevent or to stop JavaScript injections from happening in a PHP Web application so that sensitive information is not given out (best-practices in PHP, HTML/XHTML and JavaScript)?

需要采取哪些措施来防止或阻止在 PHP Web 应用程序中发生 JavaScript 注入,以便不泄露敏感信息(PHP、HTML/XHTML 和 JavaScript 中的最佳实践)?

采纳答案by Jeffrey Blake

A good first step is applying the methods listed in the question Gert G linked. This covers in detail the variety of functions that can be used in different situations to cleanse input, including mysql_real_escape_string, htmlentities(), htmlspecialchars(), strip_tags()and addslashes()

良好的第一步是应用问题 Gert G links 中列出的方法。此盖详细,可以在不同的情况下被用来净化输入,包括各种功能mysql_real_escape_stringhtmlentities()htmlspecialchars()strip_tags()addslashes()

A better way, whenever possible, is to avoid inserting user input directly into your database. Employ whitelist input validation: in any situation where you only have a limited range of options, choose from hard-coded values for for insertion, rather than taking the input from any client-side facing form. Basically, this means having only certain values that you accept, instead of trying to eliminate/counter evil/mal-formed/malicious input.

在可能的情况下,更好的方法是避免将用户输入直接插入到数据库中。使用白名单输入验证:在任何选项范围有限的情况下,从硬编码值中进行选择以进行插入,而不是从任何面向客户端的表单中获取输入。基本上,这意味着只有您接受的某些值,而不是试图消除/反击邪恶/格式错误/恶意输入。

For example: If you have a form with a drop down for items, do not take use the input from this dropdown for insertion. Remember that a malicious client can edit the information sent with the form's submission, even if you think they only have limited options. Instead, have the drop down refer to an index in an array in your server-side code. Then use that array to choose what to insert. This way, even if an attacker tries to send you malicious code, it never actually hits your database.

例如:如果您有一个带有项目下拉列表的表单,请不要使用此下拉列表中的输入进行插入。请记住,恶意客户端可以编辑随表单提交发送的信息,即使您认为他们只有有限的选择。相反,让下拉列表引用服务器端代码中数组中的索引。然后使用该数组来选择要插入的内容。这样,即使攻击者试图向您发送恶意代码,它也不会真正访问您的数据库。

Obviously, this doesn't work for free-form applications like forums or blogs. For those, you have to fall back on the "first step" techniques. Still, there are a wide range of options that can be improved via whitelist input validation.

显然,这不适用于论坛或博客等自由形式的应用程序。对于那些,您必须退回到“第一步”技术。尽管如此,仍有许多选项可以通过白名单输入验证进行改进。

You can also use parameterized queries(aka prepared statements with bind variables) for your sql interactions wherever possible. This will tell your database server that all input is simply a value, so it mitigates a lot of the potential problems from injection attacks. In many situations, this can even cover free-form applications.

您还可以尽可能为您的 sql 交互使用参数化查询(又名带有绑定变量的准备好的语句)。这将告诉您的数据库服务器所有输入只是一个值,因此它可以减轻注入攻击带来的许多潜在问题。在许多情况下,这甚至可以涵盖自由形式的应用程序。

回答by Kamil Szot

Treat any value you output to html with htmlspecialchars()by default.

对待任何价值,你输出HTML用htmlspecialchars()默认

Only excuse for not using htmlspecialchars() is when you need to output to html string that itself contains html. In that case you must be sure that this string is from completely safe source. If you don't have such confidence then you must pass it through whitelist html filter that allows only for carefully limited set of tags, attributes, and attribute values. You should be especially careful about attribute values. You should never allow everything to pass as attribute value especially for attributes like src, hef, style.

不使用 htmlspecialchars() 的唯一借口是当您需要输出到本身包含 html 的 html 字符串时。在这种情况下,您必须确保该字符串来自完全安全的来源。如果您没有这样的信心,那么您必须通过白名单 html 过滤器传递它,该过滤器只允许仔细限制标签、属性和属性值的集合。您应该特别注意属性值。您永远不应该允许所有内容作为属性值传递,尤其是对于 src、hef、style 等属性。

You should know all places in your webapp where you output anything to html without using htmspeciachars(), be sure that you really need those places and be aware that despite all your confidence those places are potential vulnerabilities.

您应该了解您的 web 应用程序中不使用 htmspeciachars() 将任何内容输出到 html 的所有位置,确保您确实需要这些位置,并注意尽管您非常有信心,但这些位置是潜在的漏洞。

If you are thinking that this is too much caution: "Why do I need to htmlspecialchar() this variable that of I know it contains just integer and loose all the precious CPU cycles?"

如果您认为这太谨慎了:“为什么我需要 htmlspecialchar() 这个我知道它只包含整数并释放所有宝贵 CPU 周期的变量?”

Remember this: You don't know, you only think you know, CPU cycles are cheapest thing in the world and nearly all of them will be wasted by waiting for database or filesystem or even memory access.

记住这一点:您不知道,您只是认为自己知道,CPU 周期是世界上最便宜的东西,几乎所有的周期都将因等待数据库或文件系统甚至内存访问而浪费掉。

Also never use blacklist html filters. Youtube made that mistake and someone suddenly found out that only first <script>is removed and if you enter second one in the comment you can inject any Javascript into visitors browser.

也永远不要使用黑名单 html 过滤器。Youtube 犯了这个错误,有人突然发现只有第一个<script>被删除,如果你在评论中输入第二个,你可以将任何 Javascript 注入访问者浏览器。

Similarly to avoid SQL Injections treat with mysql_real_escape_string() all values that you glue to SQL query, or better yet use PDO Prepared statements.

类似地,为了避免 SQL 注入,使用 mysql_real_escape_string() 处理所有粘到 SQL 查询的值,或者最好使用 PDO Prepared 语句。

回答by Tim Santeford

If your not passing anything that needs to be formated as html then use:

如果您没有传递任何需要格式化为 html 的内容,请使用:

strip_tags() <- Eliminates any suspicious html

and then run the following to clean before saving to the db

然后在保存到数据库之前运行以下命令进行清理

mysql_real_escape_string() 

If your ajax is saving user entered html via a textbox or wysiwyg then look into using HTMLPurifierto strip out javascript but allow html tags.

如果您的 ajax 正在通过文本框或所见即所得保存用户输入的 html,那么请考虑使用HTMLPurifier 去除javascript 但允许使用 html 标签。

回答by vdidxho

I do not agree fully with the other answers provided so I will post my recommendations.

我不完全同意提供的其他答案,因此我将发布我的建议。

Recommended readingXSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet

推荐阅读XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet

Html Injection:Whenever displaying any user submitted content, it should be appropriately cleaned up with htmlspecialcharsor htmlentitieswhen specifying ENT_QUOTES if used inside of single quotes. I would recommend never encapsulating in single quotes and always encapsulating your attributes in double quotes (do not omit them). This applies to things such as:

Html 注入:每当显示任何用户提交的内容时,如果在单引号内使用,则在指定 ENT_QUOTES时应使用htmlspecialcharshtmlentities对其进行适当清理。我建议永远不要用单引号封装,而总是用双引号封装你的属性(不要省略它们)。这适用于以下情况:

<input value="<?php echo htmlspecialchars($var); ?>" />
<textarea><?php echo htmlspecialchars($var); ?></textarea>
<p><?php echo htmlspecialchars($var); ?></p>
<img width="<?php echo htmlspecialchars($var); ?>" />

Javascript Injection:It is best practice (but not always practical) to never echo user content into events and javascript. However, if you do there are some things that can be done to reduce the risk. Only pass integer id's. If you require something such as a type specifier, then use a whitelist and/or conditional check ahead of time before outputting. Possibly force user content to alphanumeric only when appropriate; preg_replace("/[^A-Za-z0-9]/", '', $string);but be very careful what you allow here. Only include content when it is encapsulated in quotes and note that htmlspecialchars/htmlentities does not protect you here. It will be interpreted at runtime even if it has been translated into html entities. This applies to things such as:

Javascript 注入:最佳实践(但并不总是实用)永远不要将用户内容回显到事件和 javascript 中。但是,如果您这样做,可以采取一些措施来降低风险。只传递整数 ID。如果您需要诸如类型说明符之类的东西,请在输出之前提前使用白名单和/或条件检查。可能仅在适当的时候强制用户内容为字母数字;preg_replace("/[^A-Za-z0-9]/", '', $string);但要非常小心你在这里允许的东西。仅包含封装在引号中的内容,并注意 htmlspecialchars/htmlentities 不会在此处保护您。即使它已被翻译成 html 实体,它也会在运行时被解释。这适用于以下情况:

<a href="www.stackoverlow.com/?id=<?php echo (int)$id; ?>">Click</a>
href, src, style, onClick, etc.

Do not echo any user content into other areas such as the body of script tags etc unless it has been forced to an int or some other very very limited character set (if you know what you are doing).

不要将任何用户内容回显到其他区域,例如脚本标记的正文等,除非它被强制为 int 或其他一些非常有限的字符集(如果您知道自己在做什么)。

SQL Injection:Use Prepared statements, bind user content to them, and never directly insert user content into the query. I would recommend creating a class for prepared statements with helper functions for your different basic statement types (and while on the subject, functionalize all of your database statements). If you choose not to use prepared statements then use mysql_real_escape_string()or similar (not addslashes()). Validate content when possible before storing into the database such as forcing/checking for integer data type, conditional checks on types, etc. Use proper database column types and lengths. Remember the main goal here is to prevent sql injection but you can optionally do html/javascript injection protection here as well.

SQL注入:使用Prepared statements,将用户内容绑定到它们,永远不要直接将用户内容插入到查询中。我建议为准备好的语句创建一个类,其中包含针对不同基本语句类型的辅助函数(并且在该主题上,对所有数据库语句进行功能化)。如果您选择不使用准备好的语句,则使用mysql_real_escape_string()或类似的(而不是 addlashes())。在存储到数据库之前尽可能验证内容,例如强制/检查整数数据类型、类型的条件检查等。使用正确的数据库列类型和长度。请记住,这里的主要目标是防止 sql 注入,但您也可以选择在此处进行 html/javascript 注入保护。

Other ResourcesI have done some research online in hopes to find a simple solution already publicly available. I found OWASP ESAPI but it appears quite dated. The links to the php version are broken in several places. I believe I found it here; ESAPI PHPbut again it is quite dated and not as simple as I was hoping for. You may find it useful however.

其他资源我在网上做了一些研究,希望找到一个已经公开可用的简单解决方案。我找到了 OWASP ESAPI,但它看起来很过时。php 版本的链接在几个地方被破坏了。我相信我在这里找到了它;ESAPI PHP但同样它已经过时了,不像我希望的那么简单。但是,您可能会发现它很有用。

All in all, don't ever just assume you're protected such as using htmlentities in an onClick attribute. You must use the right tool in the right location and avoid doing things in the wrong location.

总而言之,不要只是假设您受到保护,例如在 onClick 属性中使用 htmlentities。您必须在正确的位置使用正确的工具,避免在错误的位置做事。

回答by Deepak Dholiyan

This question already have some answers accepted and rated by users.

这个问题已经有一些被用户接受和评价的答案。

Instead I am also posting an answer, hope this will work fine.

相反,我也发布了一个答案,希望这能正常工作。

This is tested by me.

这是我测试的。

$value = preg_replace("/[\'\")(;|`,<>]/", "", $value); 

preg_replace() function works perfectly here.

preg_replace() 函数在这里工作得很好。