在PHP Web应用程序中阻止或阻止JavaScript注入所需的措施是什么,以便不提供敏感信息(PHP,HTML / XHTML和JavaScript中的最佳实践)?
答案 0 :(得分:7)
良好的第一步是应用question Gert G linked中列出的方法。这详细介绍了可在不同情况下用于清理输入的各种功能,包括mysql_real_escape_string
,htmlentities()
,htmlspecialchars()
,strip_tags()
和addslashes()
< / p>
尽可能更好的方法是避免将用户输入直接插入数据库。使用whitelist input validation:在您只有有限范围的选项的任何情况下,从插入的硬编码值中选择,而不是从任何面向客户端的表单中获取输入。基本上,这意味着只有你接受的某些值,而不是试图消除/反对邪恶/错误形成/恶意输入。
例如: 如果您有一个包含项目下拉列表的表单,请不要使用此下拉列表中的输入进行插入。请记住,恶意客户端可以编辑随表单提交发送的信息,即使您认为它们只有有限的选项。相反,让下拉引用服务器端代码中的数组中的索引。然后使用该数组选择要插入的内容。这样,即使攻击者试图向您发送恶意代码,它也不会真正命中您的数据库。
显然,这不适用于论坛或博客等自由格式应用程序。对于那些人,你必须依靠“第一步”技术。尽管如此,还是有很多选项可以通过白名单输入验证来改进。
您也可以使用parameterized queries(也称为带有绑定变量的预处理语句)进行sql交互。这将告诉您的数据库服务器所有输入只是一个值,因此它可以减轻注入攻击带来的许多潜在问题。在许多情况下,这甚至可以涵盖自由格式的应用程序。
答案 1 :(得分:6)
通过默认将您输出的任何值与htmlspecialchars()视为html。
只有当你需要输出到本身包含html的html字符串时,才有理由不使用htmlspecialchars()。在这种情况下,您必须确保此字符串来自完全安全的来源。如果您没有这种信心,那么您必须通过白名单html过滤器传递它,该过滤器仅允许精心限制的标签,属性和属性值集。您应该特别注意属性值。你永远不应该允许所有东西作为属性值传递,特别是对于src,hef,style等属性。
你应该知道你的webapp中你输出任何内容到html而不使用htmspeciachars()的所有地方,确保你真的需要那些地方并且要注意尽管你有信心这些地方都是潜在的漏洞。
如果您认为这太过谨慎:“为什么我需要htmlspecialchar()这个变量,我知道它只包含整数并且松散所有宝贵的CPU周期?”
记住这一点:你不知道,你只知道你知道,CPU周期是世界上最便宜的东西,几乎所有这些都会因等待数据库或文件系统甚至内存访问而浪费。
也绝不使用黑名单html过滤器。 Youtube犯了这个错误,有人突然发现只删除了第一个<script>
,如果你在评论中输入第二个,你可以将任何Javascript注入访问者浏览器。
与避免SQL注入类似,使用mysql_real_escape_string()处理您粘贴到SQL查询的所有值,或者更好地使用PDO Prepared语句。
答案 2 :(得分:4)
如果您没有传递任何需要格式化为html的内容,请使用:
strip_tags() <- Eliminates any suspicious html
然后在保存到db
之前运行以下内容进行清理mysql_real_escape_string()
如果您的ajax通过文本框或者wysiwyg保存用户输入的html,那么请使用HTMLPurifier删除javascript但允许使用html标记。
答案 3 :(得分:2)
我不完全同意所提供的其他答案,因此我会发布我的建议。
推荐阅读 XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet
Html注入: 每当显示任何用户提交的内容时,如果在单引号内使用,则在指定ENT_QUOTES时应使用htmlspecialchars或htmlentities进行适当的清理。我建议永远不要用单引号封装,并且总是用双引号封装你的属性(不要省略它们)。这适用于以下内容:
<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注入:
从不将用户内容回显到事件和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.
不要将任何用户内容回显到其他区域,例如脚本标记体等,除非它被强制转换为int或其他非常有限的字符集(如果你知道你在做什么)。
SQL注入: 使用Prepared statements,将用户内容绑定到它们,并且永远不会直接将用户内容插入查询。我建议为具有辅助函数的预处理语句创建一个类,用于不同的基本语句类型(在主题上,功能化所有数据库语句)。如果您选择不使用预准备语句,请使用mysql_real_escape_string()或类似语句(而不是addslashes())。在存储到数据库之前尽可能验证内容,例如强制/检查整数数据类型,对类型进行条件检查等。使用适当的数据库列类型和长度。请记住,这里的主要目标是防止sql注入,但你也可以选择在这里进行html / javascript注入保护。
其他资源 我在网上做了一些研究,希望找到一个已公开的简单解决方案。我找到了OWASP ESAPI,但看起来很陈旧。 php版本的链接在几个地方被破坏了。我相信我在这里找到了它; ESAPI PHP但它又过时了,并不像我希望的那么简单。但是你会发现它很有用。
总而言之,不要只假设您受到保护,例如在onClick属性中使用htmlentities。您必须在正确的位置使用正确的工具,避免在错误的位置做事。
答案 4 :(得分:0)
这个问题已经有一些答案被用户接受和评价。
相反,我也在发布答案,希望它能正常工作。
这是我测试过的。
$value = preg_replace("/[\'\")(;|`,<>]/", "", $value);
preg_replace()函数在这里非常有效。