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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1205889/
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-08-25 01:32:12  来源:igfitidea点击:

How to prevent code injection attacks in PHP?

phpcode-injection

提问by bbtang

I am a bit confused, there are so many functions in PHP, and some using this, some using that. Some people use: htmlspecialchars(), htmlentities(), strip_tags()etc

我有点困惑,PHP中有这么多函数,有的用这个,有的用那个。有些人使用:htmlspecialchars()htmlentities()strip_tags()

Which is the correct one and what do you guys usually use?

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

Is this correct (advise me a better one, if any):

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

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

This line can prevent MySQL injection and XSS attack??

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

Btw, is there any other things I need to pay attention besides XSS attack and MySQL injection?

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

EDIT

编辑

To conclude:

总结:

If I want to insert string to the database, I do not need to use htmlentities, just use the mysql_real_escape_string. When displaying the data, use htmlentities(), is that what you all mean??

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

Summarize:

总结:

  • mysql_real_escape_stringused when insert into database
  • htmlentities()used when outputting data into webpage
  • htmlspecialchars()used when?
  • strip_tags()used when?
  • addslashes()used when?
  • mysql_real_escape_string插入数据库时​​使用
  • htmlentities()输出数据到网页时使用
  • htmlspecialchars()什么时候用?
  • strip_tags()什么时候用?
  • addslashes()什么时候用?

Can somebody fill in the question mark?

有人可以填写问号吗?

回答by stefs

  • mysql_real_escape_stringused when insert into database
  • htmlentities()used when outputting data into webpage
  • htmlspecialchars()used when?
  • strip_tags()used when?
  • addslashes()used when?
  • mysql_real_escape_string插入数据库时​​使用
  • htmlentities()输出数据到网页时使用
  • htmlspecialchars()什么时候用?
  • strip_tags()什么时候用?
  • addslashes()什么时候用?

htmlspecialchars() used when?

htmlspecialchars() 什么时候使用?

htmlspecialcharsis roughly the same as htmlentities. The difference: character encodings.

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

Both encode control characters like <, >, &and so on used for opening tags etc. htmlentitiesalso encode chars from other languages like umlauts, euro-symbols and such. If your websites are UTF, use htmlspecialchars(), otherwise use htmlentities().

两个编码控制字符,如<>&等等用于打开标签等htmlentities从像元音变音,欧元符号和这样的其它语言也编码字符。如果您的网站是 UTF,请使用htmlspecialchars(),否则使用htmlentities().

strip_tags() used when?

strip_tags() 什么时候使用?

htmlspecialchars/ entitiesencode the special chars, so they're displayed but not interpreted. strip_tagsREMOVES them.

htmlspecialchars/entities编码特殊字符,因此它们被显示但不被解释strip_tags删除它们。

In practice, it depends on what you need to do.

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

An example: you've coded a forum, and give users a text field so they can post stuff. Malicious ones just try:

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

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

If you don't do anything, the link will be displayed and a victim that clicks on the link gets lots of pop-ups.

如果你什么都不做,链接就会显示出来,点击链接的受害者会得到很多弹出窗口。

If you htmlentity/htmlspecialchar your output, the text will be there as-is. If you strip_tag it, it simply removes the tags and displays it:

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

pictures of kittens here

Sometimes you may want a mixture, leave some tags in there, like <b>(strip_tagscan leave certain tags in there). This is unsafe too, so better use some full blown library against XSS.

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

addslashes

加斜线

To quote an old version of the PHP manual:

引用旧版本的 PHP 手册

