1. 介紹
?? Redis是一個(gè)廣泛使用的Key-Value存儲系統(tǒng),主要用于處理各個(gè)高并發(fā)場景下的數(shù)據(jù)讀取加速,與MemCache不同的是,Redis具有多種數(shù)據(jù)結(jié)構(gòu)和靈活管理,而且還支持?jǐn)?shù)據(jù)持久化。在Redis中,我們可以通過靈活地動(dòng)態(tài)修改持久化的存儲路徑的特性,該特性也帶來一個(gè)問題,當(dāng)我們的數(shù)據(jù)中存在一些惡意代碼時(shí),那么該惡意代碼就能存儲到我們指定的路徑,從而實(shí)現(xiàn):SSH免密、定時(shí)任務(wù)啟動(dòng)、修改指定文件信息。
?? 在本文,我們將通過Redis這個(gè)特性來放置一段惡意代碼,并成功獲取我們需要的數(shù)據(jù)來展示該特性帶來的一些問題,然后我們通過 “SeLinux理論在Redis下實(shí)踐:第1部分
” 介紹的Selinux來限制該特性帶來的問題,最后我將列出在這個(gè)過程中遇到的一些問題回答和總結(jié),希望通過該文讓大家認(rèn)識到Selinux的先進(jìn)安全管理機(jī)制,如果我們運(yùn)用得恰當(dāng),它將能將許多0 Day 漏洞盡可能限制在一定的范圍。
2. 實(shí)踐目的
?? 目前有一些linux教程,經(jīng)常指導(dǎo)我們將selinux默認(rèn)關(guān)閉,其實(shí)對于linux的整體安全就會大打折扣。在這個(gè)實(shí)踐中,我主要通過利用Redis持久化數(shù)據(jù)到任意目錄文件的漏洞,在一個(gè)沒有開啟selinux的環(huán)境中,將一個(gè)可以讀取/etc/passwd的腳本寫到網(wǎng)站的運(yùn)行目錄,從而驗(yàn)證沒有selinux下的我們可以讀取一些敏感數(shù)據(jù)的風(fēng)險(xiǎn)點(diǎn),然后通過一步步地實(shí)踐如何在selinux下進(jìn)行防護(hù)該漏洞,以讓大家對selinux有更深的一個(gè)認(rèn)識。
3. 實(shí)驗(yàn)環(huán)境與背景
| 操作系統(tǒng): | Centos7 |
|---|---|
| WEB服務(wù)器: | Apache/2.4.6 |
| PHP: | 5.4.16 |
| Redis: | 4.0.9 |
| 網(wǎng)站目錄: | /var/www/html/ |
192.168.1.18:Redis與web服務(wù)器放置在同一臺機(jī)器。
192.168.1.19:客戶端
4. 如何進(jìn)行越權(quán)操作
為了達(dá)到實(shí)驗(yàn)?zāi)康?,Redis 開啟遠(yuǎn)程訪問的配置,并且無密碼,并且selinux是處于permissive或者disabled狀態(tài)。我們先檢查確認(rèn)服務(wù)端環(huán)境的就緒情況:
root@192.168.1.18# getenforce
Permissive
root@192.168.1.18# ss -antp|grep 6379
LISTEN 0 511 *:6379 *:* users:(("redis-server",pid=3934,fd=6))
在客戶端使用redis-cli連接到服務(wù)器,并設(shè)置保存路徑及保存文件,將惡意代碼寫入到某個(gè)test中,最后save把該代碼保存到設(shè)定的文件。
root@192.168.1.19 # redis-cli -h 192.168.1.18
192.168.1.18:6379>CONFIG SET dir /var/www/html
192.168.1.18:6379>CONFIG set dbfilename test.php
192.168.1.18:6379>set test '<?php var_dump(file_get_contents("/etc/passwd"));?>'
192.168.1.18:6379>save
然后,我們運(yùn)行該文件,可以查看到/etc/passwd內(nèi)容

以上就是我們通過redis這個(gè)漏洞獲取到敏感數(shù)據(jù)的過程。
通過上面的實(shí)驗(yàn)我們可以實(shí)現(xiàn)很多非法操作,比如文件讀寫,定時(shí)任務(wù)啟動(dòng)等等,雖然可以通過其他方式來規(guī)避這個(gè)問題,比如加密碼之類,但是有一些場景如cluster模式,必須無密碼,而且還擔(dān)心密碼泄露,沒有能基本上解決非法讀取的問題。
5. 如何通過SeLinux來防護(hù):
在服務(wù)端將selinux開啟,將能將該漏洞限制在有限的范圍內(nèi),而不會造成敏感數(shù)據(jù)泄露。
root@192.168.1.18# setenforce 1
root@192.168.1.18# getenforce
Enforcing
此時(shí),我們在客戶端就無法再通過該redis漏洞來獲取敏感數(shù)據(jù)了。
192.168.1.18:6379> save
(error) ERR
??我們查看一下服務(wù)端的selinux日志,可以發(fā)現(xiàn)以下內(nèi)容,證明我們selinux已經(jīng)實(shí)際攔截了。audit2why是一個(gè)selinux的日志分析工具,當(dāng)開啟selinux日志服務(wù)時(shí)(默認(rèn)開啟),日志文件默認(rèn)存放在/var/log/audit/audit.log:
root@192.168.1.18# audit2why < /var/log/audit/audit.log
type=AVC msg=audit(1553166802.997:6749): avc: denied { dac_override } for pid=3934 comm="redis-server" capability=1 scontext=system_u:system_r:redis_t:s0 tcontext=system_u:system_r:redis_t:s0 tclass=capability
Was caused by:
Missing type enforcement (TE) allow rule.
You can use audit2allow to generate a loadable module to allow this access.
??以上就是selinux的強(qiáng)大威力,但是selinux如何更好地為我所用呢?下面以如何將redis持久化數(shù)據(jù)保存到我們指定目錄為例,給大家更加直觀、深刻體會selinux的配置靈活性。
??如果我們想把數(shù)據(jù)文件保存到/data/redis/redis.db,下面提供兩種方式進(jìn)行配置
- 在服務(wù)端通過chcon 對該文件的selinux 類型修改為redis_var_run_t。
root@192.168.1.18# mkdir -p /opt/redis/
root@192.168.1.18# touch /opt/redis/redis.db
root@192.168.1.18# ls -Zl /opt/redis/redis.db
-rw-r--r--. 1 unconfined_u:object_r:usr_t:s0 root root 0 Mar 22 11:26 /opt/redis/redis.db
root@192.168.1.18# chcon -t redis_var_run_t /opt/redis/redis.db
root@192.168.1.18# ls -Zl /opt/redis/redis.db
-rw-r--r--. 1 unconfined_u:object_r:redis_var_run_t:s0 root root 0 Mar 22 11:26 /opt/redis/redis.db
然后在客戶端,我們再嘗試一下保持?jǐn)?shù)據(jù)
root@192.168.1.19 # redis-cli -h 192.168.1.18
192.168.1.18:6379>CONFIG SET dir /opt/redis/
192.168.1.18:6379>CONFIG set dbfilename redis.db
192.168.1.18:6379>save
OK
- 通過semange fcontext進(jìn)行添加后并重置權(quán)限:
root@192.168.1.18# semanage fcontext -a -t redis_var_run_t "/opt/redis(/.*)?"
root@192.168.1.18# restorecon -Rv /opt/redis/
6. 常見問題:
- 為何開啟selinux后,我的redis還是無法防護(hù)呢?
通過ps -auxZ 查看redis-server 的類型是否為:unconfined_troot@192.168.1.18# ps auxZ|grep redis unconfined_u:unconfined_r:unconfined_t:s0 ...如果是該提示,則是redis-server啟動(dòng)不能通過bash進(jìn)行啟動(dòng),默認(rèn)的 bash 環(huán)境是不受 SELinux 管制的~因?yàn)?bash 并不是什么特別的網(wǎng)絡(luò)服務(wù)!因此,在這個(gè)不受 SELinux 所限制的 bash 程序所產(chǎn)生的文件, 其身份識別大多就是 >unconfined_u 這個(gè)“不受限”用戶啰!
因此,需要通過systemctl start redis 來啟動(dòng)。
- 添加的上下文(context)在哪里呢?
默認(rèn)目錄在:/etc/selinux/targeted/contexts/files
這里有系統(tǒng)自帶的一些默認(rèn)的上下文資源,而我們自定義的上下文context放置到文件:file_contexts.local
7. 總結(jié):
通過以上的實(shí)驗(yàn),我們可以體驗(yàn)到一個(gè)漏洞的利用威力及其影響面是巨大的。也由于selinux配置靈活性,導(dǎo)致Selinux的配置并不直觀,在一些概念上理解比較抽象,因此很多人都默認(rèn)選擇了關(guān)閉該功能。希望通過這兩篇文章來幫助大家重新認(rèn)識selinux,并希望一起打造更加安全的linux服務(wù)環(huán)境。
8. 參考:
Redis漏洞,遠(yuǎn)程攻擊:https://www.cnblogs.com/shuaiandjun/p/8425994.html
由于時(shí)間關(guān)系,行文可能存在錯(cuò)誤或者有其他建議及問題,歡迎大家與我聯(lián)系:一虛道長(lailaiji@163.com)