整数型注入
CTFHUB中给出的网页查询为数据库查询,并且为可注入的形式。为了查询我们想要的信息,必须对数据库中的表结构了如指掌,为此需要通过在查询窗口注入SQL语句来查出数据库名,表名,列名等信息,再进一步定位到我们需要的表数据上。经过百度得知mysql中的重要数据库information_schema,该数据库记录了mysql中各种视图信息,为此需要通过查询该数据库的信息逆向推出我们需要查找的那张表的信息。
利用information_schema.schemata表可以获取所有数据库名(schema_name列):
利用information_schema.tables表可以获取所有表名(table_name列,table_schema列用于筛选数据库):
利用information_schema.columns表可以获取所有字段名(column_name列,table_name列用于筛选表):
另外,由于该页面只能展示1行2列的表,采用以下技巧:
1.通过使用select 1,group_concat(列名) from 表名可以使得该列上的同组的所有值显示在一个单元格内(在不使用group by的情况下,默认所有元素一组)。
1X1
1X2
2.通过and false/恒假式操作使得原来的查询结果为空,再使用union操作把我们查询的表拼接到空表中。
字符型注入
与整数型注入类似,只不过此时我们输入的内容默认为字符型,即在执行查询时输入的值两侧会添加上'或",以单引号'为例,只需在输入框开头添加',结尾添加#(#为注释符),就可以使得单引号闭合,我们注入的查询语句能够被执行。
报错注入
报错注入主要用于不显示查询结果的情况,此时可以另辟蹊径,通过系统返回的报错信息来获取我们想要的数据。通过一些能展示查询结果的特殊报错,可以达到该目的。
mysql 5.1以后推出了xml的解析支持,利用xml中的extractvalue()方法和updatexml()方法的报错都可以完成这一目的。
extractvalue(xml_document,xpath_string):在xml文档Xpath_string下查询xml_document字段,由于Xpath_string未按照正确路径格式传入时会报错并显示值,故可以在此处传入一个SQL查询语句与非法字符拼接(concat())的字符串,这里的查询语句需要用括号括起来否则不会执行。
updatexml (xml_document, xpath_string, new_value):文档更新函数,进行字段替换,报错原理类似。
本来没找到flag,盲猜flag表我才发现输出的字符串被截断了(真是逆天,害的我以为没有sqli数据库),这里没有再测试updatexml方法中字符串长度的上限,而是采用了另一种方法。
这里利用了网上说的group by与rand的冲突问题。原理较复杂。后期补充。另外在本地电脑使用MySQL8.0不能复现该问题。
布尔盲注
在布尔盲注题型中,报错信息也被屏蔽,通过测试可以发现只有查询结果存在时会显示"query_success",查询结果为空或者语法错误时均显示"query_error"。利用这一区别就有了布尔盲注方法,原理就是盲猜,反正猜对了就有提示,因此可以一直猜到最终结果。由于盲注法太暴力,不是人工能完成的工作量,所以我使用了kali中的sqlmap工具来实现。
查询有结果:
查询无结果:
语法错误:
如果没有前面几题的铺垫,那么此题的数据库名,表名,列名等等都要猜,但这里已经知道数据存放在sqli数据库中的flag表的flag列,所以直接猜数据值就行。
语法:sqlmap [-u 链接(需要先查询一次)] [-D 库名] [-T 表名] [-C 列名] [--dbs/current-db/tables/dump 列出库名/当前库名/表名/数据] [--batch 不询问]
爆数据指令:
检测到注入点和注入类型,这里实际上采用了时间盲注而非布尔盲注,原理类似:
爆出结果:
时间盲注
如果题目再出得狠一点,对于查询的情况不提供任何信息呢?这时我们可以考虑通过自己创造隐式的信息来判断查询结果,时间盲注就是一个高明的方式,通过在查询结果中加入sleep指令,根据查询后服务器的响应时间来判断结果。
使用 if(condition,op when true,op when false)和sleep(seconds)命令即可判断查询结果是否存在。
如下例,当前数据库名称长度为4时服务器sleep5秒:
再次使用sqlmap工具爆出数据: