圣诞节临近下班时收到一封安全审核邮件, 大概内容是说存在SQL注入漏洞需要紧急修复(WTF?), 好吧, 圣诞计划泡汤了, 开始修复漏洞吧。
引发SQL注入漏洞的原因
当谈起Web安全时我们最常听到的关键词就是: SQL注入(SQL Injection), 那什么是SQL注入?
SQL注入的漏洞是指: 未经检查或者未经充分检查的用户输入数据,意外变成了代码被执行 。
再来看一下代码中哪里有该漏洞: 因为历史原因, 执行的SQL是存在数据库中的, 每次查询时会将存在数据库里的SQL语句与用户传递的参数进行拼接, 然后发送给数据库引擎执行, 举个例子:
// 用户查询参数
const query = {
pageSize: 10
}
let sqlStatement = `select * from users limit {
{pageSize}}`
sqlStatement = sqlStatement.replace(/{
{(w+)}}/, value=>{
return query[value.slice(2, -2)] // 将上述sql中limit替换成10
})
await client.query(sqlStatement)
从上面的代码中我们可以发现: 并没有对用户的数据进行充分的检查, 因此上述代码是存在SQL注入风险的!
攻击者可以修改pageSize
为很大, 如果数据库中的数据很多的话, 连续发起这样的请求会导致数据库查询阻塞, 其他用户得不到响应。
再来看另一处代码
const name = "' or 1 =1--max '"
let sqlStatement = `select * from users where name= '${name}'`
await client.query(sqlStatement)
程序中依然没有对用户的数据进行校验, 直接将用户传入的name
拼接到SQL语句中并发起查询。
造成的结果是: 本来期望的是根据用户名查询某个用户的信息, 被攻击者通过传入单引号将原SQL语句where
条件中的name闭合如name=''
成为一个假条件, 然后通过or 1 = 1
创造一个永远执行的真条件, 最后通过注释--
将后面的语句注释掉以防报错。
原来期望的结果是查询指定用户信息: