设为首页 收藏本站
查看: 2907|回复: 0

[经验分享] 浅析SQL注入

[复制链接]

尚未签到

发表于 2018-10-22 13:31:05 | 显示全部楼层 |阅读模式
  一、SQL注入原因
  SQL漏洞出现的原因大家都应该知道了,还是哪一句熟悉的话:用户输入的数据被SQL解释器执行。
  SQL注入的原因和分类都是很简单的,难的是对可能出现SQL注入的地方进行细致拼接测试。
  二、SQL注入漏洞分类
  2.1 数字型注入
  数字型注入是最初级的注入,常出现在ASP、PHP等弱类型语言之中,因为弱类型语言会自动推导变量类型。
  示例:
http://localhost/sql.php?id=8 AND 1=1
  上述的示例多是进行自动化的“盲注”。在后台执行的SQL为:SELECT * FROM test where>  PS:盲注是在服务器没错误回显时完成的注入***。服务器没有错误回显,对于***者而言缺少了非常重要的“调式信息”,所以***者需要找一个一个方法来验证注入的SQL是否已经执行。盲注是根据多给条件进行判断,如果页面没有出错则表示存在注入点。
  2.2 字符型注入
  字符型与数字型的最大区别在于,前者一般要是有单引号来闭合,后者不需要。
  示例:
http://localhost/sql.php?name=admin and 1=1  这样是无效,因为后端的SQL为:
SELECT * FROM test where name = 'admin and 1=1'  如果改为:
http://localhost/sql.php?name='admin' and 1=1  此时后端SQL:SELECT * FROM test where name = 'admin' and 1=1
  该类型的注入是公司扫雷重点照顾对象,大家可以看看扫雷的日志多是各种拼接的SQL。
  总结一下,字符型注入还可以细分出一下不同的类型,如POST注入、Cookie注入、搜索注入、BASE64注入。。。本质上还是字符型注入,数字型注入也是可以说是特殊的字符型注入。
  因为公司已经存在强大的扫雷工具了所以在此就不再介绍别的工具了。
  三、防止SQL注入
  防SQL注入总结就一句话:有输入的地方就有存在SQL的风险。
  3.1 统一输入处理,严格类型判断
  金融知心的大多数的项目使用的PHP,弱类型的语言没有强制要求处理数据类型。但防御数字型注入还是很简单的,一个函数 intval ($param);就可以。
$param  = intval ($param);  3.2 特殊字符转义
  对于字符类型,他们都是string,所以很难判断输入的是否存在恶意***。现在通用的防御方法就是对特殊符号进行转义。
$paramStr = mysql_real_escape_string($paramStr);  最好是框架或者类库在底层提供了而不需要开发人员在业务代码中混合在一起了。
  3.3 使用预编译
  PHP的PDO也提供了预编译的功能了,只是在我们金融项目中很少使用,因为使用起来不算方便。
  3.4 使用框架
  在PHP中很多框架都是提供了好用而且安全的数据库操作类库了,知心普遍使用的Topaz使用的mysqli而且SQL语句都是拼接的,所以最近扫雷就会出现类似SQL注入的出现。
  3.5 使用存储过程
  不建议使用了,虽然使用存储过程可以提高执行效率,因为使用存储过程需要精通SQL,而且不方便经常变更和会出现移植问题。
  四、举例说明
  最近扫雷经常出现提示有SQL注入的情况,也有的是误报的。也执行到了数据库,仅是此次组装的SQL是错误的(谁知道如果是人工构造时候会不会出现真的注入了呢)。为了安全的考虑,是不允许不符合格式的SQL进入数据库执行的,不论这个语句是否可以真的注入。有可能是SQL漏洞被发觉的是因为我们异常错误的处理不当,不应该再给前端返回后端数据库异常的信息。
  出现多次扫雷问题,主要是对参数校验不足和库类使用的方式造成。
  如我们看一段代码:
public static function getLoanArticle ($input, array $arrIds, $bsPriceList, $cate, $nestId = 22){  
        $rtn = array();
  

  
        $db = Env::getDB('fnbiz');
  

  
        $ids = array();
  
        foreach ($arrIds as $id)
  
        {
  
            $id = $db->real_escape($id);
  
            if (!empty($id)) {
  
                $ids[] = $id;
  
            }
  
        }
  

  
        if (empty($ids))
  
        {
  
            Env::getLogger()->warning('DB', 'empty parameter arrIds');
  
            return $rtn;
  
        }
  

  
        //TODO delete note
  
        $tbl = 'knowledge_loan_article';
  
        $strId = implode(',', $ids);
  
         //TODO: select count
  
        $sql = "SELECT articleId, keywords, source, title, brief, lastUpdateTime, articleLink, content, ext FROM $tbl WHERE articleId IN ($strId) AND isDelete = 0 AND nestId = $nestId";
  
        Env::getLogger()->trace(
  
                "get articel from db [sql:$sql] [articleId count:" . count($ids) .
  
                         "]");
  

  
        //$rs = $db->fetchAll($sql);
  
        ...  ...
  为什么写成这样SQL拼接的方式,是因为Topaz要求这么写的,但在这个SQL语句之前没有对$id进行校验就会有SQL注入。很庆幸,扫雷发现并进行处理了。参数的校验包含了参数类型和参数长度等多种属性的校验。注:安全与成本是成反比的,注意平衡!
  使用UI的一段代码来看看:
public static function getByProductIds(array $arrIds) {  if (empty($arrIds)) {
  Env::getLogger()->warning('DB', 'empty parameter arrIds');
  
            return array() ;
  }
  $db = Env::getDB('fnbiz');
  
        $ids = array() ;
  
        foreach($arrIds as $id ){
  
            $ids[] = $db->real_escape($id) ;
  
        }
  

  
        $strIds = implode(",",$ids) ;
  
        $tb = "product";
  
        $sql = "SELECT * FROM `$tb` WHERE productId IN ( $strIds )";
  
        $res= $db->fetchAll($sql) ;
  

  
        $mapRes = array() ;
  
        foreach($res as $item){
  
            $mapRes[$item['productId']] = $item;// json_decode($item['productInfo'], true) ;
  
        }
  
        $rtn = array() ;
  
        foreach($ids as $id){
  
            if( !isset($mapRes[$id]) ) {
  
                Env::getLogger()->warning('DB',"product $id not found in db") ;
  
            }else{
  
                 $rtn[$id] = $mapRes[$id] ;
  
            }
  
        }
  
        return $rtn ;
  
    }
  可以发现参数的转义已经和业务的代码混合在一起了,每一个人的代码风格都不一样这并不可怕,可怕的是每一个人开发人员的安全意识都不一样。有的有参数的转义有的却没有!
  建议使用PDO库类替换Topaz并统一语法。



运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-625049-1-1.html 上篇帖子: mysql导入sql文件报错,“This function has none of DETERMINISTIC”,解决办法 下篇帖子: 利用SQL更改数据库名称
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表