以php语言为例,概述编码过程中的sql注入过程,注入可能涉及 存储过程 、sql语句、关键字等方式,本篇只介绍sql相关。
注入基本原理
- (正常情况)假设我们可以通过 http://localhost/test/userinfo.php?username=plhwin 这个URL来访问到具体某个会员的详情,正常情况下,如果浏览器里传入的username是合法的,那么SQL语句会执行:
SELECT uid,username FROM user WHERE username='plhwin'
- (注入情况)但是,如果用户在浏览器里把传入的username参数变为 plhwin';SHOW TABLES-- hack,也就是当URL变为 http://localhost/test/userinfo.php?username=plhwin';SHOW TABLES-- hack 的时候,此时我们程序实际执行的SQL语句变成了:
SELECT uid,username FROM user WHERE username='plhwin';SHOW TABLES-- hack'
解决办法
先说一个线上服务器的配置.
比如用PHP,php.ini文件中的错误提示开关等一定要在生产环境关掉,可百度下,此处不讲。(一般云服务器已经做好了这个)普通用户与系统管理员用户的权限要有严格的区分。
即对普通访问用户只有查询等最低使用权限,并对不同管理人员进行区分,比如root用户、启停用户、管理用户、应用用户等强迫使用参数化语句。如下面的写法
$sql = "SELECT * FROM table WHERE username = ? AND pwd = ?";
bindParam($sql, 1, $username, 'STRING');
//以字符串的形式.在第一个问号的地方绑定$username这个变量
bindParam($sql, 2, $pwd, 'STRING');
//以字符串的形式.在第二个问号的地方绑定$pwd这个变量
- 过滤特殊符号以及检查变量数据类型等
$uid = isset($_GET['uid']) ? $_GET['uid'] : 0;
$uid = addslashes(uid);
$sql = "SELECT uid,username FROM user WHERE uid='{$uid}'";
$uid = isset($_GET['uid']) ? $_GET['uid'] : 0;
$uid = addslashes(uid);
$sql = "SELECT uid,username FROM user WHERE uid={$uid}";
上面两个查询语句都经过了php的addslashes函数过滤转义,但在安全性上却大不相同,在MySQL中,对于int类型字段的条件查询,上面个语句的查询效果完全一样,由于第一句SQL的变量被单引号包含起来,SQL注入的时候,黑客面临的首要问题是必须要先闭合前面的单引号,这样才能使后面的语句作为SQL执行,并且还要注释掉原SQL语句中的后面的单引号,这样才可以成功注入,由于代码里使用了addslashes函数,黑客的攻击会无从下手,但第二句没有用引号包含变量,那黑客也不用考虑去闭合、注释,所以即便同样采用addslashes转义,也还是存在SQL攻击漏洞。