如何防止PHP中的代码注入攻击?

时间:2009-07-30 11:04:06

标签: php code-injection

我有点困惑,PHP中有这么多功能,有些使用这个,有些使用它。有些人使用:htmlspecialchars()htmlentities()strip_tags()

哪个是正确的,你们通常使用什么?

这是否正确(如果有的话,建议我更好):

$var = mysql_real_escape_string(htmlentities($_POST['username']));

这一行可以防止MySQL注入和XSS攻击吗?

顺便说一下,除了XSS攻击和MySQL注入之外还有其他什么需要注意吗?

修改

总结:

如果我想将字符串插入数据库,我不需要使用htmlentities,只需使用mysql_real_escape_string即可。显示数据时,使用htmlentities(),这就是你的意思吗?

概述:

    插入数据库时​​使用的
  • mysql_real_escape_string
  • 将数据输出到网页时使用的
  • htmlentities()
  • htmlspecialchars()何时使用?
  • strip_tags()何时使用?
  • addslashes()何时使用?

有人可以填写问号吗?

8 个答案:

答案 0 :(得分:63)

  
      插入数据库时​​使用的
  • mysql_real_escape_string
  •   将数据输出到网页时使用的
  • htmlentities()
  •   
  • htmlspecialchars()何时使用?
  •   
  • strip_tags()何时使用?
  •   
  • addslashes()何时使用?
  •   

htmlspecialchars()在何时使用?

htmlspecialcharshtmlentities大致相同。区别:字符编码。

两者都编码控制字符,如<>&等用于打开标记等。htmlentities也编码来自其他语言的字符,例如变形金刚,欧元 - 符号等。如果您的网站是UTF,请使用htmlspecialchars(),否则请使用htmlentities()

strip_tags()在?

时使用

htmlspecialchars / entities对特殊字符进行编码,因此它们显示但未解释strip_tags删除它们。

在实践中,这取决于你需要做什么。

一个例子:您编写了一个论坛,并为用户提供了一个文本字段,以便他们发布内容。恶意的只是尝试:

pictures of <a href="javascript:void(window.setInterval(function () {window.open('http://evil.com');}, 1000));">kittens</a> here

如果您不做任何事情,将显示该链接,点击该链接的受害者会获得大量弹出窗口。

如果您输出htmlentity / htmlspecialchar,则文本将按原样显示。如果你strip_tag它,它只是删除标签并显示它:

pictures of kittens here

有时您可能想要混合,在其中留下一些标签,例如<b>strip_tags可以在其中留下某些标签)。这也是不安全的,所以最好使用一些完整的库来对抗XSS。

和addslashes

引用old version of the PHP manual

  

