防止SQL注入
看韩顺平老师 数据库编程陷阱 视频讲座 笔记
--------------------------------------------------
SQL注入:
攻击:
$sql = "SELECT * FROM users WHERE username='$user' and passwd='$ps'";
万能用户名:
$user=bb' union select * from user (limit 1 或者 order by 之类的)/*
此时 SQL语句为
SELECT * FROM users WHERE
username='bb' union select * from users/*' and passwd='$ps'
注: /* 表示后面的sql语句不执行 union 后面一定有值出现,所以此sql会有返回值
万能密码:
$pw=bb' or 1=1 或者 $pw = bb' union select * from user
如果PHP中书写sql语句时,变量值没有用单引号引起来,mysql会将变量值当成数值类型,很危险
防止:
1. 服务器
设置php.ini
把magic_quote_gpc设置为on(对单引号进行转译),display_errors设为off。
此时,原来的万能用户名和万能密码已无效,但还是能注入,因为 char(96)对应的是单引号,使用 char(96) 一样能注入
2.代码
方案 (1)
密码比对: 通过用户输入的用户名查询数据库,如果得到密码,再与用户输入的密码相比对,如果相等,则正确
方案(2)
使用PDO (PHP Data Object)
<?php //1.初始化一个PDO对象 $dsn='mysql:host=localhost;port=3306;dbname=text'; $user='root'; $pw='root'; $myPDO = new PDO($dsn,$user,$pw); //2.设置编码 $myPDO->exec("set name utf8"); //3.预处理sql $sql = 'select * from users where username=? and passwd=?'; $pdoStatment=$myPDO->prepare($sql); //4. $pdoStatment->execute(array($username,$passwd)); //5. $res=$pdoStatment->fetch(); if(empty($res)) { //错误 } ?>
===============================================================
另外一种 是用 mysql_real_escape_string
预防数据库攻击的正确做法:
<?php function check_input($value) { // 去除斜杠 if (get_magic_quotes_gpc()) { $value = stripslashes($value); } // 如果不是数字则加引号 if (!is_numeric($value)) { $value = "'" . mysql_real_escape_string($value) . "'"; } return $value; } $con = mysql_connect("localhost", "hello", "321"); if (!$con) { die('Could not connect: ' . mysql_error()); } // 进行安全的 SQL $user = check_input($_POST['user']); $pwd = check_input($_POST['pwd']); $sql = "SELECT * FROM users WHERE user=$user AND password=$pwd"; mysql_query($sql); mysql_close($con); ?>