Php 使用CodeIgniter防止MS SQL注入

Php 使用CodeIgniter防止MS SQL注入,php,codeigniter,security,sql-injection,Php,Codeigniter,Security,Sql Injection,我想找到一种最佳的方法来缓解在CodeIgniter框架中开发的web应用程序中的SQL注入(web应用程序使用MS SQL后端数据库和ODBC连接) 假设我有一个简单的易受攻击的代码,如下所示: $this->db->query("SELECT * FROM users WHERE Login = '".$_GET['name']."'"); 此查询显然容易受到通过HTTP GET参数“name”进行SQL注入的攻击 我已经阅读了CodeIgniter文档以及我在网上找到的所有内

我想找到一种最佳的方法来缓解在CodeIgniter框架中开发的web应用程序中的SQL注入(web应用程序使用MS SQL后端数据库和ODBC连接)

假设我有一个简单的易受攻击的代码,如下所示:

$this->db->query("SELECT * FROM users WHERE Login = '".$_GET['name']."'");
此查询显然容易受到通过HTTP GET参数“name”进行SQL注入的攻击

我已经阅读了CodeIgniter文档以及我在网上找到的所有内容,以了解如何缓解CodeIgniter中的这种简单SQL注入,并且我已经尝试了以下所有选项:

备选案文1:

$this->db->query("SELECT * FROM users WHERE Login = ".$this->db->escape($_GET['name']));
备选案文2:

$this->db->select("*")->from("users")->where('Login', $_GET['name'])->get();
备选案文3:

$query = "SELECT * FROM users WHERE Login = '?'"; 
$this->db->query($query, array($_GET['name']));
备选案文4:

$query = "SELECT * FROM users WHERE Login = ?"; 
$this->db->query($query, array($_GET['name']));
我震惊地发现,上述四个选项与初始查询一样容易受到SQL注入的攻击。我想知道CodeIgniter从安全角度看是否设计得如此糟糕,或者我是否遗漏了一些重要的配置

在这种情况下,有没有概念上的方法来防止CodeIgniter中的SQL注入?

  • 检查每个用户输入的数据类型以及正则表达式适用的位置(从不信任用户输入)
  • 使用事先准备好的陈述
这需要做很多工作,尤其是在应用程序状态不好的情况下,但这是获得良好安全级别的最佳方法


另一种方法(我建议反对)可能是使用mod_security或WAF进行虚拟修补,以过滤注入尝试,但首先是:尝试编写健壮的应用程序(虚拟补丁可能看起来是一种懒散的修复方法,但实际上也需要大量的工作和测试,而且应该只在已经强大的应用程序代码上使用)

好的,经过几个小时的努力,我自己终于找到了答案

版本3.1.0之前的CodeIgniter ODBC驱动程序中存在SQL注入漏洞。因此,即使从安全角度来看编码样式(查询绑定)是正确的(如选项4所示),应用程序仍然容易通过用户提供的输入进行SQL注入

通过并行安装运行相同查询的CodeIgniter 3.0.6和3.1.0,我验证了这一点。CodeIgniter 3.0.6中的代码仍然容易受到SQL注入的攻击,而运行在CodeIgniter 3.1.0中的代码则没有

代码点火器更改日志


因此,我们将从中吸取教训。请始终记住检查框架版本。

您是如何发现所有选项都易受攻击的?前两个选项根本不起作用,第三个选项只是执行第四个选项的错误方式……第四个选项是唯一的“选项”这是有效的,也是唯一安全的。选项2有什么问题?我已经对应用程序进行了渗透测试,其中有我在帖子中提到的易受攻击的代码行。现在,我想提出解决方案如何修复它。我在帖子中测试了所有四个选项,它们都对我有效-但这实际上并不重要。如果我使用选项4这应该是安全的,我提交了以下HTTP GET参数?name=nonexistent'或1=1,然后应用程序抛出以下错误:[Microsoft][ODBC SQL Server驱动程序][SQL Server]字符串“”后未闭合的引号。请从auth_user中选择*,其中Login='nonexistent'或1=1'您确定第四个选项不安全吗?第三个选项实际上不应该工作。您应该编写
,而不是
“?”
。这样做的原因是不需要转义整数值,但字符串值会被转义被CodeIgniter自动转义,然后被你的引号包围。此外,这个问题可能是我打开这个问题的重复,因为对我来说没有任何效果。我用选项4替换了原始易受攻击的代码,并且我能够执行与以前完全相同的sql注入。可能它与后端MS sql和ODBC有关。否我真的不确定……并定期更新。不要将其保留在3.1.0版本-它是修复此特定问题的版本,但不是最新版本。