Returns a string with backslashes before characters that need to be quoted in database queries etc. These characters are single quote ('), double quote ("), backslash () and NUL (the NULLbyte).

An example use of addslashes()is when you're entering data into a database. For example, to insert the name O'reillyinto a database, you will need to escape it. It's highly recommeneded to use DBMS specific escape function (e.g. mysqli_real_escape_string() for MySQL or pg_escape_string() for PostgreSQL), but if the DBMS you're using does't have an escape function and the DBMS uses \ to escape special chars, you can use this function.

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

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

The current versionis worded differently.

目前的版本是不同的措词。

回答by OverCoder

I thought of this quick checklist:

我想到了这个快速清单:

  • Always use HTTPS, without HTTPS your site is totally unencrypted. And no, client-side encrypting things and sending them won't work, think about it. Invalid HTTPS certificates also make you vulnerable to a MITMattack. Just use Let's Encrypt if you can't afford a certificate.
  • Always use htmlspecialchars()on any output from your PHP code, that is, or contains a user input. Most templating engines help you do that easily.
  • Use HTTP-only flag in your php.inito prevent scripts from accessing your cookies
  • Prevent session-related problems
    • Never expose user's PHPSESSID(session ID) outside the cookie, if anybody gets to know a Session ID of somebody else, they can simply use it to login to their account
    • Be very careful with the Remember mefunction, show a little warning maybe.
    • Refresh session ID when the user signs in (or whatever appropriate)
    • Timeout inactive sessions
  • Nevertrust a cookie, it can be changed, removed, modified, and created by a script/user at any moment
  • Prevent SQL-related problems
    • Always use prepared statements. Prepared statements causes the user input to be passed separately and prevents SQL Injection
    • Make your code throw an exception when it fails. Sometimes your SQL server might be down for some reason, libraries like PDOignore that error by default, and log a warning in the logs. This causes the variables you get from the DB to be null, depending on your code, this may cause a security issue.
    • Some libraries like PDOemulateprepared statements. Turn that off.
    • Use UTF-8encoding in your databases, it allows you to store virtually any character and avoid encoding-related attacks
    • Never concatenate anything to your query. Things like $myquery = "INSERT INTO mydb.mytable (title) VALUES(" . $user_input . ")"pretty much mean you have a huge security risk of an SQL injection.
  • Store uploaded files in random, extension-less filenames. If a user uploads a file with .phpfile extension then whenever your code loads that file it executes it, and enables the user to execute some backend code
  • Make sure you're not vulnerable to a CSRF attack.
  • Always update your PHP copy to ensure the latest security patches and performance improvements
  • 始终使用 HTTPS,如果没有 HTTPS,您的网站将完全未加密。不,客户端加密并发送它们是行不通的,考虑一下。无效的 HTTPS 证书还会使您容易受到MITM攻击。如果您买不起证书,请使用 Let's Encrypt。
  • 始终用于htmlspecialchars()PHP 代码的任何输出,即或包含用户输入。大多数模板引擎可以帮助您轻松地做到这一点。
  • 在您的 HTTP-only 标志中使用php.ini以防止脚本访问您的 cookie
  • 防止与会话相关的问题
    • 永远不要PHPSESSID在 cookie 之外暴露用户的(会话 ID),如果有人知道其他人的会话 ID,他们可以简单地使用它登录到他们的帐户
    • 小心使用该Remember me功能,可能会显示一些警告。
    • 当用户登录(或任何适当的)时刷新会话 ID
    • 超时非活动会话
  • 永远不要相信 cookie,它可以随时由脚本/用户更改、删除、修改和创建
  • 防止与 SQL 相关的问题
    • 始终使用准备好的语句。准备好的语句导致用户输入单独传递并防止SQL 注入
    • 使您的代码在失败时抛出异常。有时您的 SQL 服务器可能由于某种原因关闭,PDO默认情况下会忽略该错误,并在日志中记录警告等库。这会导致您从数据库获取的变量为空,具体取决于您的代码,这可能会导致安全问题。
    • 一些库喜欢PDO模拟准备好的语句。把它关掉。
    • UTF-8在您的数据库中使用编码,它允许您存储几乎任何字符并避免与编码相关的攻击
    • 切勿将任何内容连接到您的查询。诸如此类的事情$myquery = "INSERT INTO mydb.mytable (title) VALUES(" . $user_input . ")"几乎意味着您面临 SQL 注入的巨大安全风险。
  • 以随机的、无扩展名的文件名存储上传的文件。如果用户上传带有.php文件扩展名的文件,那么每当您的代码加载该文件时,它就会执行它,并使用户能够执行一些后端代码
  • 确保您不易受到CSRF 攻击
  • 始终更新您的 PHP 副本以确保获得最新的安全补丁和性能改进

回答by Quentin

Only encode data at the point where it goes into the system it needs to be encoded for — otherwise you will run into situations where you want to manipulate the real data.

仅在数据进入需要对其进行编码的系统的位置对数据进行编码 - 否则您将遇到想要操作真实数据的情况。

For SQL injection - use bound variables as described in How can I prevent SQL injection in PHP?(it talks about prepared statements, but it is the binding that gives you protection, not the preparation).

对于 SQL 注入 - 使用如何防止 PHP 中的 SQL 注入中所述的绑定变量(它谈论的是准备好的语句,但它是为您提供保护的约束,而不是准备)。

For XSS - if you are writing into HTML at point where either HTML or text is specified. Use htmlentities at the point where you generate your document. I would avoid storing the data in that form in the database (except possible in a write-rare-read-often system where CPU performance/disk access times were becoming and issue - then I would have a raw_ and an html_ version of the column … or just use memcached or similar).

对于 XSS - 如果您在指定 HTML 或文本的位置写入 HTML。在生成文档的地方使用 htmlentities。我会避免将数据以这种形式存储在数据库中(除非可能在 CPU 性能/磁盘访问时间变得和问题的写入罕见的系统中可能出现问题 - 然后我将拥有一个 raw_ 和一个 html_ 版本的列...或者只是使用 memcached 或类似的)。

If you are letting users enter URLs then you need to be more careful, as javascript:do_evil()is a valid URI that will execute (e.g. as an href for a clicked upon link or (in some browsers) the src of an image that is just loaded).

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

回答by Faraz Kelhini

htmlspecialchars()turns &, ', ", <, and >into an HTML entity format (&amp;, &quot;, etc.)

htmlspecialchars()&'"<,和>到HTML实体格式(&amp;&quot;等)

htmlentities()turns all applicable characters into their HTML entity format.

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

strip_tags()removes all HTML and PHP tags.

strip_tags()删除所有 HTML 和 PHP 标签。

Both htmlspecialchars()and htmlentities()take an optional parameter indicating how quotation marks should be handled. See the PHP manual for specifics.

双方htmlspecialchars()htmlentities()采取指示引号应该如何处理的可选参数。有关详细信息,请参阅 PHP 手册。

The strip_tags()function takes an optional parameter indicating what tags should not be stripped.

strip_tags()函数采用一个可选参数,指示不应剥离哪些标签。

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

The strip_tags()function will remove even invalid HTML tags, which may cause problems. For example, strip_tags()will yank out all of the code it thinks is an HTML tag, even if it's improperly formed, like

strip_tags()函数甚至会删除无效的 HTML 标签,这可能会导致问题。例如, strip_tags()会删除它认为是 HTML 标记的所有代码,即使它的格式不正确,例如

<b I forgot to close the tag.

回答by Sam152

You only need to use mysql_escape_string() when inserting into a database and htmlentites when displaying the HTML. This is sufficient if you want to prevent a simple injection attack, but there are no doubt many other security issues you should be aware of when developing a web app, another major one being cross site request forgeries.

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

回答by Tom Haigh

I wouldn't use htmlentities() when inserting data into the database or querying the database. If the data in you database is stored as entities, that data is then only useful to something that understands html entities.

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

You have to use different escaping mechanisms for different types of output, e.g. SQL - mysql_real_escape_string(), HTML - htmlentities()or htmlspecialchars(), shell - escapeshellarg(). This is because the characters that are 'dangerous' are different for each one - there isn't a magic way you can make any data safe for any output medium.

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

回答by Henrik P. Hessel

Take a look at this site PHP Security Consortium. I found it to be a good site for an overall overview on PHP Security (SQL Injection and XSS included).

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

回答by Tomasz Durda

I know it's an old question, but nowadays the most voted answer can be misleading for the beginners.

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

As of 2017

截至 2017 年

  1. You should never ever use mysql_real_escape_string. Even mysqli_real_escape_string is too weak to protect your database from the SQL injections. Instead of this, you should use PDO, and similar techniques. (see that guide)

  2. XSS (here I mean: strip_tags(), addslashes(), htmlspecialchars(), htmlentities()) - here the most voted answer is still correct, but I would suggest reading this article

  1. 你永远不应该使用 mysql_real_escape_string。即使 mysqli_real_escape_string 也太弱,无法保护您的数据库免受 SQL 注入。取而代之的是,您应该使用 PDO 和类似的技术。(请参阅该指南

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