• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

SQL注入如何防范?

php 搞代码 4年前 (2022-01-23) 20次浏览 已收录 0个评论
文章目录[隐藏]
  1. 昨天晚上已经11点多的时间,一个朋友突然找我说她们公司的网站的漏洞被提交到wooyun了。(然后就跟妹子大概了解了一下漏洞的情况 PS:妹子是php程序员)

  2. wooyun上提交了两处漏洞,1处是SQL注入 (经过了解,她们公司的用的框架是11年的老框架,还是mysql_query()这些老的mysql函数) 另一处就是cookie的问题,妹子把用户的uid,等敏感信息都写进cookie了,2333。然后php处理业务逻辑的uid也是从cookie里面拿的,233333 (导致修改cookie后可以伪装成任意用户)

  3. 我给她说了SQL注入的解决方案(第一种治标不治本的,用正则匹配SQL语句,过滤危险字符,关键字,转义符号,第二种方案,弃用mysql老函数,用PDO或者mysqli)(cookie那个地方的漏洞,我建议她把uid等敏感信息存在session里面,然后把sessionID加密后放在cookie里面)

  4. 妹子最后说,她大概听懂了.改公司框架的mysql驱动是不太现实的,公司不会让她改的,那就只好用正则匹配SQL语句,过滤非法字符串了!

  5. 我就去网上找了一些SQL语句过滤的函数 号称很好用的SQL过滤函数
    知乎大婶们的回答

想跟大家讨论一下 SQL注入防范的姿势 大家有没有比较好用的SQL注入 过滤SQL语句的函数,分享一下,谢谢!

