sql注入风险,你有吗?

C#

浏览数:213

2019-8-30

溢+项目提测后,QA反馈的安全报告里出现了sql盲注风险和sql注入漏洞。
经分析,溢+调用支付中心,而支付中心的DAL用ADO.NET实现,在对请求数据进行持久化时,当时的工程师是这么拼的insert语句:

string GetInsertSqlStr(PayApplyDTO entity)
{
    string format = @"
INSERT dbo.T_PayApply
( systemId ,
    businessCode ,
    platform ,
    plattype ,
    paySource ,
    bankCode ,
    payMoney ,
    backAddress ,
    returnUrl ,
    .....
)
VALUES  ( {0} , -- systemId - int
    {1} , -- businessCode - int
    {2} , -- platform - int
    {3} , -- plattype - int
    '{4}' , -- paySource - varchar(50)
    '{5}' , -- bankCode - varchar(50)
    {6} , -- payMoney - decimal
    '{7}' , -- backAddress - varchar(500)
    '{8}' , -- returnUrl - varchar(500)
    .....
)";
    string insertSql = string.Format(format,
        (int)entity.BusinessSystemId, (int)entity.BusinessCode, (int)entity.ThirdPayPlatform, (int)entity.PayType,
        entity.PaySource, entity.BankCode, entity.PayMoney,
        entity.BackAddress, entity.ReturnUrl,
        ...
        );
    return insertSql;
}

很显然,当字符串参数里包含’时,而程序未对其转义,就会报SQLException。这个漏洞显然必须要补掉,要不然我们的系统太low了。

修复后的版本:

把上面的是string类型的属性做下处理,将’转义为”:

string insertSql = string.Format(format,
    (int)entity.BusinessSystemId, (int)entity.BusinessCode, (int)entity.ThirdPayPlatform, (int)entity.PayType,
    entity.PaySource, entity.BankCode.Replace("'","''"), entity.PayMoney,
    entity.BackAddress.Replace("'", "''"), entity.ReturnUrl.Replace("'", "''"),
    ...
    );
return insertSql;

上面的修复未免草率,这不,禁不起测试,运行单元测试时用例抛出了System.NullReferenceException。 最后,还是改成用传递SqlParamters参数的形式来持久化吧。

public static int Add(PayApplyDTO entity)
{
    string cmdText = @"
INSERT dbo.T_PayApply
( systemId ,
    businessCode ,
    platform ,
    plattype ,
    paySource ,
    bankCode ,
    payMoney ,
    backAddress ,
    returnUrl ,
    ...
)
VALUES  ( @systemId ,
    @businessCode , 
    @platform , 
    @plattype , 
    @paySource , 
    @bankCode , 
    @payMoney , 
    @backAddress ,
    @returnUrl ,
    ... 
)";

    List<SqlParameter> paramList = new List<SqlParameter>()
{
    new SqlParameter("@systemId",entity.BusinessSystemId),//enum本身是int值,所以不需要.GetHashCode()了
    new SqlParameter("@businessCode",entity.BusinessCode),
    new SqlParameter("@platform",entity.ThirdPayPlatform),
    new SqlParameter("@plattype",entity.PayType),
    new SqlParameter("@paySource",entity.PaySource),
    new SqlParameter("@bankCode",entity.BankCode??""),
    new SqlParameter("@payMoney",entity.PayMoney),
    new SqlParameter("@backAddress", entity.BackAddress??""),
    new SqlParameter("@returnUrl",entity.ReturnUrl??""),
    ...
};
    int i = SqlHelper.ExecuteNonQuery(
        ConfigFile.PayCenterConnection,
        System.Data.CommandType.Text,
        cmdText,
        paramList.ToArray());
    return i;
}

【结语】真是不测不知道呀! 上面的拼接sql还会带来很多风险:

  1. 可能会查看、修改或删除数据库条目和表;
  2. 可能会窃取诸如用户名和密码等未经加密即发送了的用户登录信息

大家一定要抛弃这种拼接sql的方式。

【附】非常专业的安全扫描报告截图:

1.png
2.png
3.png
4.png
sql盲注.png
sql注入.png
发现数据库错误模式.png

作者:buguge