gpt4 book ai didi

php - 它们如何工作:DB-Connect和SQL注入(inject)?

转载 作者:太空宇宙 更新时间:2023-11-03 10:52:35 26 4
gpt4 key购买 nike

我的问题是关于数据库连接和SQL注入的应用程序。我正在使用下面提供的代码成功连接到我的数据库。我想问一下:


foreach如何停止SQL注入?
是否有更好,更有效的方法来使连接更安全?
如果将dbconnect.php包含在另一个文件(例如global.php)中,而该连接又包含在实际使用数据库的主文件中,则该连接是否仍会工作并向我提供数据库中的有效数据?是吗


example_file.php:

<?php 
//MySQL Database Connect
include './includes/dbconnect.php';


//This stops SQL Injection in POST vars
foreach ($_POST as $key => $value) {
$_POST[$key] = mysql_real_escape_string($value);
}
//This stops SQL Injection in GET vars
foreach ($_GET as $key => $value) {
$_GET[$key] = mysql_real_escape_string($value);
}
?>


dbconnect.php:

<?php
$con = mysql_connect("localhost","username","password");

if (!$con){ die('Could not connect: ' . mysql_error()); }
mysql_select_db("databasename", $con);

?>


非常感谢!

最佳答案

foreach如何停止SQL注入?


这真的非常重要,因此我要大声说出来,希望人们可以理解……

没有!

“为什么不呢?”,我听到你问。好吧,我年轻的padawan,是因为:


它只转义字符串

假设有一个网站,用户可以通过该网站查看他们的病历。为了使用户能够过滤与特定疾病相关的记录,可以允许其id将疾病指定为查询参数:

http://www.example.com/health/fetchmyrecords.php?illness=123

开发人员首先在您的问题中应用foreach循环,然后假定“ phe,我可以安全地进行SQL注入-不用担心!”,然后这样做:

$res = mysql_query("
SELECT *
FROM health_records
WHERE user = $_SESSION[uid]
AND illness = $_GET[illness]
");
while ($row = mysql_fetch_array($res)) print_r($row);


你看到问题了吗?考虑一下。


  问题
  
  假设有人请求以下URI:
  
   http://www.example.com/health/fetchmyrecords.php?illness=123+OR+1
  
  然后,MySQL将收到以下查询:
  
  
SELECT *
FROM health_records
WHERE user = 987
AND illness = 123 OR 1

  
  SQL成功注入!在此特定示例中,注入是致命的,因为MySQL会将 WHERE子句解析为:
  
  
WHERE (user = 987 AND illness = 123) OR 1

  
  …因此它实际上将返回数据库中每个用户的每条健康记录!
  
  祝你好运,承受由此而产生的法律费用。有一个合理的猜测,就是您的业务将崩溃,您的个人财务将被破坏,您的房屋将被收回,您的妻子将离开您,您的孩子将不会与您说话并且您的猫会逃走!


解释(对于注射,不是您的猫的消失)是,一个人只能使用 mysql_real_escape_string()转义字符串(线索在名称中)。它不能用于转义任何其他SQL令牌:not number literals;不是 identifiers;当然不是SQL关键字或特殊字符。这些令牌必须以其他方式保护。

因此,几乎不管其含义如何,都将每个接收到的变量任意转义几乎是不正确的。此外,结果仅在SQL中有用:如果您想将这些变量用于其他任何用途,数据将被杂乱无章,因此您实际上绝对不应该将结果存储回 $_GET$_POST数组中。
它只转义字符串

对于实际上是字符串的变量,仅应用 mysql_real_escape_string()不一定会停止SQL注入。您还必须正确引用 String Literals


  字符串是字节或字符序列,用单引号(“ '”)或双引号(“ "”)字符括起来。


但是,如果MySQL服务器处于 NO_BACKSLASH_ESCAPES SQL模式,则 mysql_real_escape_string()不能安全地转义用于双引号的字符串。因此,为了安全起见,您必须:


使用单引号文字;要么
明确设置其他一些SQL模式。


此外,在调用 mysql_real_escape_string()之前,您必须首先告诉MySQL客户端库,服务器将使用哪种字符编码来解释此类字符串-通常通过调用 mysql_set_charset()(但是,有一些与编码相关的注入,即使这样做也不会失败如果您使用的是旧版客户端库)。


有关更多详细信息,请参见 SQL injection that gets around mysql_real_escape_string()

加起来


使用最新的客户端库
致电 mysql_set_charset()
禁用 NO_BACKSLASH_ESCAPES或使用单引号文字
仅在字符串文字上使用 mysql_real_escape_string()
除了产生SQL之外,不要将结果用于任何其他用途
以其他方式使其他令牌安全




  是否有更好,更有效的方法来使连接更安全?


是的,最肯定的是-已经有好几年了。实际上,以至于 mysql_real_escape_string()确实应该被视为反模式。永远不要使用它。

可悲的是,一个接一个的教程继续讲授这种可笑的过时和危险的构造SQL方法。他们中的许多人早已不存在了,因此原本写得不好可能是可以原谅的(但到现在为止,它们确实应该被更新,删除或忽略);但是,对于每一个推荐使用 mysql_real_escape_string()的新课程或教程,上帝都会杀死一只小猫。有人会不会想到小猫?!

“更好的方式”实际上有两个方面:


停止使用以 mysql_为前缀的那些PHP函数。它们最初是在MySQL v3.23的PHP v2.0中引入的,自2006年以来未添加任何新功能。自2011年6月以来,该手册包含有关在新代码中使用它们的警告,并且在PHP v5.5中已正式弃用它们。 。

PHP附带了两个非常好的现代替代方案: mysqliPDO_MySQL-有关确定使用哪种方法的帮助,请参见 MySQL: Choosing an API
使用这些替代API之一,您可以对SQL语句进行参数化,以使文字值独立于语句本身传输到服务器:因此,服务器甚至都不会尝试解析这些文字值的SQL,无论它们包含的值如何。注入根本不可能从字面值发生(请注意,您仍然需要保护其他令牌,但这不是很常见的要求,并且不在此答案的范围之内)。


How can I prevent SQL injection in PHP?



  如果将dbconnect.php包含在另一个文件(例如global.php)中,而该连接又包含在实际使用数据库的主文件中,则该连接是否仍会工作并向我提供数据库中的有效数据?是吗


是。在大型项目中,包含文件包含更多文件是很常见的。

关于php - 它们如何工作:DB-Connect和SQL注入(inject)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23373888/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com