zoukankan      html  css  js  c++  java
  • WEB安全实战(一)SQL盲注


    前言


    好长时间没有写过东西了,不是不想写,仅仅只是是一直静不下心来写点东西。当然,拖了这么长的时间,也总该写点什么的。近期刚刚上手安全方面的东西,作为一个菜鸟,也本着学习的目的,就谈谈近期接触到的安全方面的问题吧。


    背景


    既然提到了背景,那我们就简单的带一下,近期互联网上爆出了各种惊人的事件、各种门、各种照的,归根结底,都是网络安全出的问题,有的是网络被别人监控了,广大群众的生活工作都处在人家的眼皮底下,一举一动都逃不出人家的“法眼”;还有的是一些商家的server被黑,username、password被盗,信用卡被盗刷,私人文件泄漏等等。这些都是安全出了问题。当然,强如苹果那样的大公司,都会出现这种事件,更别说普普通通的小公司了。


    问题


    SQL盲注,这个词我想大家应该不怎么陌生。假设说实在不知道的话,那么“SQL注入”你一定听说过。这两个词似乎有什么联系,长的跟双胞胎似的?没错,SQL盲注是一种Web系统的安全漏洞,并且是比較严重的那种,它是SQL注入的当中一种方式。也就是说,SQL注入存在非常多种方式,而SQL盲注就是当中的一种。

    在安全级别中,SQL盲注是一种威胁程度非常高的安全漏洞,通过这样的方式,能够入侵服务提供商的server数据库,从而窃取、篡改、甚至是删除用户数据。当然,在正常情况下,这些都是不同意发生的,在系统上线之前,这些都是经过严格检測的,并且数据库中的数据也都是不定向的加密,不会暴露用户数据的。


    技术描写叙述


    採用IBM的AppScan,对系统进行測试,因为在早期的开发中,採用了非常多不规范的代码,因此,这次的測试可谓是“大丰收”,站点安全方面的漏洞暴露无疑,而在安全測试报告中,最严重的漏洞就非SQL盲注莫属了。



    解决方式


    SQL盲注的危害大家也都清楚了,那么该怎样防止这样的情况的发生呢?说简单点,就是对请求进行过滤,对參数进行验证,对非法字符进行拦截替换,清理用户输入的危急字符,保证sql可以在数据库中正确的编译和运行。这就是解决的简单思路。只是,今天我想要说的不是这些,而是在巨人的肩膀上发现问题,解决这个问题。

    MyBatis,一款相当好用的持久化框架,有了它之后,我们省下了非常多的时间、非常多的反复性工作。同一时候,也要意识到,在框架的运用中,也是存在一些安全问题的,当然,框架中有的已经给出了非常好的解决方式,但有的还是须要我们自己去解决。比方这个SQL盲注的问题,MyBatis就给出了非常好的解决方式,在mapper.xml文件里使用#{name}的方式提供占位符,使得sql在数据库中编译的时候,将这些占位符替换成用户输入的正确的參数值,这样就避免了一部分的问题。

    代码例如以下

    <span style="font-family:Comic Sans MS;font-size:12px;"><?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.test.dao.TAcntMapper">
      <resultMap id="BaseResultMap" type="com.test.entity.TAcnt">
         <id column="SYS_ID" jdbcType="DECIMAL" property="sysId" />
       	 <result column="OBJ_ID" jdbcType="VARCHAR" property="objId" />
       	 <result column="OBJ_NAME" jdbcType="VARCHAR" property="objName" />
       	 <result column="OBJ_DESCRIPTION" jdbcType="VARCHAR" property="objDescription" />
       	 <result column="CREATOR" jdbcType="VARCHAR" property="creator" />
       	 <result column="CREATE_TIME" jdbcType="TIMESTAMP" property="createTime" />
       	 <result column="UPDATE_OPERATOR" jdbcType="VARCHAR" property="updateOperator" />
       	 <result column="UPDATE_TIME" jdbcType="TIMESTAMP" property="updateTime" />
       	 <result column="CLIENT_CHK_FLAG" jdbcType="DECIMAL" property="clientChkFlag" />
       	 <result column="CELL_PHONE" jdbcType="VARCHAR" property="cellPhone" />
       	 <result column="REG_EMAIL" jdbcType="VARCHAR" property="regEmail" />
       	 <result column="GENDER" jdbcType="DECIMAL" property="gender" />
       	 <result column="QQ_NO" jdbcType="VARCHAR" property="qqNo" />
       	 <result column="WEB_URL" jdbcType="VARCHAR" property="webUrl" />
       </resultMap>
     
    
      <sql id="Example_Where_Clause">
        <where>
          <foreach collection="oredCriteria" item="criteria" separator="or">
            <if test="criteria.valid">
              <trim prefix="(" prefixOverrides="and" suffix=")">
                <foreach collection="criteria.criteria" item="criterion">
                  <choose>
                    <when test="criterion.noValue">
                      and ${criterion.condition}
                    </when>
                    <when test="criterion.singleValue">
                      and ${criterion.condition} #{criterion.value}
                    </when>
                    <when test="criterion.betweenValue">
                      and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
                    </when>
                    <when test="criterion.listValue">
                      and ${criterion.condition}
                      <foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
                        #{listItem}
                      </foreach>
                    </when>
                  </choose>
                </foreach>
              </trim>
            </if>
          </foreach>
        </where>
      </sql>
      <sql id="Update_By_Example_Where_Clause">
        <where>
          <foreach collection="example.oredCriteria" item="criteria" separator="or">
            <if test="criteria.valid">
              <trim prefix="(" prefixOverrides="and" suffix=")">
                <foreach collection="criteria.criteria" item="criterion">
                  <choose>
                    <when test="criterion.noValue">
                      and ${criterion.condition}
                    </when>
                    <when test="criterion.singleValue">
                      and ${criterion.condition} #{criterion.value}
                    </when>
                    <when test="criterion.betweenValue">
                      and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
                    </when>
                    <when test="criterion.listValue">
                      and ${criterion.condition}
                      <foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
                        #{listItem}
                      </foreach>
                    </when>
                  </choose>
                </foreach>
              </trim>
            </if>
          </foreach>
        </where>
      </sql>
      <sql id="Base_Column_List">
              SYS_ID     , OBJ_ID     , OBJ_NAME     , OBJ_DESCRIPTION     , CREATOR     , CREATE_TIME     , UPDATE_OPERATOR     , UPDATE_TIME     , CLIENT_CHK_FLAG     , CELL_PHONE     , REG_EMAIL     , GENDER     , QQ_NO     , WEB_URL  </sql>
    
      <sql id="From_join">
      from   	 T_ACNT 
      </sql>
      
      <select id="selectByExample" parameterType="com.test.entity.TAcntCriteria" resultMap="BaseResultMap">
        select
        <if test="distinct">
          distinct
        </if>
        <include refid="Base_Column_List" />
        <include refid="From_join" /> 
        <if test="_parameter != null">
          <include refid="Example_Where_Clause" />
        </if>
        <if test="orderByClause != null">
          order by ${orderByClause}
        </if>
      </select>
      
      <select id="selectByPrimaryKey" parameterType="BigDecimal" resultMap="BaseResultMap">
        select 
        <include refid="Base_Column_List" />
        <include refid="From_join" /> 
        where SYS_ID = #{sysId,jdbcType=DECIMAL}
      </select>
      
      <delete id="deleteByExample" parameterType="com.test.entity.TAcntCriteria">
    
        delete from T_ACNT
        <if test="_parameter != null">
          <include refid="Example_Where_Clause" />
        </if>
      </delete>
      
      <insert id="insert" parameterType="com.test.entity.TAcnt">
              insert into T_ACNT ( OBJ_ID     , OBJ_NAME     , OBJ_DESCRIPTION     , CREATOR     , CREATE_TIME     , UPDATE_OPERATOR     , UPDATE_TIME     , CLIENT_CHK_FLAG     , CELL_PHONE     , REG_EMAIL     , GENDER     , QQ_NO     , WEB_URL )
        values (        #{objId,jdbcType=VARCHAR}      , #{objName,jdbcType=VARCHAR}      , #{objDescription,jdbcType=VARCHAR}      , #{creator,jdbcType=VARCHAR}      , #{createTime,jdbcType=TIMESTAMP}      , #{updateOperator,jdbcType=VARCHAR}      , #{updateTime,jdbcType=TIMESTAMP}      , #{clientChkFlag,jdbcType=DECIMAL}      , #{cellPhone,jdbcType=VARCHAR}      , #{regEmail,jdbcType=VARCHAR}      , #{gender,jdbcType=DECIMAL}      , #{qqNo,jdbcType=VARCHAR}      , #{webUrl,jdbcType=VARCHAR}  )
      </insert>  
      
      
      <select id="countByExample" parameterType="com.test.entity.TAcntCriteria" resultType="java.lang.Integer">
        select count(*) 
        <include refid="From_join" /> 
        <if test="_parameter != null">
          <include refid="Example_Where_Clause" />
        </if>
      </select>
      
      <update id="updateByExample" parameterType="map">
        update T_ACNT
        set				OBJ_ID = #{record.objId,jdbcType=VARCHAR} 
                   , OBJ_NAME = #{record.objName,jdbcType=VARCHAR} 
                   , OBJ_DESCRIPTION = #{record.objDescription,jdbcType=VARCHAR} 
                   , CREATOR = #{record.creator,jdbcType=VARCHAR} 
                   , CREATE_TIME = #{record.createTime,jdbcType=TIMESTAMP} 
                   , UPDATE_OPERATOR = #{record.updateOperator,jdbcType=VARCHAR} 
                   , UPDATE_TIME = #{record.updateTime,jdbcType=TIMESTAMP} 
                   , CLIENT_CHK_FLAG = #{record.clientChkFlag,jdbcType=DECIMAL} 
                   , CELL_PHONE = #{record.cellPhone,jdbcType=VARCHAR} 
                   , REG_EMAIL = #{record.regEmail,jdbcType=VARCHAR} 
                   , GENDER = #{record.gender,jdbcType=DECIMAL} 
                   , QQ_NO = #{record.qqNo,jdbcType=VARCHAR} 
                   , WEB_URL = #{record.webUrl,jdbcType=VARCHAR} 
                <if test="_parameter != null">
          <include refid="Update_By_Example_Where_Clause" />
        </if>
      </update>
      
      <update id="updateByPrimaryKeySelective" parameterType="com.test.entity.TAcnt">
        update T_ACNT
        <set>
          <if test="objId != null">
            OBJ_ID = #{objId,jdbcType=VARCHAR},
          </if>
          <if test="objName != null">
            OBJ_NAME = #{objName,jdbcType=VARCHAR},
          </if>
          <if test="objDescription != null">
            OBJ_DESCRIPTION = #{objDescription,jdbcType=VARCHAR},
          </if>
          <if test="creator != null">
            CREATOR = #{creator,jdbcType=VARCHAR},
          </if>
          <if test="createTime != null">
            CREATE_TIME = #{createTime,jdbcType=TIMESTAMP},
          </if>
          <if test="updateOperator != null">
            UPDATE_OPERATOR = #{updateOperator,jdbcType=VARCHAR},
          </if>
          <if test="updateTime != null">
            UPDATE_TIME = #{updateTime,jdbcType=TIMESTAMP},
          </if>
          <if test="clientChkFlag != null">
            CLIENT_CHK_FLAG = #{clientChkFlag,jdbcType=DECIMAL},
          </if>
          <if test="cellPhone != null">
            CELL_PHONE = #{cellPhone,jdbcType=VARCHAR},
          </if>
          <if test="regEmail != null">
            REG_EMAIL = #{regEmail,jdbcType=VARCHAR},
          </if>
          <if test="gender != null">
            GENDER = #{gender,jdbcType=DECIMAL},
          </if>
          <if test="qqNo != null">
            QQ_NO = #{qqNo,jdbcType=VARCHAR},
          </if>
          <if test="webUrl != null">
            WEB_URL = #{webUrl,jdbcType=VARCHAR},
          </if>
        </set>
        where SYS_ID = #{sysId,jdbcType=DECIMAL}
      </update>
    </mapper></span>

    当然,这不过第一步,假设你想写出一个彻底防止SQL盲注的系统。那么还是须要对用户发出的请求进行过滤,并且还要包含请求中的參数值,非常有可能包含一些危急字符,这些危急字符就是我们须要过滤并处理的问题所在。关于解决危急字符这一块,我留到后面细说,由于这涉及到非常多个漏洞,包含:XSS,CSRF等等。


    结束语


    俗话说,安全猛于虎!安全无小事!在互联网上,这些也是一样的。刚開始接触安全的我,也许说是,刚開始深入研究安全的我,正在汲取这方面的养分,通过測试出来的安全漏洞,一点一点的解决潜在的危机。这还不过个開始,兴许的日子里还有非常长的路要走,大家一起加油吧。当然,假设有什么新的感受,我也会写出来跟大家一起分享,一起进步。


  • 相关阅读:
    创建类型5-3:单例模式(Singleton Pattern)
    创建类型5-2:抽象工厂模式(Abstract Factory Pattern)
    创建类型5-1:工厂模式(Factory Pattern)
    第一章:Netty介绍
    第二章:第一个Netty程序
    第四章:Transports(传输)
    第十六章:从EventLoop取消注册和重新注册
    第十五章:选择正确的线程模型
    第十四章:实现自定义的编码解码器
    第十三章:通过UDP广播事件
  • 原文地址:https://www.cnblogs.com/zfyouxi/p/4309271.html
Copyright © 2011-2022 走看看