做ctf的题时刚好做到要用sql约束攻击的题,赶紧去看看别人的文章学习一下这种攻击
题目大致上是一个登陆界面和一个注册界面,需要我们用管理员的身份登陆才能拿到flag值
登陆页面:
1 |
|
注册页面:
1 |
|
看似对用户的输入进行了转义的过滤,能防止sql注入,但是我们还是有办法能登录任意已存在的账号
下面演示具体过程:
首先先创建一个数据库test,再test库下建立users表,里面的列名为username和password
注意这里对用户名和密码字符串长度限制最大为15位
接着创建一个管理员身份账户,用户名为admin,密码为123456
然后我们以攻击者的身份要以管理员身份登陆,首先注册用户,用户名为admin+若干个空格+1,这里空格在10个以上,原因后面会提到
这时候我们注册页面首先会进行是否存在注册的用户名的查询
没有查询到结果,所以成功绕过了查询,这里就可以解释一下为什么要在末尾加1,其实1是随便加的,任何字母数字都可以,原因是mysql进行select查询时,会忽略末尾的若干个空格,例如我们执行sql语句:”select username,password from users where username=’admin ‘ “
结果跟没有加空格是一样的,那么我们要绕过是否存在用户名的查询,如果只在末尾加空格,是会被检测到存在admin用户,所以我们在末尾加个任意字符,就可以绕过这个查询
那么为什么空格要在10个以上呢,我们继续看下去
下面注册页面执行的是insert语句
可见成功的注册了
我们再来查询一下”select username,password from users where username=’admin’ “
这时候发现有两个admin用户,但是这两个用户其实是不一样的,因为我们之前说过了,mysql在select查询时会将末尾空格忽略,而mysql在insert操作时不会忽略空格,也就是说我们以攻击者身份注册的用户名’admin 1’中的空格不会被省略,这里肯定就有疑问,那么1跑哪里去了,答案很简单,我们之前就已经限制了username的最大长度为15,这里空格在10个以上,加上admin的5个长度,所以长度在15以上的字符就被截断了,之前的才会被写入数据库,那么实际上写入数据库的就是admin+10个空格,但是我们登录查询select语句会自动忽略空格,所以将后面没有空格的admin和加了10个空格的admin都查询了出来
也就是说,我们在登录页面输入用户名为admin,密码为aaa,就会有查询结果,也就以管理员身份登录成功了
当然我们查询到的并不是真正的admin用户,但是服务器只检测有没有查询结果,有则认为我们登录成功
那么防御手段也挺简单就能想到,我们只需要对查询的结果进行检查,检查查询到的用户密码是不是之前设置的管理员密码,就可以防御了
最后附上参考链接:https://www.cnblogs.com/ECJTUACM-873284962/p/8977983.html