在 PHP 站点中避免 xss 攻击的最佳实践是什么
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/71328/
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
What are the best practices for avoiding xss attacks in a PHP site
提问by Rik Heywood
I have PHP configured so that magic quotes are on and register globals are off.
我已经配置了 PHP,以便打开魔术引号并关闭注册全局变量。
I do my best to always call htmlentities() for anything I am outputing that is derived from user input.
对于我输出的任何源自用户输入的内容,我都会尽我最大的努力始终调用 htmlentities()。
I also occasionally seach my database for common things used in xss attached such as...
我也偶尔会在我的数据库中搜索附加的 xss 中使用的常用内容,例如...
<script
What else should I be doing and how can I make sure that the things I am trying to do are alwaysdone.
我还应该做什么以及我如何确保我正在尝试做的事情总是完成。
采纳答案by Micha? Rudnicki
Escaping input is not the best you can do for successful XSS prevention. Also output must be escaped. If you use Smarty template engine, you may use |escape:'htmlall'modifier to convert all sensitive characters to HTML entities (I use own |emodifier which is alias to the above).
转义输入并不是成功预防 XSS 的最佳方法。还必须对输出进行转义。如果您使用 Smarty 模板引擎,您可以使用|escape:'htmlall'修饰符将所有敏感字符转换为 HTML 实体(我使用自己的|e修饰符,它是上述的别名)。
My approach to input/output security is:
我的输入/输出安全方法是:
- store user input not modified (no HTML escaping on input, only DB-aware escaping done via PDO prepared statements)
- escape on output, depending on what output format you use (e.g. HTML and JSON need different escaping rules)
- 存储未修改的用户输入(输入时没有 HTML 转义,仅通过 PDO 准备好的语句完成 DB-aware 转义)
- 转义输出,取决于您使用的输出格式(例如 HTML 和 JSON 需要不同的转义规则)
回答by Jilles
I'm of the opinion that one shouldn't escape anything during input, only on output. Since (most of the time) you can not assume that you know where that data is going. Example, if you have form that takes data that later on appears in an email that you send out, you need different escaping (otherwise a malicious user could rewrite your email-headers).
我认为在输入过程中不应该逃避任何事情,只能在输出中逃避。因为(大部分时间)您不能假设您知道数据的去向。例如,如果您的表单需要稍后出现在您发送的电子邮件中的数据,则需要不同的转义(否则恶意用户可能会重写您的电子邮件标题)。
In other words, you can only escape at the very last moment the data is "leaving" your application:
换句话说,您只能在数据“离开”您的应用程序的最后时刻逃脱:
- List item
- Write to XML file, escape for XML
- Write to DB, escape (for that particular DBMS)
- Write email, escape for emails
- etc
- 项目清单
- 写入 XML 文件,转义为 XML
- 写入数据库,转义(对于那个特定的 DBMS)
- 写电子邮件,逃避电子邮件
- 等等
To go short:
做空:
- You don't know where your data is going
- Data might actually end up in more than one place, needing different escaping mechanism's BUT NOT BOTH
- Data escaped for the wrong target is really not nice. (E.g. get an email with the subject "Go to Tommy\'s bar".)
- 你不知道你的数据去哪里
- 数据实际上可能会出现在不止一个地方,需要不同的转义机制,但不能同时存在
- 为错误的目标转义的数据真的不好。(例如,收到一封主题为“去汤米酒吧”的电子邮件。)
Esp #3 will occur if you escape data at the input layer (or you need to de-escape it again, etc).
如果您在输入层转义数据(或者您需要再次对其进行转义等),则会发生 Esp #3。
PS: I'll second the advice for not using magic_quotes, those are pure evil!
PS:我会支持不使用magic_quotes的建议,那些是纯粹的邪恶!
回答by Christian Studer
There are a lot of ways to do XSS (See http://ha.ckers.org/xss.html) and it's very hard to catch.
有很多方法可以进行 XSS(参见http://ha.ckers.org/xss.html),而且很难捕捉。
I personally delegate this to the current framework I'm using (Code Igniter for example). While not perfect, it might catch more than my hand made routines ever do.
我个人将此委托给我正在使用的当前框架(例如 Code Igniter)。虽然不完美,但它可能比我手工制作的例程更能吸引人。
回答by Matt Farina
This is a great question.
这是一个很好的问题。
First, don't escape text on input except to make it safe for storage (such as being put into a database). The reason for this is you want to keep what was input so you can contextually present it in different ways and places. Making changes here can compromise your later presentation.
首先,不要对输入的文本进行转义,除非是为了安全存储(例如放入数据库)。这样做的原因是您希望保留输入的内容,以便您可以在不同的方式和位置以上下文方式呈现它。在此处进行更改可能会影响您以后的演示。
When you go to present your data filter out what shouldn't be there. For example, if there isn't a reason for javascript to be there search for it and remove it. An easy way to do that is to use the strip_tagsfunction and only present the html tags you are allowing.
当你去展示你的数据时,过滤掉不应该存在的东西。例如,如果 javascript 没有理由在那里搜索并删除它。一个简单的方法是使用strip_tags函数并只显示您允许的 html 标签。
Next, take what you have and pass it thought htmlentities or htmlspecialchars to change what's there to ascii characters. Do this based on context and what you want to get out.
接下来,获取您拥有的内容并将其传递给 htmlentities 或 htmlspecialchars 以将那里的内容更改为 ascii 字符。根据上下文和您想得到的内容执行此操作。
I'd, also, suggest turning off Magic Quotes. It is has been removed from PHP 6 and is considered bad practice to use it. Details at http://us3.php.net/magic_quotes
我也建议关闭 Magic Quotes。它已从 PHP 6 中删除,使用它被认为是不好的做法。详情见http://us3.php.net/magic_quotes
For more details check out http://ha.ckers.org/xss.html
有关更多详细信息,请查看http://ha.ckers.org/xss.html
This isn't a complete answer but, hopefully enough to help you get started.
这不是一个完整的答案,但希望足以帮助您入门。
回答by Mason
rikh Writes:
I do my best to always call htmlentities() for anything I am outputing that is derived from user input.
里克写道:
对于我输出的任何源自用户输入的内容,我都会尽我最大的努力始终调用 htmlentities()。
See Joel's essay on Making Code Look Wrongfor help with this
请参阅乔尔关于使代码看起来错误的文章以寻求帮助
回答by Kornel
I rely on PHPTALfor that.
我依赖PHPTAL。
Unlike Smarty and plain PHP, it escapes all output by default. This is a big win for security, because your site won't become vurnelable if you forget htmlspecialchars()or |escapesomewhere.
与 Smarty 和普通 PHP 不同,它默认转义所有输出。这是安全方面的一大胜利,因为如果您忘记htmlspecialchars()或在|escape某个地方,您的网站不会变得易受攻击。
XSS is HTML-specific attack, so HTML output is the right place to prevent it. You should not try pre-filtering data in the database, because you could need to output data to another medium which doesn't accept HTML, but has its own risks.
XSS 是特定于 HTML 的攻击,因此 HTML 输出是防止它的正确位置。您不应该尝试预先过滤数据库中的数据,因为您可能需要将数据输出到另一种不接受 HTML 但有其自身风险的媒体。
回答by user319490
Template library.Or at least, that is what template libraries should do. To prevent XSS alloutput should be encoded. This is not the task of the main application / control logic, it should solely be handled by the output methods.
模板库。或者至少,这是模板库应该做的。为了防止 XSS,所有输出都应该被编码。这不是主要应用程序/控制逻辑的任务,它应该完全由输出方法处理。
If you sprinkle htmlentities() thorughout your code, the overall design is wrong. And as you suggest, you might miss one or two spots. That's why the only solution is rigorous html encoding -> whenoutput vars get written into a html/xml stream.
如果您在整个代码中使用 htmlentities(),则整体设计是错误的。正如您所建议的,您可能会错过一两个景点。这就是为什么唯一的解决方案是严格的 html 编码-> 当输出变量被写入 html/xml 流时。
Unfortunately, most php template libraries only add their own template syntax, but don't concern themselves with output encoding, or localization, or html validation, or anything important. Maybe someone else knows a proper template library for php?
不幸的是,大多数 php 模板库只添加自己的模板语法,而不关心输出编码、本地化、html 验证或任何重要的事情。也许其他人知道一个合适的 php 模板库?
回答by barce
I find that using this function helps to strip out a lot of possible xss attacks: http://www.codebelay.com/killxss.phps
我发现使用这个功能有助于剔除很多可能的 xss 攻击:http: //www.codebelay.com/killxss.phps
回答by Alexey Feldgendler
“Magic quotes” is a palliative remedy for some of the worst XSS flaws which works by escaping everything on input, something that's wrong by design. The only case where one would want to use it is when you absolutely must use an existing PHP application known to be written carelessly with regard to XSS. (In this case you're in a serious trouble even with “magic quotes”.) When developing your own application, you should disable “magic quotes” and follow XSS-safe practices instead.
“魔术引号”是对一些最严重的 XSS 缺陷的一种姑息疗法,它通过转义输入的所有内容来工作,这是设计错误的。唯一想要使用它的情况是,您绝对必须使用现有的 PHP 应用程序,该应用程序已知针对 XSS 编写的粗心大意。(在这种情况下,即使使用“魔术引号”,您也会遇到严重的麻烦。)在开发您自己的应用程序时,您应该禁用“魔术引号”并遵循 XSS 安全实践。
XSS, a cross-site scripting vulnerability, occurs when an application includes strings from external sources (user input, fetched from other websites, etc) in its [X]HTML, CSS, ECMAscript or other browser-parsed output without proper escaping, hoping that special characters like less-than (in [X]HTML), single or double quotes (ECMAscript) will never appear. The proper solution to it is to always escape strings according to the rules of the output language: using entities in [X]HTML, backslashes in ECMAscript etc.
XSS 是一种跨站点脚本漏洞,当应用程序在其 [X]HTML、CSS、ECMAscript 或其他浏览器解析的输出中包含来自外部来源(用户输入、从其他网站获取等)的字符串而没有适当转义时,就会发生这种情况,希望诸如小于(在 [X]HTML 中)、单引号或双引号 (ECMAscript) 之类的特殊字符将永远不会出现。正确的解决方案是始终根据输出语言的规则对字符串进行转义:在 [X]HTML 中使用实体,在 ECMAscript 中使用反斜杠等。
Because it can be hard to keep track of what is untrusted and has to be escaped, it's a good idea to always escape everything that is a “text string” as opposed to “text with markup” in a language like HTML. Some programming environments make it easier by introducing several incompatible string types: “string” (normal text), “HTML string” (HTML markup) and so on. That way, a direct implicit conversion from “string” to “HTML string” would be impossible, and the only way a string could become HTML markup is by passing it through an escaping function.
因为跟踪不可信和必须转义的内容可能很困难,所以最好总是转义所有“文本字符串”而不是像 HTML 这样的语言中的“带有标记的文本”。一些编程环境通过引入几种不兼容的字符串类型来简化它:“字符串”(普通文本)、“HTML 字符串”(HTML 标记)等。那样的话,从“字符串”到“HTML 字符串”的直接隐式转换将是不可能的,并且字符串可以成为 HTML 标记的唯一方法是通过转义函数传递它。
“Register globals”, though disabling it is definitely a good idea, deals with a problem entirely different from XSS.
“注册全局变量”虽然禁用它绝对是一个好主意,但它处理的问题与 XSS 完全不同。
回答by Niyaz
If you are concerned about XSS attacks, encoding your output strings to HTML is the solution. If you remember to encode every single output character to HTML format, there is no way to execute a successful XSS attack.
如果您担心 XSS 攻击,将输出字符串编码为 HTML 是解决方案。如果您记得将每个输出字符编码为 HTML 格式,则无法执行成功的 XSS 攻击。
Read more: Sanitizing user data: How and where to do it
阅读更多: 清理用户数据:如何以及在何处执行此操作

