SQL约束攻击

 Von's Blog     2019-08-05   1228 words    & views

前言

这几天做CTF了解到SQL约束攻击的相关知识,特此写篇博客总结一下。(突然发现博客已经N长时间没有更新了)

前置知识

在SQL中执行字符串处理时,字符串末尾的空格符将会被删除。 EG: 可以看出,在图中两个SQL查询语句得出的结果是相同的。这是第一个利用的知识点。 在所有的INSERT查询中,SQL都会根据varchar(n)来限制字符串的最大长度。也就是说,如果字符串的长度大于“n”个字符的话,那么仅使用字符串的前“n”个字符。 EG: 之后,mysql将数据进行储存时会将末尾的空格全部删除,因为 mysql 在where 语句后面进行比较时,会用空格将字符长度补全成maxlength。

攻击思路

所以当我们想要进入一个后台而又不知道密码时,我们可以以’[管理员(admin)][许多空白字符]1’和一个随机密码进行注册。(注意:空格后需再跟一个或多个任意字符,防止程序在检查用户名是否已存在时匹配到目标用户),空格的长度要超过数据库字段限制的长度,让其强制截断。因为INSERT语句的截断,此时我们的用户名就为:[管理员 ],即除了后面的一串空格,我们的用户名和目标用户名一样。 如果现在搜索“admin”的话,将返回两个用户。注意,第二个用户名实际上是“admin”加上尾部的多个空格。现在,如果使用用户名“admin”和密码“88888888”登录的话,因为查询 语句将忽略后面的空格,导致攻击者能够以新申请的’admin[多个空格]’账号登陆admin账号。这就是总体的攻击思路。

CTF实战

以BUGKU一道题目为例子进行说明。题目网址 先利用约束攻击注册账号 此时我们自己的admin账号已经被插入数据库 登陆即可得到flag

限制条件

服务端没有对用户名长度进行限制。如果服务端限制了用户名长度就不能导致数据库截断,也就没有利用条件。
登陆验证的SQL语句必须是用户名和密码一起验证。如果是验证流程是先根据用户名查找出对应的密码,然后再比对密码的话,那么也不能进行利用。因为当使用admin为用户名来查询密码的话,数据库此时就会返回两条记录,而一般取第一条则是目标用户的记录,那么你传输的密码肯定是和目标用户密码匹配不上的。
验证成功后返回的必须是用户传递进来的用户名,而不是从数据库取出的用户名。因为当我们以用户admin和密码88888888登陆时,其实数据库返回的是我们自己的用户信息,而我们的用户名其实是[admin ],如果此后的业务逻辑以该用户名为准,那么就不能达到越权的目的了。

本文参考: https://www.k0rz3n.com/2017/06/03/passsignup/
https://www.freebuf.com/articles/web/124537.html
https://panda1g1.github.io/2018/05/26/mysql%20%E7%BA%A6%E6%9D%9F%E6%94%BB%E5%87%BB/