在使用CentOS時(shí)多多少少會涉及SELinux,尤其是針對Web服務(wù),大部分的做法是關(guān)閉SELinux,正確的做法是設(shè)置好SELiunx,可以防范網(wǎng)站攻擊風(fēng)險(xiǎn)。
本文參照官方SELinux文檔整理
1. Apache HTTP服務(wù)和SELinux
當(dāng)SELinux啟動,Apache HTTP服務(wù)(httpd)默認(rèn)運(yùn)行在受限模式下。運(yùn)行的進(jìn)程只能在設(shè)定好的域domains內(nèi)運(yùn)行,并與其他受限進(jìn)程分開。如果一個受限進(jìn)程被攻擊,依靠SELinux策略policy配置,攻擊者訪問的資源和可能的損失都會被限制。
接下來演示一下:
- 運(yùn)行
getenforce命令確認(rèn)SELinux的運(yùn)行在enforcing強(qiáng)制模式下:
~]# getenforce
Enforcing
- 查看
httpd的狀態(tài),確認(rèn)服務(wù)正在運(yùn)行:
~]# systemctl status httpd.service
httpd.service - The Apache HTTP Server
Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled; vendor preset: disabled)
Active: active (running) since Mon 2018-11-05 17:13:09 CST; 43min ago
- 查看
httpd進(jìn)程是否關(guān)聯(lián)了SELinuxcontext(上下文):
~]# ps -eZ | grep httpd
system_u:system_r:httpd_t:s0 30275 ? 00:00:00 httpd
system_u:system_r:httpd_t:s0 30276 ? 00:00:00 httpd
system_u:system_r:httpd_t:s0 30277 ? 00:00:00 httpd
system_u:system_r:httpd_t:s0 30278 ? 00:00:00 httpd
system_u:system_r:httpd_t:s0 30279 ? 00:00:00 httpd
system_u:system_r:httpd_t:s0 30280 ? 00:00:00 httpd
通過
ps命令的-Z參數(shù)可以查看進(jìn)城SELinux上下文狀態(tài)。
SELinux 上下文與httpd進(jìn)程關(guān)聯(lián)內(nèi)容為,system_u:system_r:httpd_t:s0。其中httpd_t是SELinux的類型type。這個類型定義了一個進(jìn)程域domain和一個文件類型type。
當(dāng)前httpd進(jìn)程運(yùn)行在httpd_t域httpd_t中。
SELinux策略policy定義了在受限域(如httpd_t)中運(yùn)行的進(jìn)程,如何與文件、其他進(jìn)程和系統(tǒng)進(jìn)行交互。
文件必須被正確標(biāo)記label,以通過httpd訪問它們。比如:httpd可以讀取標(biāo)記為httpd_sys_content_t類型的文件,但是不能進(jìn)行寫入操作,即便是文件加入了寫入權(quán)限,如下:
~]# ls -Z /var/www/html/index.html
-rw-rw-rw-. root root unconfined_u:object_r:httpd_sys_content_t:s0 index.html
SELinux的布爾型設(shè)置boolean必須啟動,以便允許確定的行為,比如,允許腳本網(wǎng)絡(luò)訪問,允許httpd訪問NFS和CIFS卷,或者httpd允許執(zhí)行CGI腳本。
2. Apache HTTP端口與SELinux端口
當(dāng)/etc/httpd/conf/httpd.conf文件配置完,httpd監(jiān)聽一個或多個端口,比如80,443,448,8080,8009或者8443等等。
必須使用semanage port命令添加新的端口到SELinux策略配置中。
下面演示使用新的httpd端口后,必須添加SELinux端口策略,否側(cè)httpd無法啟動。
- 確認(rèn)
httpd服務(wù)沒有運(yùn)行
~]# systemctl stop httpd
~]# systemctl status httpd.service
httpd.service - The Apache HTTP Server
Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled; vendor preset: disabled)
Active: inactive (dead)
- 使用
semanage工具查看當(dāng)前關(guān)于httpd的監(jiān)聽端口:
~]# semanage port -l | grep -w http_port_t
http_port_t tcp 80, 81, 443, 488, 8008, 8009, 8443, 9000
- 編輯
/etc/httpd/conf/httpd.conf文件,修改Listen的端口號為12345,可以確認(rèn)12345端口不再SELinux策略policy配置中:
~]# vim /etc/httpd/conf/httpd.conf
---
#Listen 12.34.56.78:80
Listen 12345
---
- 再次啟動
httpd查看結(jié)果:
~]# systemctl start httpd
Job for httpd.service failed because the control process exited with error code.
See "systemctl status httpd.service" and "journalctl -xe" for details.
~]# ausearch -m avc -c httpd
type=AVC msg=audit(1541420299.439:1731): avc:
denied { name_bind } for pid=51139 comm="httpd" src=12345
scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:unreserved_port_t:s0
tclass=tcp_socket
httpd服務(wù)無法啟動
使用ausearch命令查看SELinux相關(guān)日志
日志顯示SELinux已經(jīng)拒絕(denied)啟動httpd服務(wù)
- 現(xiàn)在允許
httpd監(jiān)聽12345端口
~]# semanage port -a -t http_port_t -p tcp 12345
~]# semanage port -l | grep httpd
http_port_t tcp 12345, 80, 81, 443, 488, 8008, 8009, 8443, 9000
- 再次啟動
httpd服務(wù),可以看到添加端口后,服務(wù)正常啟動了
~]# systemctl start httpd.service
為了保證能正常訪問,還需要在防火墻中添加端口
12345~]# firewall-cmd --permanent --add-port=12345/tcp ~]# firewall-cmd --reload
- 至此可以發(fā)現(xiàn)SELinux中對于端口的限制策略。
注意:
a.semanage port刪除端口,使用-d參數(shù)即可
semanage port -d -t http_port_t -p tcp 12345
b.firewall-cmd刪除端口,使用--remove-port參數(shù)
firewall-cmd --permanent --remove-port=12345/tcp
firewall-cmd --reload
3. 類型上下文(TYPES)
在SELinux的默認(rèn)策略targeted中,高級進(jìn)程隔離的主要權(quán)限控制方法是使用類型強(qiáng)制Type EnForcement。
所有文件和進(jìn)程都使用類型type標(biāo)簽label來標(biāo)記:為進(jìn)程定義一個SELinux域domain類型,為文件定義一個SELinux類型type。
SELinux策略規(guī)則定義了類型如何互相訪問,域是不是正在訪問一個類型,或者一個域訪問其他的域。
只有在指定SELinux策略規(guī)則允許訪問時(shí),才能訪問。
參照下面例子在/var/www/html/目錄中創(chuàng)建一個新文件,顯示當(dāng)前文件是繼承了父目錄/var/www/html/目錄下的httpd_sys_content_t類型:
- 查看
/var/www/html/目錄的SELinux上下文context:
~]# ls -Zd /var/www/html
drwxr-xr-x. root root system_u:object_r:httpd_sys_content_t:s0 /var/www/html/
可以看到當(dāng)前目錄使用的是
httpd_sys_content_t類型
所有的類型上下文都用_t結(jié)尾
- 創(chuàng)建一個新文件再次驗(yàn)證文件的類型上下文:
~]# touch /var/www/html/myfile1
~]# ls -Z /var/www/html/myfile1
-rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 /var/www/html/myfile1
可以看到文件的類型上下文被標(biāo)記為
httpd_sys_content_t,說明這是繼承了父目錄的類型上下文。
使用httpd_sys_content_t類型,那么SELinux允許httpd讀取當(dāng)前文件,但不允許寫操作,即便是給文件加入了寫權(quán)限。
SELinux策略定義了運(yùn)行在httpd_t域中的進(jìn)程可以讀寫的類型,這有助于防止進(jìn)程訪問其他進(jìn)程使用的文件。
例如:httpd能訪問標(biāo)記為httpd_sys_content_t類型的文件,但是默認(rèn)情況下不能訪問標(biāo)記為samba_share_t類型的文件。
同樣,在用戶主目錄中的文件被標(biāo)記為user_home_t類型:默認(rèn)在用戶目錄中,不允許httpd讀取或?qū)懭胛募?/p>
下面列出了一些關(guān)于httpd的類型,不同的類型允許靈活的配置和訪問:
httpd_sys_content_t
這個類型針對靜態(tài)web內(nèi)容,比如靜態(tài)網(wǎng)站使用的.html文件。
標(biāo)記為這種類型的文件,httpd可以讀取訪問,并且可以執(zhí)行腳本。
默認(rèn)情況下,標(biāo)有此類型的文件和目錄不能被httpd或其他進(jìn)程寫入或修改。
需要注意的是,默認(rèn)情況下,在/var/www/html/目錄中創(chuàng)建或復(fù)制的文件都用httpd_sys_content_t類型標(biāo)記。
httpd_sys_script_exec_t
如果希望httpd執(zhí)行的腳本,使用這種類型。
這種類型通常用于/var/www/cgi-bin/目錄中的通用網(wǎng)關(guān)接口(CGI)腳本。
默認(rèn)情況下,SELinux策略阻止httpd執(zhí)行CGI腳本。為了實(shí)現(xiàn)這一點(diǎn),使用httpd_sys_script_exec_t類型標(biāo)記腳本,并啟用httpd_enable_cgi布爾值。
用httpd_sys_script_exec_t標(biāo)記的腳本在httpd_sys_script_t域中運(yùn)行時(shí)被httpd執(zhí)行。
httpd_sys_script_t域可以訪問其他系統(tǒng)域,比如postgresql_t和mysqld_t。
httpd_sys_rw_content_t
標(biāo)記為這種類型的文件可以由標(biāo)記為httpd_sys_script_exec_t類型的腳本寫入,但不能被標(biāo)記為任何其他類型的腳本修改。
標(biāo)記為httpd_sys_rw_content_t類型來標(biāo)記文件,將由具有httpd_sys_script_exec_t類型的腳本讀取和寫入。
httpd_sys_ra_content_t
標(biāo)記為這種類型的文件可以由標(biāo)記為httpd_sys_script_exec_t類型的腳本追加寫入,但不能由標(biāo)記為任何其他類型的腳本修改。
使用httpd_sys_ra_content_t類型來標(biāo)記的文件,將由標(biāo)有httpd_sys_script_exec_t類型的腳本讀取并追加到這些文件中。
httpd_unconfined_script_exec_t
標(biāo)記為這種類型的腳本,意味著腳本不受限,運(yùn)行在沒有SELinux保護(hù)的情況下。
在無可奈何的情況下,針對對復(fù)雜腳本使用此類型。
換個角度來說,最好使用這種類型,而不是對httpd或整個系統(tǒng)禁用SELinux保護(hù)。
4. 修改SELinux上下文context
a. 臨時(shí)修改上下文
可以通過使用chcon命令修改文件和目錄的類型上下文。chcon的修改模式是臨時(shí)的,當(dāng)系統(tǒng)重新標(biāo)記relabel或者執(zhí)行restorecon命令時(shí)就會失效。
SELinux策略控制用戶是否能夠修改指定文件的SELinux上下文。
接下來演示,創(chuàng)建一個新的目錄/my/website/和index.html文件供httpd使用,并且設(shè)置標(biāo)簽允許httpd訪問:
- 在根目錄下,創(chuàng)建一個新的目錄,查看當(dāng)前目錄的上下文狀態(tài):
~]# mkdir -p /my/website
~]# ls -dZ /my
drwxr-xr-x. root root unconfined_u:object_r:default_t:s0 /my
可以看到默認(rèn)新建的目錄的類型上下文是
default_t
- 使用
chcon命令修改/my/目錄及子目錄的類型上下文:
~]# chcon -R -t httpd_sys_content_t /my/
~]# ls -dZ /my
drwxr-xr-x. root root unconfined_u:object_r:httpd_sys_content_t:s0 /my
~]# ls -Z /my
drwxr-xr-x. root root unconfined_u:object_r:httpd_sys_content_t:s0 website
可以看到
/my/目錄和子目錄/website的類型上下文都修改為httpd_sys_content_t
chcon命令的-R參數(shù)是遞歸全部子目錄和文件
chcon命令的-t參數(shù)是添加一個類型
- 創(chuàng)建一個新文件,查看文件的類型上下文:
~]# touch /my/website/index.html
~]# ls -Z /my/website/index.html
-rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 /my/website/index.html
可以看到,新建文件自動繼承了,所在文件夾的類型上下文
b. 永久修改上下文
使用semanage fcontext命令是創(chuàng)建一個標(biāo)簽,并在重新標(biāo)記,配合restorecon命令使用。
步驟:先使用semanage fcontext修改文件上下文的配置,然后運(yùn)行restorecon,讀取文件的上下文配置,并且允許修改標(biāo)簽。
接下來還是使用上面的例子來演示,創(chuàng)建一個新的目錄/my/website/和index.html文件供httpd使用,并且設(shè)置標(biāo)簽允許httpd訪問:
- 在根目錄下,創(chuàng)建一個新的目錄,查看當(dāng)前目錄的上下文狀態(tài):
~]# mkdir -p /my/website
~]# ls -dZ /my
drwxr-xr-x. root root unconfined_u:object_r:default_t:s0 /my
- 使用
semanage fcontext命令修改類型上下文:
~]# semanage fcontext -a -t httpd_sys_content_t "/my(/.*)?"
~]# ls -dZ /my
drwxr-xr-x. root root unconfined_u:object_r:default_t:s0 /my
可以看到使用
semanage fcontext命令后,文件夾的類型上下文并沒有發(fā)生變化。
- 創(chuàng)建一個新的文件:
~]# touch /my/website/index.html
~]# ls -Z /my/website/index.html
-rw-r--r--. root root unconfined_u:object_r:default_t:s0 /my/website/index.html
新建的文件
index.html類型上下文也沒有發(fā)生改變
- 接下來使用
restorecon命令重新讀取文件上下文配置:
~]# restorecon -R -v /my/
restorecon reset /my context unconfined_u:object_r:default_t:s0->unconfined_u:object_r:httpd_sys_content_t:s0
restorecon reset /my/website context unconfined_u:object_r:default_t:s0->unconfined_u:object_r:httpd_sys_content_t:s0
restorecon reset /my/website/index.html context unconfined_u:object_r:default_t:s0->unconfined_u:object_r:httpd_sys_content_t:s0
至此,可以看到文件夾和文件的類型上下文都變?yōu)?code>httpd_sys_content_t。
restorecon命令的-R參數(shù)是遞歸全部子目錄和文件
restorecon命令的-v參數(shù)是顯示修改的標(biāo)記
5.布爾值設(shè)置boolean
SELinux是在系統(tǒng)底層運(yùn)行。服務(wù)以多種方式運(yùn)行,可以通過使用布爾值來實(shí)現(xiàn)如何運(yùn)行指定的服務(wù)。布爾值設(shè)置允許在運(yùn)行時(shí)更改SELinux策略的部分內(nèi)容,而不需要了解如何編寫SELinux的策略。布爾值是實(shí)時(shí)更新的,例如允許服務(wù)訪問NFS卷,而無需重新加載或重新編譯SELinux策略。
修改布爾值的狀態(tài)很簡單,只需通過setsebool命令即可。比如:啟動httpd_anon_write布爾值,輸入下面的命令:
~]# setsebool httpd_anon_write on
關(guān)閉一個布爾值同樣使用setsebool命令,僅僅是在on和off之間切換:
~]# setsebool httpd_anon_write off
需要注意
如果想永久修改布爾值,需要在setsebool命令后加入-P參數(shù)。
一旦加入-P參數(shù),則系統(tǒng)重啟后依然有效。
下面列出與httpd相關(guān)的部分布爾值:
| 布爾值 | 說明 |
|---|---|
| httpd_anon_write | 當(dāng)被禁用時(shí),這個布爾值允許httpd只能讀取標(biāo)記為public_content_rw_t類型的文件。啟用此布爾值允許httpd寫入標(biāo)記為public_content_rw_t類型的文件,例如包含公共文件傳輸服務(wù)文件的公共目錄。 |
| httpd_mod_auth_ntlm_winbind | 啟用此布爾值允許使用httpd中的mod_auth_ntlm_winbind模塊訪問NTLM和Winbind身份驗(yàn)證機(jī)制。 |
| httpd_mod_auth_pam | 啟用此布爾值允許使用httpd中的mod_auth_pam模塊訪問PAM身份驗(yàn)證機(jī)制。 |
| httpd_sys_script_anon_write | 這個布爾值定義是否允許HTTP腳本對標(biāo)記為public_content_rw_t類型的文件進(jìn)行寫訪問,就像在公共文件傳輸服務(wù)中使用的那樣。 |
| httpd_builtin_scripting | 這個布爾定義了對httpd腳本的訪問。PHP內(nèi)容通常需要啟用這個布爾值。 |
| httpd_can_network_connect | 當(dāng)禁用此布爾值時(shí),將阻止HTTP腳本和模塊啟動到網(wǎng)絡(luò)或遠(yuǎn)程端口的連接。啟用此布爾值以允許此訪問。 |
| httpd_can_network_connect_db | 當(dāng)禁用此布爾值時(shí),將阻止HTTP腳本和模塊啟動到數(shù)據(jù)庫服務(wù)器的連接。啟用此布爾值以允許此訪問。 |
| httpd_can_network_relay | 當(dāng)httpd用作正向或反向代理時(shí),啟用此布爾值。 |
| httpd_can_sendmail | 當(dāng)禁用此布爾值時(shí),將阻止HTTP模塊發(fā)送郵件。如果在httpd中發(fā)現(xiàn)漏洞,這可以防止垃圾郵件攻擊。啟用此布爾值以允許HTTP模塊發(fā)送郵件。 |
| httpd_dbus_avahi | 當(dāng)被禁用時(shí),這個布爾值拒絕httpd通過總線訪問avahi服務(wù)。啟用此布爾值以允許此訪問。 |
| httpd_enable_cgi | 當(dāng)禁用此布爾值時(shí),將阻止httpd執(zhí)行CGI腳本。啟用此布爾值以允許httpd執(zhí)行CGI腳本(CGI腳本必須用httpd_sys_script_exec_t類型標(biāo)記)。 |
| httpd_enable_ftp_server | 啟用此布爾值允許httpd在FTP端口上偵聽并充當(dāng)FTP服務(wù)器。 |
| httpd_enable_homedirs | 當(dāng)禁用此布爾值時(shí),將阻止httpd訪問用戶主目錄。啟用此布爾值以允許httpd訪問用戶主目錄;例如,/home/*/中的內(nèi)容。 |
| httpd_execmem | 當(dāng)啟用時(shí),這個布爾值允許httpd執(zhí)行需要可執(zhí)行和可寫的內(nèi)存地址的程序。從安全角度來看,不建議啟用這個布爾值,因?yàn)樗鼫p少了對緩沖區(qū)溢出的保護(hù),但是某些模塊和應(yīng)用程序(如Java和Mono應(yīng)用程序)需要這個特權(quán)。 |
| httpd_ssi_exec | 這個布爾值定義web頁面中的服務(wù)器端包含(SSI)元素是否可以執(zhí)行。 |
| httpd_tty_comm | 此布爾值定義是否允許httpd訪問控制終端。通常不需要這種訪問,但是在配置SSL證書文件等情況下,顯示和處理密碼提示需要終端訪問。 |
| httpd_unified | 啟用后,此布爾值允許httpd_t完全訪問所有httpd類型(即執(zhí)行、讀取或?qū)懭雜ys_content_t)。禁用時(shí),在只讀、可寫或可執(zhí)行的web內(nèi)容之間存在分離。禁用此布爾值可以確保額外的安全級別,但增加了管理開銷,即必須根據(jù)每個腳本和其他web內(nèi)容各自具有的文件訪問權(quán)限分別標(biāo)記腳本和其他web內(nèi)容。 |
| httpd_use_cifs | 啟用此布爾值以允許httpd訪問標(biāo)記為cifs_t類型的CIFS卷上的文件,例如使用Samba掛載的文件系統(tǒng)。 |
| httpd_use_nfs | 啟用此布爾值以允許httpd訪問標(biāo)為nfs_t類型的NFS卷上的文件,例如使用NFS掛載的文件系統(tǒng)。 |
提示:
可以使用getsebool -a命令獲取全部的布爾值~]$ getsebool -a | grep service_name使用下面的命令查詢具體布爾值的說明:
~]$ sepolicy booleans -b boolean_name需要安裝
policycoreutils-devel軟件包,才能使用sepolicy命令。