星期五实验室
漏洞描述
WSO2 API Manager是一款可以旨在提供优秀的API管理功能的产品,能够实现API的创建、发布、生命周期管理、流量控制、版本控制、治理和安全控制等功能。WSO2 API Manager可以为开发团队提供Web页面进行部署、管理和监控API。WSO2由于无限制的任意文件上传可以导致远程代码执行漏洞。目前官方已经给出了解决办法。
影响版本
WSO2 API Manager 2.2.0 and above
WSO2 Identity Server 5.2.0 and above
WSO2 Identity Server Analytics 5.4.0, 5.4.1, 5.5.0, 5.6.0
WSO2 Identity Server as Key Manager 5.3.0 and above
WSO2 Enterprise Integrator 6.2.0 and above
漏洞复现
![WSO2 RCE(CVE-2022-29464) 漏洞复现 WSO2 RCE(CVE-2022-29464) 漏洞复现]()
漏洞复现
https://github.com/wso2/product-apim/releases/tag/v4.0.0
环境搭建
-
运行服务
运行效果如下:
2.访问目标网址
bash api-manager.sh --debug 5005 #linux
./api-manager.bat --debug 5005 #windows
细节分析
https://docs.wso2.com/display/MB220/Configuring+identity.xml
<ResourceAccessControl default-access="allow">
<Resource context="/duoauthenticationendpoint(.*)" http-method="all" secured="false"/>
<!--这就是文件上传的url,可以看到/fileupload 是不需要认证就可以访问的-->
<Resource context="(.*)/fileupload(.*)" http-method="all" secured="false"/>
<Resource context="(.*)/filedownload(.*)" http-method="all" secured="false"/>
<Resource context="(.*)/logincontext(.*)" http-method="all" secured="false"/>
</ResourceAccessControl>
public class FileUploadServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response){}
protected void doGet(HttpServletRequest request, HttpServletResponse response){}
//有javaWeb开发经验的一看就能知道它的作用了
public void init(ServletConfig servletConfig) throws ServletException {
this.servletConfig = servletConfig;
try {
this.fileUploadExecutorManager = new FileUploadExecutorManager(this.bundleContext, this.configContext, this.webContext);
this.bundleContext.registerService(FileUploadExecutorManager.class.getName(), this.fileUploadExecutorManager, (Dictionary)null);
} catch (CarbonException var3) {
log.error("Exception occurred while trying to initialize FileUploadServlet", var3);
throw new ServletException(var3);
}
}
}
public class FileUploadExecutorManager {
public FileUploadExecutorManager(BundleContext bundleContext, ConfigurationContext configCtx, String webContext) throws CarbonException {
this.bundleContext = bundleContext;
this.configContext = configCtx;
this.webContext = webContext;
this.loadExecutorMap();
}
public void addExecutor(String action, String executorClass) throws CarbonException {
String msg;
try {
Class clazz = this.bundleContext.getBundle().loadClass(executorClass);
Constructor constructor = clazz.getConstructor();
AbstractFileUploadExecutor object = (AbstractFileUploadExecutor)constructor.newInstance();
//添加值
this.executorMap.put(action, object);
} catch (Exception var6) {
}
}
}
这中间存储的就是fileupload目录下的实例化类。
this.fileUploadExecutorManager.execute(request, response);
所以我们跟到FileUploadExecutorManager#execute()方法中,代码如下:
public boolean execute(HttpServletRequest request, HttpServletResponse response) throws IOException {
HttpSession session = request.getSession();
String cookie = (String)session.getAttribute("wso2carbon.admin.service.cookie");
request.setAttribute("wso2carbon.admin.service.cookie", cookie);
request.setAttribute("WebContext", this.webContext);
request.setAttribute("ServerURL", CarbonUIUtil.getServerURL(request.getSession().getServletContext(), request.getSession()));
String requestURI = request.getRequestURI();
int indexToSplit = requestURI.indexOf("fileupload/") + "fileupload/".length();
//actionString就是我们需要执行对象在executeMap中的key值
String actionString = requestURI.substring(indexToSplit);
FileUploadExecutorManager.FileUploadExecutionHandlerManager execHandlerManager = new FileUploadExecutorManager.FileUploadExecutionHandlerManager();
FileUploadExecutorManager.CarbonXmlFileUploadExecHandler carbonXmlExecHandler = new FileUploadExecutorManager.CarbonXmlFileUploadExecHandler(request, response, actionString);
execHandlerManager.addExecHandler(carbonXmlExecHandler);
FileUploadExecutorManager.OSGiFileUploadExecHandler osgiExecHandler = new FileUploadExecutorManager.OSGiFileUploadExecHandler(request, response);
execHandlerManager.addExecHandler(osgiExecHandler);
FileUploadExecutorManager.AnyFileUploadExecHandler anyFileExecHandler = new FileUploadExecutorManager.AnyFileUploadExecHandler(request, response);
execHandlerManager.addExecHandler(anyFileExecHandler);
//开始
execHandlerManager.startExec();
return true;
}
execute:55, ToolsAnyFileUploadExecutor (org.wso2.carbon.ui.transports.fileupload)
executeGeneric:104, AbstractFileUploadExecutor (org.wso2.carbon.ui.transports.fileupload)
execute:436, FileUploadExecutorManager$CarbonXmlFileUploadExecHandler (org.wso2.carbon.ui.transports.fileupload)
//这里就是上方我们标记 “开始” 的位置
startExec:320, FileUploadExecutorManager$FileUploadExecutionHandlerManager (org.wso2.carbon.ui.transports.fileupload)
execute:127, FileUploadExecutorManager (org.wso2.carbon.ui.transports.fileupload)
doPost:57, FileUploadServlet (org.wso2.carbon.ui.transports)
service:660, HttpServlet (javax.servlet.http)
service:741, HttpServlet (javax.servlet.http)
service:37, ContextPathServletAdaptor (org.eclipse.equinox.http.helper)
service:61, ServletRegistration (org.eclipse.equinox.http.servlet.internal)
processAlias:128, ProxyServlet (org.eclipse.equinox.http.servlet.internal)
service:68, ProxyServlet (org.eclipse.equinox.http.servlet.internal)
service:741, HttpServlet (javax.servlet.http)
service:68, DelegationServlet (org.wso2.carbon.tomcat.ext.servlet)
internalDoFilter:231, ApplicationFilterChain (org.apache.catalina.core)
doFilter:166, ApplicationFilterChain (org.apache.catalina.core)
doFilter:53, WsFilter (org.apache.tomcat.websocket.server)
internalDoFilter:193, ApplicationFilterChain (org.apache.catalina.core)
doFilter:166, ApplicationFilterChain (org.apache.catalina.core)
doFilter:72, CsrfGuardFilter (org.owasp.csrfguard)
internalDoFilter:193, ApplicationFilterChain (org.apache.catalina.core)
doFilter:166, ApplicationFilterChain (org.apache.catalina.core)
doFilter:65, CharacterSetFilter (org.wso2.carbon.tomcat.ext.filter)
internalDoFilter:193, ApplicationFilterChain (org.apache.catalina.core)
doFilter:166, ApplicationFilterChain (org.apache.catalina.core)
doFilter:126, HttpHeaderSecurityFilter (org.apache.catalina.filters)
internalDoFilter:193, ApplicationFilterChain (org.apache.catalina.core)
doFilter:166, ApplicationFilterChain (org.apache.catalina.core)
invoke:202, StandardWrapperValve (org.apache.catalina.core)
invoke:96, StandardContextValve (org.apache.catalina.core)
invoke:541, AuthenticatorBase (org.apache.catalina.authenticator)
invoke:139, StandardHostValve (org.apache.catalina.core)
invoke:92, ErrorReportValve (org.apache.catalina.valves)
invoke:107, TenantContextRewriteValve (org.wso2.carbon.identity.context.rewrite.valve)
invoke:110, AuthorizationValve (org.wso2.carbon.identity.authz.valve)
invoke:102, AuthenticationValve (org.wso2.carbon.identity.auth.valve)
continueInvocation:101, CompositeValve (org.wso2.carbon.tomcat.ext.valves)
invokeValves:49, TomcatValveContainer (org.wso2.carbon.tomcat.ext.valves)
invoke:62, CompositeValve (org.wso2.carbon.tomcat.ext.valves)
invoke:145, CarbonStuckThreadDetectionValve (org.wso2.carbon.tomcat.ext.valves)
invoke:690, AbstractAccessLogValve (org.apache.catalina.valves)
invoke:57, CarbonContextCreatorValve (org.wso2.carbon.tomcat.ext.valves)
invoke:126, RequestCorrelationIdValve (org.wso2.carbon.tomcat.ext.valves)
invoke:74, StandardEngineValve (org.apache.catalina.core)
service:343, CoyoteAdapter (org.apache.catalina.connector)
service:373, Http11Processor (org.apache.coyote.http11)
process:65, AbstractProcessorLight (org.apache.coyote)
process:868, AbstractProtocol$ConnectionHandler (org.apache.coyote)
doRun:1590, NioEndpoint$SocketProcessor (org.apache.tomcat.util.net)
run:49, SocketProcessorBase (org.apache.tomcat.util.net)
runWorker:1149, ThreadPoolExecutor (java.util.concurrent)
run:624, ThreadPoolExecutor$Worker (java.util.concurrent)
run:61, TaskThread$WrappingRunnable (org.apache.tomcat.util.threads)
run:748, Thread (java.lang)
接下来就是执行ToolsAnyFileUploadExecutor#excute() 方法了,我们看具体代码
public boolean execute(HttpServletRequest request, HttpServletResponse response) {
PrintWriter out = response.getWriter();
try {
Map fileResourceMap = (Map)this.configurationContext.getProperty("file.resource.map");
if (fileResourceMap == null) {
fileResourceMap = new TreeBidiMap();
this.configurationContext.setProperty("file.resource.map", fileResourceMap);
}
List<FileItemData> fileItems = this.getAllFileItems();
Iterator i$ = fileItems.iterator();
while(i$.hasNext()) {
FileItemData fileItem = (FileItemData)i$.next();
String uuid = String.valueOf((double)System.currentTimeMillis() + Math.random());
String serviceUploadDir = this.configurationContext.getProperty("WORK_DIR") + File.separator + "extra" + File.separator + uuid + File.separator;
File dir = new File(serviceUploadDir);
if (!dir.exists()) {
dir.mkdirs();
}
//这里是整个rce能正常执行的重点,我们看到这里并没有对文件名做任何的../或./过滤,导致我们可以任意构造
File uploadedFile = new File(dir, fileItem.getFileItem().getFieldName());
FileOutputStream fileOutStream = new FileOutputStream(uploadedFile);
Throwable var13 = null;
try {
//文件写入
fileItem.getDataHandler().writeTo(fileOutStream);
fileOutStream.flush();
} catch (Throwable var31) {
} finally
}
response.setContentType("text/plain; charset=utf-8");
((Map)fileResourceMap).put(uuid, uploadedFile.getAbsolutePath());
//返回UUID值也是文件上级目录名
out.write(uuid);
}
} catch (Exception var33) {
} finally {
}
return true;
}
../../../../repository/deployment/server/webapps/authenticationendpoint/y2an0.jsp
发现恶意文件已经上传到想要的目录
成功执行了命令
解决方案
![WSO2 RCE(CVE-2022-29464) 漏洞复现 WSO2 RCE(CVE-2022-29464) 漏洞复现]()
解决方案
更新至最新版本,如未发布最新版本只需要使用缓解措施依旧能够解决问题。
具体解决方案:
https://docs.wso2.com/pages/viewpage.action?pageId=180952746
FRIDAY LAB
扫二维码|关注我们
星期五实验室
FRIDAY LAB
原文始发于微信公众号(星期五实验室):WSO2 RCE(CVE-2022-29464) 漏洞复现
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论