在需要在数据库查询中引用的字符之前返回带有反斜杠的字符串。这些字符是单引号('),双引号(“),反斜杠()和NUL( NULL 字节)。

     

使用 addslashes()的一个示例是将数据输入数据库。例如,要将名称​​ O'reilly 插入数据库,您需要将其转义。强烈建议使用DBMS特定的转义函数(例如MySQL的mysqli_real_escape_string()或PostgreSQL的pg_escape_string()),但如果您使用的DBMS没有转义函数且DBMS使用\来转义特殊字符,那么可以使用这个功能。

current version措辞不同。

答案 1 :(得分:9)

我想到了这个快速清单:

  • 始终使用HTTPS,不使用HTTPS,您的网站完全未加密。不,客户端加密和发送它们不会起作用,想一想。 无效的HTTPS证书也会让您容易受到MITM攻击。如果您无法负担证书,请使用我们的加密。
  • 始终在PHP代码的任何输出上使用htmlspecialchars(),即包含用户输入。大多数模板引擎都可以帮助您轻松完成。
  • php.ini中使用仅HTTP标记以防止脚本访问您的Cookie
  • 防止与会话相关的问题
    • 永远不要在Cookie之外公开用户PHPSESSID(会话ID),如果有人知道其他人的会话ID,他们可以直接使用它登录他们的帐户
    • Remember me功能要非常小心,可能会显示一点警告。
    • 当用户登录时(或任何适当的时候)刷新会话ID
    • 超时非活动会话
  • 从不信任cookie,可随时由脚本/用户更改,删除,修改和创建
  • 防止与SQL相关的问题
    • 始终使用准备好的陈述。准备好的语句会导致用户输入单独传递并阻止SQL Injection
    • 让代码在失败时抛出异常。有时您的SQL服务器可能由于某种原因而关闭,PDO等库默认忽略该错误,并在日志中记录警告。这会导致从数据库获取的变量为空,具体取决于您的代码,这可能会导致安全问题。
    • 某些库,例如PDO 模拟准备好的语句。把它关掉。
    • 在您的数据库中使用UTF-8编码,它允许您存储几乎任何字符并避免与编码相关的攻击
    • 永远不要将任何内容连接到您的查询。像$myquery = "INSERT INTO mydb.mytable (title) VALUES(" . $user_input . ")"之类的东西几乎意味着你有很大的SQL注入安全风险。
  • 以随机,无扩展名的文件名存储上传的文件。如果用户上传文件扩展名为.php的文件,那么只要您的代码加载该文件,它就会执行该文件,并使用户能够执行某些后端代码
  • 确保您不会受到CSRF attack
  • 的攻击
  • 始终更新您的PHP副本以确保最新的安全补丁和性能改进

答案 2 :(得分:6)

仅对数据进入需要编码的系统进行编码 - 否则您将遇到想要操纵实际数据的情况。

对于SQL注入 - 使用How can I prevent SQL injection in PHP?中描述的绑定变量(它讨论预准备语句,但它是为您提供保护而不是准备的绑定)。

对于XSS - 如果您在指定HTML或文本的位置写入HTML。在生成文档的位置使用htmlentities。我会避免以这种形式将数据存储在数据库中(除了可能在写入稀疏读取的系统中,CPU性能/磁盘访问时间正在变成并发出 - 然后我会有一个raw_和html_版本的列......或者只是使用memcached或类似的东西。)

如果您要让用户输入网址,那么您需要更加小心,因为javascript:do_evil()是一个有效的URI(例如,作为点击链接的href或(在某些浏览器中)的src刚加载的图像。

答案 3 :(得分:4)

<强> htmlspecialchars() &'"<>转换为HTML实体格式(&amp;&quot;等。)

<强> htmlentities() 将所有适用的字符转换为HTML实体格式。

<强> strip_tags() 删除所有HTML和PHP标记。

htmlspecialchars()htmlentities()都会使用一个可选参数来指示如何处理引号。见 有关细节的PHP手册。

strip_tags()函数需要一个 可选参数指示什么标签 不应剥夺。

 $var = strip_tags ($var, '<p><br />');

strip_tags()功能将被删除 即使是无效的HTML标签也可能 引起问题。例如, strip_tags()会把所有人都拉出来 它认为是HTML标记的代码 如果它形成不正确,比如

<b I forgot to close the tag.

答案 4 :(得分:3)

在插入数据库时​​只需要使用mysql_escape_string(),在显示HTML时需要使用htmlentites。如果您想要防止简单的注入攻击,这就足够了,但毫无疑问,在开发Web应用程序时您应该注意许多其他安全问题,另一个主要问题是跨站点请求伪造。

答案 5 :(得分:2)

在将数据插入数据库或查询数据库时,我不会使用htmlentities()。如果您数据库中的数据存储为实体,那么该数据仅对理解html实体的内容有用。

您必须为不同类型的输出使用不同的转义机制,例如SQL - mysql_real_escape_string(),HTML - htmlentities()htmlspecialchars(),shell - escapeshellarg()。这是因为“危险”的字符对于每个字符都是不同的 - 没有一种神奇的方法可以使任何数据对任何输出媒体都安全。

答案 6 :(得分:1)

查看此网站PHP Security Consortium。我发现它是一个很好的网站,可以全面了解PHP安全性(包括SQL注入和XSS)。

答案 7 :(得分:1)

我知道这是一个老问题,但现在投票最多的答案可能会误导初学者。

截至2017年

  1. 你永远不应该使用mysql_real_escape_string。甚至mysqli_real_escape_string也太弱,无法保护您的数据库免受SQL注入。而不是这个,你应该使用PDO和类似的技术。 (见that guide

  2. XSS(我的意思是:strip_tags()addslashes()htmlspecialchars()htmlentities()) - 这里投票最多的答案仍然是正确的,但我建议阅读this article