从http://www.tizag.com/mysqlTutorial/mysql-php-sql-injection.php我得到了:
SQL注入是指行为 有人插入MySQL语句 在没有你的数据库的情况下在你的数 知识。通常会发生注射 当你问用户输入时,比如 他们的名字,而不是他们的名字 给你一个MySQL声明 将在不知不觉中运行您的数据库。
我阅读了整篇文章,但我仍然有一些重大问题需要了解它是什么以及如何完成。
在第一个例子中,他们实际会看到什么?
据我所知,如果我真的回应$ name,会看到所有的名字,因为它总是“是真的”我是否正确?
我不明白的另一件事是mysql_real_escape_string()是否解决了MySQL注入问题,还有更多问题需要解决。
我真的没有得到的是mysql_real_escape_string()是为了解决这个问题,为什么不自动完成,我的意思是你有必要每次都添加mysql_real_escape_string(),是否有案例何时你应该使用它,这就是为什么他们不自动化?
答案 0 :(得分:10)
MySQL不会自动转义,因为您自己构建查询字符串。例如:
$query = 'SELECT * FROM users WHERE name="' . $name . '"';
您只需传递存储在$ query中的原始字符串,该字符串对SQL注入开放。例如,如果$ name为[OR“1 = 1],则查询字符串最终为:
$query = 'SELECT * FROM users WHERE name="something" OR "1=1"
这将返回用户表中的每个用户。这就是你需要逃避价值的原因。但是,如果您使用PDO,则在您使用绑定功能时会为您完成。这是一个两步过程,准备查询,然后将数据/变量“绑定”到占位符。在PDO中,您的查询字符串将如下所示:
$query = 'SELECT * FROM users WHERE name=":name"';
$bindings = array('name'=>'something');
prepare($query);
execute($bindings);
然后,事情会自动转义给你。
答案 1 :(得分:5)
Bobby Tables总结了SQL注入的工作原理。它带来的好处很多就是几种语言(C#,Java,Perl,PHP等)
对于PHP,它很大程度上取决于您访问数据库的方式。您可以使用数据库提取层(例如ADODB来参与化查询。
答案 2 :(得分:3)
在Tizag链接的第一个示例中,查询看起来像脚本作者希望最多获取一行。因此,假设每一行都被提取,最可能的结果可能是返回的第一行的信息将被采取行动;由于篡改查询中没有ORDER BY
子句,这可能是用户首先存储在表中,但当然缺少ORDER BY
子句时SQL中没有定义顺序,那么谁可以说。你可以说的是,只要表不为空,它就会获取有效用户的详细信息。
我不确定你的意思是“如果我回应$name
”; $name
变量在代码中分配了值"timmy"
。所以我猜他们会看到timmy
。如果你的意思是,如果你试图回应查询获得的用户信息,他们会看到什么 - 嗯,这取决于你使用的代码。如果您循环遍历结果集并且他们使用SQL注入来获取您不希望它们获取的行,那么他们可能会看到所有行,包括您不打算看到的行。如果你的代码只是从一行获取信息并对其进行处理,那么它们仍然会看到一行,但同样可能是一行你并不意味着它们能够到达。
至于为什么mysql_real_escape_string()
提供的功能不是自动的,那是因为它是自动的,依赖于计算机能够从你的SQL代码中解决你想要做的事情,而不仅仅是做你说的做。这既困难又坦率地说是不可取的,因为没有人想让计算机再次猜测他们想做什么(特别是程序员)。
如果您希望能够远离使用mysql_real_escape_string()
等,您可能希望查看使用参数化查询,这样您就可以采取更轻松的方法。您仍然需要向计算机明确查询的哪些部分是您想要转义的变量,因为这只是与计算机进行通信的部分内容。
答案 3 :(得分:3)
在讨论SQL注入时,最常见的例子是“foo'OR 1 = 1”删除整个表或泄露密码。这些注射可以通过逃避弦来挫败。
但是,有很多简单的注入,其中 mysql_real_escape_string()无效。例如,假设您有一个页面,用户可以从中删除数据库中的选定条目。常见的实现是建立查询以基于GET或POST变量删除条目,例如:
$row_to_delete = $_POST['id'];
$query = "DELETE FROM table WHERE id=$row_to_delete";
正如您所看到的,即使对字符串执行了mysql_real_escape_string(),用户也可以轻松地将他们想要的任何“id”发布到此脚本,可能会删除整个表。同样的漏洞可以被利用来猜测哪个“id”属于管理员并且篡改了整个地方的值。据我所知,唯一的保护是从你能想到的每个可能的角度验证所有get和post参数。基本上,不要只进行表单验证 - 进行PARAMETER验证。
如果让这么简单的漏洞泄漏到您的代码中,您会感到惊讶。
答案 4 :(得分:1)
据我所知,在制作网站时,你必须始终认为最终用户是一个肮脏的恶臭威胁,想破坏你的东西。因此,您应始终使用mysql_real_escape_string();
,htmlentities();
和其他人清理字符串。代码可以注入到表单数据中,可以退出它正在执行的操作,插入新代码,然后根据它有权访问的内容完全控制数据库和文件结构。这意味着可以销毁或修改表,值,密码和整个数据库。
有些情况下您可能希望自己注入代码,例如,如果您想创建一个可以向您的数据库输入代码的用户界面,那该怎么办? (ala phpMyAdmin)。也许让它以某种方式自动转义代码会更好,然后如果你想要它可以解除它...也许应该与PHP / mySQL的创建者讨论一下?
这就像我所知道的那样。我希望其他人可以给你更多的洞察力。请记住始终从表单和用户输入中清除返回值。
答案 5 :(得分:1)
你是对的,在第一个例子中,输入“坏”名称的人被允许改变你正在执行的数据库查询,在这种情况下,他们已经改变它以显示表中的所有行
就如何使用子例程来转义特殊字符一样容易防止,您需要了解字符串(或任何数据)可以在不同的级别上理解。当您接受用户输入然后使用它来构建数据库查询时,您希望数据库服务器将该字符串解释为数据。但是,数据库服务器执行此操作的唯一原因是因为您使用特殊字符(如单引号),因此它知道它知道字符串的开始和结束位置。 Escape Characters通过告诉数据库服务器(或任何其他解释它们的系统)不将特殊字符解释为特殊字符,而是将它们解释为数据,就像字符串的其余部分一样。这样,如果你的字符串中有一个特殊字符,那么它的特殊功能就会被忽略。
至于为什么不自动完成?数据库服务器无法知道哪些数据可以信任,哪些数据不可信。只有程序员知道,如果他们很幸运!而且你不能只对所有数据进行处理,因为那些特殊字符(例如单引号)是有原因的 - 它们向数据库服务器传达意义 - 如果你逃避所有这些,那么就没有办法传达他们的意思。这是计算机科学中一个非常基本的概念 - 相同的信息可以在系统的不同层面上解释,系统可能会在该信息中使用特殊的数据模式来表示何时需要在不同的层次上解释数据。
您可能会发现,阅读抽象层的概念对于更基本的理解也很有用。
祝你好运!答案 6 :(得分:0)