PHP MySQL $_GET 防止黑客攻击

8
如果我使用$_GET函数从URL中检索变量,如何使其防止被黑客攻击?现在我只是使用addSlashes,还应该添加什么?
(提示:此问题已有解决方案,请参考PHP中防止SQL注入的最佳方法
$variable1 = addslashes($_GET['variable1']);
//www.xxxxx.com/GetTest.php?variable1=xxxx

为了以后参考,这是我用于保护get函数中数值的函数(对于非数值的get值,请移除floatval()函数):addslashes(mysql_real_escape_string(strip_tags(floatval()))); - Albert Renshaw
4个回答

21

对于任何输入,不仅仅是 $_GET,甚至包括 $_POST、$_FILES 以及从磁盘或流中读取的任何内容,首要原则都是验证。

现在更详细地回答你的问题,世界上有几种黑客攻击方法。让我给你展示一些:

XSS 注入

如果你接受来自 URL 的数据,例如从 $_GET 中获取并输出这些数据而没有删除可能存在的标签,你可能会使你的网站容易受到 XSS 注入或代码注入攻击。例如:

http://myhoturl.com/?search=<script>window.location.href="http://thisisahack.com/"</script>

这会在你的网站上输出一个黑客脚本并将人们重定向到另一个页面。该页面可能是钓鱼攻击,用于窃取凭据。

SQL注入

可以向您的应用程序注入SQL代码。例如:

http://myhoturl.com/?search=%'; UPDATE users SET password=MD5('hello'); SELECT * FROM users WHERE username LIKE '%

这将使您的SQL看起来像这样:

SELECT * FROM articles WHERE title LIKE '%%'; UPDATE users SET password=MD5('hello'); SELECT * FROM users WHERE username LIKE '%%';

因此,您将更新所有用户的密码为“Hello”,然后返回与之不匹配的内容。

这只是关于如何使用SQL注入的简要概述。要保护自己,请使用mysql_real_escape_string或PDO或任何良好的数据库抽象层。

代码注入

许多人喜欢从磁盘上的某个位置包含数据并允许上传文件。例如:

//File igotuploaded.txt
<?php echo 'helloworld'; ?>

此外,该URL允许您通过文件名INCLUDE文件。 ?show=myhotfile.txt

//In this file we include myhotfile.txt
include($_GET['show']);

那个人将其更改为 ?show=../uploads/igotuploaded.txt 然后你将运行echo 'Hello world';

这是很危险的。

经验原则是... 永远不要相信用户输入,总是进行验证、防止、验证、修复、验证和再次纠正...

祝你好运


那么我该如何让我的PHP脚本忽略通过$_get检索到的SQL查询呢?感谢所有的示例! - Albert Renshaw
mysql_real_escape_string或者如果您使用PDO或良好的DB层,通常会自动为您完成... - Mathieu Dumoulin
什么是“PDO”?它代表什么,我该如何使用它?我经常看到这个词!非常感谢你迄今为止提供的所有帮助! - Albert Renshaw
1
PHP 数据对象(PDO)- http://php.net/manual/zh/book.pdo.php - Mathieu Dumoulin
“XSS”代表跨站脚本攻击吗?我在另一个用户的回复中看到了这个词。 - Albert Renshaw
1
是的,XSS指的是跨站脚本攻击。 - Mathieu Dumoulin

5

这完全取决于你将用它做什么:

如果不知道你要用数据做什么,就无法确定哪种方法可以使其更安全。


假设我正在按照下面的人所说的方式使用它(目前我没有特定的用途,只是想学习,所以当我决定在未来使用get时,我会安全地使用它... 无论如何,假设:mysql_query("SELECT userid FROM user WHERE password='".$_GET["variable1"]."';"); - Albert Renshaw
1
@Albert Renshaw,你必须了解你的数据,如果一个字段应该是整数,最好将它转换为整数:(int) $_GET['...'] - jeroen
那么像<b><center>hello</center></b>这样的东西只会显示为“bcenterhellocenterb”。 另外,我记得有一些关于仅剥离HTML标签的内容,以便它只显示为“hello”,我该怎么做? - Albert Renshaw
1
@Albert Renshaw strip_tags($string) 去除 HTML 标签函数。 - jeroen
要在PHP中进行过滤,请查看http://php.net/filter。 - Bill Karwin
显示剩余5条评论

3

当使用用户输入(任何HTTP请求都算作用户输入)时,您面临的两个最大风险是:

您应该了解这些威胁和防御措施。每种威胁的防御措施都是不同的。使用addslashes()并不是一种完整的防御方法。

学习更多关于安全的Web编程的好资源是OWASP十大项目

我做过一个关于SQL注入的神话和谬论的演示文稿,希望对您有所帮助。


我注意到另一个用户的评论中提到了“XSS注入”,这是指跨站点脚本注入吗? - Albert Renshaw
是的,XSS是跨站脚本攻击的常用缩写。 - Bill Karwin

-1

读取 $_GET 变量本身并不危险,

危险通常在于 SQL 注入攻击,

例如:

$_GET["variable1"] = "' OR 1=1 --";

使用查询语句:

mysql_query("SELECT userid FROM user WHERE password='".$_GET["variable1"]."';");

为了防止这种情况发生:
$safe_input = mysql_real_escape_string($GET["variable1"]);
mysql_query("SELECT userid FROM user WHERE password='".$safe_input."';");

2
mysql_real_escape_string() 不总能防止注入。这可能会让提问者认为,如果他只转义输入,就永远不用担心 SQL 注入问题了。 - kba
1
@AlbertRenshaw mysql_real_escape_string() 只转义单引号、双引号等字符。如果没有这些字符,它就毫无用处。例如,在分页时使用 LIMIT 10, $page。如果 $page 包含 1; DROP TABLE tbl --,转义也无济于事。始终验证您的输入并确保您拥有正确的值(例如 is_numericintval)。 - kba
is_numeric!哇!太好了!啊,真不错!谢谢!这将在诸如页码之类的事情上大有帮助!太棒了!谢谢!+1 - Albert Renshaw
2
@AlbertRenshaw 不,它不会报错,只会返回true。考虑一个糟糕的登录系统,SELECT username FROM tbl WHERE username='$user' AND password='$pass'。如果$pass是' OR 1=1 --,那么查询语句将变成SELECT username FROM tbl WHERE username='$user' AND password='' OR 1=1 --',因此返回用户名并使应用程序认为输入了正确的密码。 - kba
此外,供像我这样毫无头绪的其他人参考(通过谷歌找到了这个)如果您想使用Kristian提供的“intval();”功能,并且您有一个数字但它不是整数(例如4.389),intval将返回4,但如果您想保留完整的数字值但仍要剥离掉字母和SQL查询,您可以使用“floatval();”。 - Albert Renshaw
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接