通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。具体来说,它是利用现有应用程序,将(恶意)的SQL命令注入到后台数据库引擎执行的能力,得到一个存在安全漏洞的网站上的数据库。
SQL Injection,SQL 注入,其实就是利用代码漏洞改变 SQL 的语意,从而形成恶意 SQL 语句
$username = $_POST['username']; $password = $_POST['password']; $query = "select * from users where username = '{$username}' and password = '{$password}'"; // 判断是否登录成功 if (DB::select($query)) { return true; } return false;
咋一看这段伪代码没啥问题,就是判断账号密码是否正确,正确就返回 true,允许登录。但是如果传入的 username 为 123' or 1=1;#\,那么 SQL 语句就变为了
select * from users where username = '123' or 1=1; # and password = '{$password}'";
这条恶意的 SQL 语句无论何时都会返回 true,因为 1=1
我们前面讲过 SQL Injection 就是利用代码漏洞改变 SQL 的语意,意味着 ORM 也是一个潜在的注入点。以 tp3.2 为例,有下面这段代码
$result = D('User')->where([ 'username' => $_POST['username'], 'password' => $_POST['password'], ]); if ($result) { echo '登录成功'; } else { echo '登录失败'; }
这段代码咋看起来没啥问题,但是如果 username 传入的是 username[0]=neq&username[1]=1111,这样就是的查询语句变为
$result = D('User')->where([ 'username' => ['neq', 111], 'password' => $_POST['password'], ]);
那么 $result 的结果将永远为 true
对传入的参数进行数据类型判断和数据类型转换
对引号进行转义,PHP 可以使用 addslashes,mysql_real_escape_string 等函数
预处理语句,最有效防范 SQL Injection
代码审计
预处理语句是由数据库实现的,比如 MySQL 就有实现预处理语句。首先讲下预处理的基本流程
MySQL 接收到 预处理 SQL Template,立刻着手进行解析(词法和语法)
客户端发送数据,去替换 SQL Template 中的占位符(?)
MySQL 执行语句,返回结果
删除预处理语句(可选)
那么预处理语句是如何防范 SQL 注入的呢?首先所谓的 SQL Injection 就是强行去改变 SQL 语意。而在步骤一中已经处理完成语句,将 SQL 的语意固定下来,步骤二的替换占位符并不会改变 SQL 语意。下面是 PHP PDO 的例子
$stmt = $pdo->prepare("select * from users where username = '?' and password = '?'"); $stmt->execute("123' or 1=1;#", 'test');
相关推荐:《mysql教程》
以上是一分钟带你了解SQL Injection的详细内容。更多信息请关注PHP中文网其他相关文章!