Openfire身份认证漏洞分析(CVE-2023-32315)

admin 2023年10月17日08:09:14评论15 views字数 3920阅读13分4秒阅读模式

Openfire介绍

openfire是一个即时通讯服务器,也称之为即时通讯平台。它是基于XMPP协议的,大家所熟悉的通讯软件QQ、MSN和Gtalk等等,其中Gtalk就是基于XMPP协议的实现。
在即时通讯中往往因为需要保存一些状态或者数据所以不能采用点对点通讯,而是需要搭建服务器来转发。

来源:`https://blog.csdn.net/qin34/article/details/41316231`

通俗的讲openfire是一个即时通讯服务器,也叫即时通讯平台

影响版本

3.10.0 <= Openfire < 4.6.8

4.7.0 <= Openfire < 4.7.5

代码原理分析

这个漏洞的原理有点像多年前出现的CVE-2008-6508目录穿越漏洞

在设置为maven项目之后,先从源头配置找起

<filter>
<filter-name>AuthCheck</filter-name>
<filter-class>org.jivesoftware.admin.AuthCheckFilter</filter-class>
<init-param>
<param-name>excludes</param-name>
<param-value>
login.jsp,index.jsp?logout=true,setup/index.jsp,setup/setup-*,.gif,.png,error-serverdown.jsp,loginToken.jsp
</param-value>
</init-param>
</filter>

该处定义了一个名为AuthCheckfilter,用于对部分url免除鉴权

然后全局搜索AuthCheckFilter去寻找定义文件

定位代码

public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException
{
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse)res;
// Do not allow framing; OF-997
response.setHeader("X-Frame-Options", JiveGlobals.getProperty("adminConsole.frame-options", "SAMEORIGIN"));
// Reset the defaultLoginPage variable
String loginPage = defaultLoginPage;
if (loginPage == null) {
loginPage = request.getContextPath() + (AuthFactory.isOneTimeAccessTokenEnabled() ? "/loginToken.jsp" : "/login.jsp" );
}
// Get the page we're on:
String url = request.getRequestURI().substring(1);
if (url.startsWith("plugins/")) {
url = url.substring("plugins/".length());
}
// See if it's contained in the exclude list. If so, skip filter execution
boolean doExclude = false;
for (String exclude : excludes) {
if (testURLPassesExclude(url, exclude)) {
doExclude = true;
break;
}
}

定义代码里面可以看出

if (testURLPassesExclude(url, exclude)) {
doExclude = true;
break;
}

doExclude = true则无需鉴权

继续跟进testURLPassesExclude方法

public static boolean testURLPassesExclude(String url, String exclude) {
// If the exclude rule includes a "?" character, the url must exactly match the exclude rule.
// If the exclude rule does not contain the "?" character, we chop off everything starting at the first "?"
// in the URL and then the resulting url must exactly match the exclude rule. If the exclude ends with a "*"
// character then the URL is allowed if it exactly matches everything before the * and there are no ".."
// characters after the "*". All data in the URL before

if (exclude.endsWith("*")) {
if (url.startsWith(exclude.substring(0, exclude.length()-1))) {
// Now make sure that there are no ".." characters in the rest of the URL.
if (!url.contains("..") && !url.toLowerCase().contains("%2e")) {
return true;
}
}
}
else if (exclude.contains("?")) {
if (url.equals(exclude)) {
return true;
}
}
else {
int paramIndex = url.indexOf("?");
if (paramIndex != -1) {
url = url.substring(0, paramIndex);
}
if (url.equals(exclude)) {
return true;
}
}
return false;
}

代码中 if (!url.contains("..") && !url.toLowerCase().contains("%2e")) {可以发现对部分字符做了过滤

但是其内置的web服务器支持对%u002e非标准unicode编码的解析

具体代码如下所示

if (!encodedPath && !dot)
{
if (_param == null)
_decodedPath = _path;
else
_decodedPath = _path.substring(0, _path.length() - _param.length() - 1);
}
else if (_path != null)
{
// The RFC requires this to be canonical before decoding, but this can leave dot segments and dot dot segments
// which are not canonicalized and could be used in an attempt to bypass security checks.
String decodedNonCanonical = URIUtil.decodePath(_path);
_decodedPath = URIUtil.canonicalPath(decodedNonCanonical);
if (_decodedPath == null)
throw new IllegalArgumentException("Bad URI");
}

for (int i = offset; i < end; i++)
{
char c = path.charAt(i);
switch (c)
{
case '%':
if (builder == null)
{
builder = new Utf8StringBuilder(path.length());
builder.append(path, offset, i - offset);
}
if ((i + 2) < end)
{
char u = path.charAt(i + 1);
if (u == 'u')
{
// 解码%uxxxx形式的Unicode字符
builder.append((char)(0xffff & TypeUtil.parseInt(path, i + 2, 4, 16)));
i += 5;
}
else
{
// 解码%xx形式的ASCII字符
builder.append((byte)(0xff & (TypeUtil.convertHexDigit(u) * 16 + TypeUtil.convertHexDigit(path.charAt(i + 2)))));
i += 2;
}
}
else
{
throw new IllegalArgumentException("Bad URI % encoding");
}
break;

复现

环境部署

首先利用docker拉取漏洞版本镜像

然后开启漏洞环境

Openfire身份认证漏洞分析(CVE-2023-32315)

然后确定一下

Openfire身份认证漏洞分析(CVE-2023-32315)

部署完毕

Openfire身份认证漏洞分析(CVE-2023-32315)

利用漏洞

brupsuit打洞

Openfire身份认证漏洞分析(CVE-2023-32315)

go打洞

cd CVE-2023-32315-Openfire-Bypass/scan_all
go mod tidy
go run main.go -u http://openfire.com:9090

然后就直接出来了,操作不难

来源:https://xz.aliyun.com/ 感谢【将遗憾写成歌 

原文始发于微信公众号(衡阳信安):Openfire身份认证漏洞分析(CVE-2023-32315)

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年10月17日08:09:14
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   Openfire身份认证漏洞分析(CVE-2023-32315)https://cn-sec.com/archives/2119459.html

发表评论

匿名网友 填写信息