+本文来源gao!%daima.com搞$代*!码9网(

搞gaodaima代码

回复内容:

  1. 昨天晚上已经11点多的时间,一个朋友突然找我说她们公司的网站的漏洞被提交到wooyun了。(然后就跟妹子大概了解了一下漏洞的情况 PS:妹子是php程序员)

  2. wooyun上提交了两处漏洞,1处是SQL注入 (经过了解,她们公司的用的框架是11年的老框架,还是mysql_query()这些老的mysql函数) 另一处就是cookie的问题,妹子把用户的uid,等敏感信息都写进cookie了,2333。然后php处理业务逻辑的uid也是从cookie里面拿的,233333 (导致修改cookie后可以伪装成任意用户)

  3. 我给她说了SQL注入的解决方案(第一种治标不治本的,用正则匹配SQL语句,过滤危险字符,关键字,转义符号,第二种方案,弃用mysql老函数,用PDO或者mysqli)(cookie那个地方的漏洞,我建议她把uid等敏感信息存在session里面,然后把sessionID加密后放在cookie里面)

  4. 妹子最后说,她大概听懂了.改公司框架的mysql驱动是不太现实的,公司不会让她改的,那就只好用正则匹配SQL语句,过滤非法字符串了!

  5. 我就去网上找了一些SQL语句过滤的函数 号称很好用的SQL过滤函数
    知乎大婶们的回答

想跟大家讨论一下 SQL注入防范的姿势 大家有没有比较好用的SQL注入 过滤SQL语句的函数,分享一下,谢谢!

为什么不用预处理??????????
为什么不用预处理??????????
为什么不用预处理??????????
重要的事情说三遍!
SQL注入已经是上个世纪的事情了!
如果你不想重新编写,可以使用我简单封装的现成PHP类,请选择其中一个使用。
(我发现代码有我的项目的某些痕迹,所以删掉了无关代码)
MySQLi版:

<code><?phpclass DB{    var $Sql;    var $Fetch;    var $Param = array();        public function __construct($Sql, $Fetch, $Param = array())    {        $this->sql = $Sql;        $this->fetch = $Fetch;        $this->param = $Param;        //数据库信息存放在配置文件里面,请自行修改成正确的路径和值        require($_SERVER['DOCUMENT_ROOT'] . '/configs/config.inc.php');        $this->dbhost = & $DBHost;        $this->dbuser = & $DBUser;        $this->dbpw = & $DBPassword;        $this->dbname = & $DBName;    }        public function Query()    {        $Mysqli = new mysqli($this->dbhost, $this->dbuser, $this->dbpw, $this->dbname);        if ($Mysqli->connect_errno)        {            echo '无法连接数据库';            return false;        }        $Mysqli->query('SET NAMES UTF8');        $Mysqli->begin_transaction(MYSQLI_TRANS_START_READ_ONLY);        $Stmt = $Mysqli->stmt_init();        $Stmt->prepare($this->sql);        if (count($this->param) > 0)        {            $Type = '';            for ($i = 0; $i param); $i++)            {                if (is_double($this->param[$i]))                {                    $Type .= 'd';                }                else if (is_int($this->param[$i]))                {                    $Type .= 'i';                }                else if (is_string($this->param[$i]))                {                    $Type .= 's';                }                else                {                    $Type .= 'b';                }            }            $RefArg = array($Type);            for ($I = 0; $I param); $I++)            {                $RefArg[] = & $this->param[$I];            }            call_user_func_array(array($Stmt, 'bind_param'), $RefArg);        }        if (!$Stmt->execute())        {            echo '读取数据库时发生错误:'. $Stmt->error;            echo $this->sql;            print_r($this->param);            $Mysqli->rollback();                        return false;        }        $Mysqli->commit();        if (strtolower(substr($this->sql, 0, 6)) == 'select')        {            $this->res = $Stmt->get_result();            $Stmt->free_result();            return $this->GetRes();        }        else        {            $Stmt->free_result();            return true;        }    }        public function GetRes()    {        switch(strtolower($this->fetch))        {            case 'all':                $row = $this->res->fetch_all();                break;            case 'array':                $row = $this->res->fetch_array();                break;            case 'assoc':                $row = $this->res->fetch_assoc();                break;            case 'field':                $row = $this->res->fetch_field();                break;            case 'row':                $row = $this->res->fetch_row();                break;            default:                echo 'Please select a row return mode.';                exit;        }        return $row;    }        public function NumRow()    {        if (isset($this->res))        {            return $this->res->num_rows;        }        else        {            return false;        }    }}?></code>

PDO_MYSQL版:

<code><?phpclass DB{    var $SQL;    var $Fetch;    var $Param = array();        public function __construct($SQL, $Fetch, $Param)    {        //数据库信息存放在配置文件里面,请自行修改成正确的路径和值        require($_SERVER['DOCUMENT_ROOT'] . '/configs/config.inc.php');        $this->DBHost = & $DBHost;        $this->DBUser = & $DBUser;        $this->DBPW = & $DBPassword;        $this->DBName = & $DBName;        $this->SQL = $SQL;        $this->Fetch = $Fetch;        $this->Param = $Param;    }        public function Query()    {        try        {            $Pdo = new PDO('mysql:host=' . $this->DBHost . ';dbname=' . $this->DBName, $this->DBUser, $this->DBPW);            $Pdo->query('SET NAMES UTF8');            $Pdo->beginTransaction();            $Stmt = $Pdo->prepare($this->SQL);            if (count($this->Param) > 0)            {                for ($I = 0; $I Param); $I++)                {                    $Stmt->bindParam($I + 1, $this->Param[$I]);                }            }            if (!$Stmt->execute())            {                echo '读取数据库时发生错误:' . $Stmt->errorinfo()[2];                $Pdo->rollback();                return false;            }            $Pdo->commit();            if (strtolower(substr($this->SQL, 0, 6)) == 'select' || strtolower(substr($this->SQL, 0, 4)) == 'desc')            {                $this->Res = $Stmt;                return $this->GetRes();            }            else            {                return true;            }        }        catch (PDOException $e)        {            echo '无法连接数据库';            $Pdo->rollback();            return false;        }    }        public function GetRes()    {        switch(strtolower($this->Fetch))        {            case 'all':                $Row = $this->Res->fetchAll(PDO::FETCH_ASSOC);                break;            case 'array':                $Row = $this->Res->fetch(PDO::FETCH_BOTH);                break;            case 'assoc':            case 'field':                $Row = $this->Res->fetch(PDO::FETCH_ASSOC);                break;            case 'row':                $Row = $this->Res->fetch(PDO::FETCH_NUM);                break;            default:                echo 'Please select a row return mode.';                exit;        }        return $Row;    }        public function NumRow()    {        if (isset($this->Res))        {            return $this->Res->num_rows;        }        else        {            return false;        }    }}?></code>

使用方法:

<code>$DB = new DB(SQL语句, 结果集方式, array(要绑定的参数);$DB->Query();</code>

注意!!!SQL语句用 ? 代替要查询的参数!!!SQL注入漏洞是因为SQL语句拼接了变量!!!
PS:如果不能改框架,那还是洗洗睡吧,时间只会淘汰墨守成规的人和过时的技术。
别指望正则过滤SQL语句能彻底杜绝SQL注入,PHP7放弃MySQL扩展的原因就是因为这个扩展有安全漏洞!

之前已经写过类似的总结就不照搬了,常用Web安全的防范建议都有(稍微有些遗漏的后续再继续补充),可参考:PHP安全编码

简单理解就是能用PDO预处理用PDO,不能用PDO就用addslashes顶上。

PHP 系统函数有这个 addslashes() 可以试试

如果不用正则过滤,可以考虑转义。

其实防御SQL注入的本质就是对GPC外来变量进行敏感字符进行相关的转义,或者拦截。可以在框架入口文件或路由解析类中对GPC进行预处理好后给后面的业务使用,这比较容易实现还动起来好实现。至于cookie,一改大改,用一些加密方式检验cookie吧,加密密钥可以放在session。

嗯,这个事情的姿势应该是这样的:

  1. 外面加一些安全服务,例如加速乐之类的(我们用加速乐,响应一般多了100毫秒,偶尔有波动,安全性也只是基础吧,一些post一些xss都拦截不到)

  2. 服务器装web应用防火墙软件

  3. 评估时间,慢慢迁移到pdo,查询都用参数绑定(我个人觉得不是不让改,而是需要时间来安排这个)

由于PHP>=5.5已经废除了mysql_*,所以为了兼容性考虑应该抽空把框架重构了。

试试 http://www.oneasp.com


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:SQL注入如何防范?

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址