溢+项目提测后,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 paramList = new List()
{
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还会带来很多风险:
- 可能会查看、修改或删除数据库条目和表;
- 可能会窃取诸如用户名和密码等未经加密即发送了的用户登录信息
大家一定要抛弃这种拼接sql的方式。
【附】非常专业的安全扫描报告截图: