欢迎各位兄弟 发布技术文章

这里的技术是共享的

You are here

mysql语句转义,sql特殊字符转义(sql防注入)

shiping1 的头像
我的过滤方法 #号好像可以去掉
function safe_func($str){
    $vowels = array("\\","#","$","%","^","&","*",'<','>');
    $str = str_replace($vowels, "", $str);
    empty($str) && $str='';
    return $str;
}

function doneSearch($keywords,$columnName){
    $whereSql = " and (";
    $keywords = preg_replace('/\s(?=\s)/', '', trim($keywords));
    $vowels = array("/", "\\", "'", "\"","!","@","#","$","%","^","&","*");
    $keywords = str_replace($vowels, "", $keywords);
    $keywords = explode(' ', $keywords);
    foreach($keywords as $keyword){
        $whereSql .= " $columnName like '%".$keyword."%' or";
    }
    $whereSql=substr($whereSql,0,strlen($whereSql)-2);
    $whereSql .=" )";
    return $whereSql;
}


在sql防注入方法我们是说天天都在想各种办法,前段时间公司数据库中存在大量的注入代码,后来发使用了php mysql_real_escape_string 和 mysql_escape_string但怎么还是有问题呢,下面我来分析一下。
 

具体方法

当sql where 条件等于一串特殊符号时候 就容易报错,切断,甚至不执行,或者造成数据库危险。
下面我们简单测试下
创建测试数据

 代码如下复制代码

DROP TABLE IF EXISTS `user`; 
CREATE TABLE `user` ( 
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
  `name` varchar(255) DEFAULT NULL, 
  PRIMARY KEY (`id`) 
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; 
  
INSERT INTO `user` VALUES ('1', ''\\'''\\\'');

如果我们通过这样的sql语句查询,是查不到的

 代码如下复制代码

select * from user where name = "'\'''\'"

必须要经过转义后才能查询,这样才能查询到结果

 代码如下复制代码

select * from user where name = "'\\'''\\\'"

有些人可能会想到用模糊查询比如like,但并不是一个很好的解决方案,导致查询不准确

那我们在执行sql之前要进行转义
但是 mysql_real_escape_string 和 mysql_escape_string 这样的转移函数 也并不是所有时候都靠谱。
这里我写了个php函数

 代码如下复制代码

function escape($sql_str) { 
    $search = array('\', '/', '"', "'", '|', '-', ';', '[', ']');  
    $replace = array('\\', '\/', '\"', "\'", '\|', '\-', '\;', '\[', '\]'); 
    return str_replace($search, $replace, $sql_str); 
}

在执行sql前进行一次特殊符号转义即可

 代码如下复制代码

$sql = escape($sql);

 
另外对于php手册中get_magic_quotes_gpc的举例:

 代码如下复制代码

if (!get_magic_quotes_gpc()) {
$lastname = addslashes($_POST[‘lastname’]);
} else {
$lastname = $_POST[‘lastname’];
}

语句有四大句:select 、update、delete、insert,那么我们如果在我们提交的数据中进行过滤是不是能够避免这些问题呢?
于是我们使用正则就构建如下函数:

PHP代码

 代码如下复制代码
    <?php           
    function inject_check($sql_str)     
    {     
    return eregi('select|insert|update|delete|'|     
    function verify_id($id=null)     
    {     
    if (!$id) { exit('没有提交参数!'); } // 是否为空判断     
    elseif (inject_check($id)) { exit('提交的参数非法!'); } // 注射判断     
    elseif (!is_numeric($id)) { exit('提交的参数非法!'); } // 数字判断     
    $id = intval($id); // 整型化          
    return $id;     
    }     
    ?>

呵呵,那么我们就能够进行校验了,于是我们上面的程序代码就变成了下面的:

PHP代码     

 代码如下复制代码
    <?php     
    if (inject_check($_GET['id']))     
    {     
    exit('你提交的数据非法,请检查后重新提交!');     
    }     
    else     
    {     
    $id = verify_id($_GET['id']); // 这里引用了我们的过滤函数,对$id进行过滤     
    echo '提交的数据合法,请继续!';     
    }     
    ?>

但是我们有没有考虑过post提交的数据,大批量的数据呢?

比如一些字符可能会对数据库造成危害,比如 ' _ ', ' %',这些字符都有特殊意义,那么我们如果进行控制呢?还有一点,就是当我们的php.ini里面的magic_quotes_gpc = off的时候,那么提交的不符合数据库规则的数据都是不会自动在前面加' '的,那么我们要控制这些问题,于是构建如下函数:
PHP代码      

 代码如下复制代码
<?php         
    function str_check( $str )     
    {     
    if (!get_magic_quotes_gpc()) // 判断magic_quotes_gpc是否打开     
    {     
    $str = addslashes($str); // 进行过滤     
    }     
    $str = str_replace("_", "_", $str); // 把 '_'过滤掉     
    $str = str_replace("%", "%", $str); // 把' % '过滤掉     
         
    return $str;     
    }     
    ?>

   

这样你只要再对php.ini与服务器进行安全配置了。

来自 http://www.111cn.net/database/mysql/50375.htm

普通分类: