sql注入
如果SQL当中,存在浏览器端请求的数据(用户数据),用户通过特殊的形式,对我们的sql语句产生影响,称为sql注入(SQL Injection)。
$sql = "SELECT * FROM `p34_admin` WHERE admin_name='$admin_name' and admin_pass=md5('$admin_pass')";
例如上面的语句中,让admin_name=’or 1 or’,那么WHERE表达式恒成立。
tip:不仅在登录时,可以被注入,任何用户数据参与执行,都可以被注入。
预防
- 业务逻辑上预防(使用白名单,将用户数据限制在合理范围之内):
- 通过限定数据格式(比如用户名仅由字母、数字、下划线和特定字符组成),如果检测不安组要求,则直接不予参与SQL注入问题。
- 通过限定数类型(比如,ID需要整形的数据,将用户床底请求数据强制转化成整型),进行避免。比如防止(DELETE FROM match where m_id=$_GET[‘m_id’]变为$GET[‘m_id’]=’5 or 1’#)。可以在后者前面加上(int)进行强制转换。
- 通过特殊数据转义
- 通过函数:PHP字符串函数addslashes(),Mysql提供的转义函数:mysql_real_escape_string(待转义字符串,连接)。
tip:PHP中魔术引号(magic quotes),PHP中自动为请求数据(GET,POST)增加转义的一种防止SQL注入机制。
本文示例代码:
dao层:
class MySQLDB{
/**
* avoid SQL Injection
* @param $data string
* @return string
*/
public function escapeString($data) {
return "'" . mysql_real_escape_string($data, $this->resourc) . "'";
}
}
model代码:
class AdminModel{
public function check($admin_name, $admin_pass) {
//method1
//$admin_name = addslashes($admin_name);
//$admin_psss = addslashes($admin_pass);
//method2
$admin_name_escape = $this->_dao->escapeString($admin_name);
$admin_pass_escape = $this->_dao->escapeString($admin_pass);
$sql = "SELECT * FROM `p34_admin` WHERE admin_name=$admin_name_escape
and admin_pass=md5($admin_pass_escape)";
$row = $this->_dao->getRow($sql);
return (bool)$row;
}
}