PHP相關安全配置【轉】

PHP是普遍使用的開源服務端腳本語言。經過HTTP或HTTPS協議,Apache Web服務容許用戶訪問文件或內容。服務端腳本語言的錯誤配置會致使各類問題。所以,PHP應該當心使用。如下是爲系統管理員準備的,安全配置PHP的25個實踐事例。php

用於下文的PHP設置樣例css

  • DocumentRoot:/var/www/html
  • 默認Web服務:Apache(可使用Lighttpd或Nginx代替)
  • 默認PHP配置文件:/etc/php.ini
  • 默認PHP Extensions配置目錄:/etc/php.d/
  • PHP安全配置樣例文件:/etc/php.d/security.ini(須要使用文本編輯器建立這個文件)
  • 操做系統:RHEL / CentOS / Fedora Linux(指令應該能夠在全部其餘Linux發行版,如Debian / Ubuntu,或是Unix-like的操做系統,如OpenBSD / FreeBSD / HP-UX下正常運行)
  • PHP服務的默認TCP/UDP端口:none

下午列出的大部分操做,都是基於 root 用戶能在 bash 或其餘現代 shell 上執行操做的假設。html

1
$ php - v

樣例輸出前端

1
2
3
PHP 5.3.3 (cli) (built: Oct 24 2011 08:35:41)
  Copyright (c) 1997-2010 The PHP Group
  Zend Engine v2.3.0, Copyright (c) 1998-2010 Zend Technologies

本文使用的操做系統mysql

1
$ cat /etc/redhat-release

樣例輸出linux

1
Red Hat Enterprise Linux Server release 6.1 (Santiago)

#1:知彼nginx

基於PHP的應用面臨着各類各樣的攻擊:程序員

  • XSS:對PHP的Web應用而言,跨站腳本是一個易受攻擊的點。攻擊者能夠利用它盜取用戶信息。你能夠配置Apache,或是寫更安全的PHP代碼(驗證全部用戶輸入)來防範XSS攻擊
  • SQL注入:這是PHP應用中,數據庫層的易受攻擊點。防範方式同上。經常使用的方法是,使用mysql_real_escape_string()對參數進行轉義,然後進行SQL查詢。
  • 文件上傳:它可讓訪問者在服務器上放置(即上傳)文件。這會形成例如,刪除服務器文件、數據庫,獲取用戶信息等一系列問題。你可使用PHP來禁止文件上傳,或編寫更安全的代碼(如檢驗用戶輸入,只容許上傳png、gif這些圖片格式)
  • 包含本地與遠程文件:攻擊者可使遠程服務器打開文件,運行任何PHP代碼,而後上傳或刪除文件,安裝後門。能夠經過取消遠程文件執行的設置來防範
  • eval():這個函數可使一段字符串如同PHP代碼同樣執行。它一般被攻擊者用於在服務器上隱藏代碼和工具。經過配置PHP,取消eval()函數調用來實現
  • Sea-surt Attack(Cross-site request forgery,CSRF。跨站請求僞造):這種攻擊會使終端用戶在當前帳號下執行非指定行爲。這會危害終端用戶的數據與操做安全。若是目標終端用戶的帳號用於管理員權限,整個Web應用都會收到威脅。

 

#2:減小內建的PHP模塊sql

執行下面指令能夠查看當前PHP所編譯的模塊shell

1
$ php -m

樣例輸出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
[PHP Modules]
  apc
  bcmath
  bz2
  calendar
  Core
  ctype
  curl
  date
  dom
  ereg
  exif
  fileinfo
  filter
  ftp
  gd
  gettext
  gmp
  hash
  iconv
  imap
  json
  libxml
  mbstring
  memcache
  mysql
  mysqli
  openssl
  pcntl
  pcre
  PDO
  pdo_mysql
  pdo_sqlite
  Phar
  readline
  Reflection
  session
  shmop
  SimpleXML
  sockets
  SPL
  sqlite3
  standard
  suhosin
  tokenizer
  wddx
  xml
  xmlreader
  xmlrpc
  xmlwriter
  xsl
  zip
  zlib
  [Zend Modules]
  Suhosin

從性能與安全性的角度考慮,我建議使用PHP時減小沒必要要的模塊。例如上面的sqlite3是沒必要要的。那麼能夠經過刪除或重命名/etc/php.d/sqlite3.ini文件來取消它:

1
# rm /etc/php.d/sqlite3.ini

1
# mv /etc/php.d/sqlite3.ini /etc/php.d/sqlite3.disable

有些模塊則只能經過使用從新編譯安裝PHP來移除。例如,從php.net下載PHP源碼後,使用下面指令編譯GD,fastcgi和MySQL支持:

1
. /configure --with-libdir=lib64 --with-gd --with-mysql --prefix= /usr -- exec -prefix= /usr --bindir= /usr/bin --sbindir= /usr/sbin --sysconfdir= /etc --datadir= /usr/share --includedir= /usr/include --libexecdir= /usr/libexec --localstatedir= /var --sharedstatedir= /usr/com --mandir= /usr/share/man --infodir= /usr/share/info --cache- file =.. /config .cache --with-config- file -path= /etc --with-config- file -scan- dir = /etc/php .d  -- enable -fastcgi -- enable -force-cgi-redirect

更多信息請查看:how to compile and reinstall php on Unix like operating system

 

#3:防止PHP信息泄漏

能夠經過取消export_php,對PHP信息泄漏進行限制。編輯/etc/php.d/security.ini以下:

1
expose_php=Off

expose_php會在HTTP Header中添加服務器上,包括版本在內的PHP信息(例如X-Powered-By: PHP/5.3.3)。同時,PHP的全局統一標識符也會暴露。若是export_php啓用的話,能夠經過下面命令查看PHP版本信息:

1
$ curl -I http: //www .cyberciti.biz /index .php

樣例輸出:

1
2
3
4
5
6
7
HTTP /1 .1 200 OK
  X-Powered-By: PHP /5 .3.3
  Content- type : text /html ; charset=UTF-8
  Vary: Accept-Encoding, Cookie
  X-Vary-Options: Accept-Encoding;list-contains= gzip ,Cookie;string-contains=wikiToken;string-contains=wikiLoggedOut;string-contains=wiki_session
  Last-Modified: Thu, 03 Nov 2011 22:32:55 GMT
  ...

建議同時隱藏Apache版本等信息:ServerTokens and ServerSignature directives in httpd.conf to hide Apache version

 

#4:最小化可載入的PHP模塊(動態Extension)

PHP支持「Dynamic Extensions」。默認狀況下,RHEL會載入/etc/php.d/目錄下的全部Extension模塊。如需啓用或取消某一模塊,只需把/etc/php.d/目錄下配置文件把該模塊註釋掉。也能夠把文件刪除或重命名該模塊的配置文件。爲了最優化PHP的性能和安全性,應只啓用Web應用所需的Extension。例如,用下面命令取消GD模塊:

1
2
3
# cd /etc/php.d/
  # mv gd.{ini,disable}
  # <span style="text-decoration: underline;">/sbin/service httpd restart</span>

啓用則是:

1
2
# mv gd.{disable,ini}
  # <span style="text-decoration: underline;">/sbin/service httpd restart</span>

 

#5:記錄全部PHP錯誤

不要把PHP錯誤信息輸出給所用用戶。編輯/etc/php.d/security.ini,以下修改:

1
display_errors=Off

確保把全部錯誤信息記錄到日誌文件

1
2
log_errors=On
error_log= /var/log/httpd/php_scripts_error .log

 

#6:禁止文件上傳

爲安全考慮,以下編輯/etc/php.d/security.ini取消文件上傳

1
file_uploads=Off

如用戶的確須要上傳文件,那麼把它啓用,然後限制PHP接受的最大文件大小:

1
2
3
file_uploads=On
# user can only upload upto 1MB via php
upload_max_filesize=1M

 

#7:關閉遠程代碼執行

若是這個特性被啓動,PHP能夠經過allow_url_fopen,在file_get_contents()、include、require中獲取諸如FTP或網頁內容這些遠程數據。程序員常常忘記了對用戶輸入進行過濾,而若是這些函數調用了這些數據,則造成了注入漏洞。在基於PHP的Web應用中,大量代碼中的注入漏洞都由此產生。能夠經過編輯/etc/php.d/security.ini來關閉該特性:

1
allow_url_fopen=Off

除此以外,建議把allow_url_include也取消掉:

1
allow_url_include=Off

 

#8:啓用SQL安全模式

以下修改/etc/php.d/security.ini:

1
sql.safe_mode=On

當此特性被啓用,mysql_connect()和mysql_pconnect()會忽略傳入的全部參數。與此同時,你須要在代碼上作些相應的修改。第三方以及開源應用,如Wordpress,在sql.safe_mode下可能沒法正常工做。同時建議關閉5.3.x版本的PHP的magic_quotes_gpc過濾,由於它簡單粗暴又沒效率。使用mysql_escape_string()以及自定義的過濾函數會更好一些

1
magic_quotes_gpc=Off

 

#9:控制POST的數據大小

HTTP POST一般做爲請求的一部分,被客戶端用於向Apache Web服務器發送數據,如上傳文件或提交表單。攻擊者會嘗試發送超大的POST請求去消耗服務器的資源。以下編輯/etc/php.d/security.ini限制POST的最大大小:

1
2
; 在這裏設置一個靠譜的數值
  post_max_size=1K

這裏設置了1K的最大大小。這個設置會影響到文件上傳。要上傳大文件,這個值須要比update_max_filesize大。
建議在Apache中限制可用的請求方法,編輯httpd.conf以下:

1
2
3
4
5
6
<Directory /var/www/html >
      <LimitExcept GET POST>
          Order allow,deny
      < /LimitExcept >
  ## Add rest of the config goes here... ##
  < /Directory >

 

#10:資源控制(DoS控制)

設置每一個PHP腳本的最大運行時間。另外建議限制用於處理請求數據的最大時間,以及最大可用內存數。
# 單位:秒

1
2
3
max_execution_time = 30
max_input_time = 30
memory_limit = 40M

 

#11:爲PHP安裝Suhosin高級保護系統

具體參考Suhosin項目頁:project page

 

#12:取消危險的PHP函數

PHP有大量可用於入侵服務器的函數,如使用不當則會成爲漏洞。以下取消這些函數:

1
disable_functions = exec ,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source

 

#13:PHP Fastcgi / CGI – cgi.force_redirect管理

PHP可與Fastcgi協同工做。Fastcgi能夠減小Web服務器的內存足跡(memory footprint),並改善PHP性能。能夠參考這個來配置Apache2+PHP+FastCGI。在這個配置中,cgi.force_redirect會阻止用戶經過訪問URL來調用PHP。爲安全考慮,啓用該特性:

1
2
; Enable cgi.force_redirect for security reasons in a typical *Apache+PHP-CGI /FastCGI * setup
  cgi.force_redirect=On

 

#14:PHP用戶與用戶組ID

mod_fastcgi是Apache Web服務的一個cgi模塊,可鏈接到外部的FASTCGI服務器。你須要確保PHP使用非root用戶運行。若其使用root或是UID小於100的用戶權限,它就能夠訪問,乃至操做系統文件。經過Apache’s suEXECmod_suPHP,可在非特權用戶下執行PHP CGI。suEXEC能夠是Apache調用CGI程序的user ID不一樣於運行Apache的user ID。以下:

1
# ps aux | grep php-cgi

樣例輸出:

1
2
3
4
5
6
7
phpcgi      6012  0.0  0.4 225036 60140          S    Nov22   0:12 /usr/bin/php-cgi
  phpcgi      6054  0.0  0.5 229928 62820          S    Nov22   0:11 /usr/bin/php-cgi
  phpcgi      6055  0.1  0.4 224944 53260          S    Nov22   0:18 /usr/bin/php-cgi
  phpcgi      6085  0.0  0.4 224680 56948          S    Nov22   0:11 /usr/bin/php-cgi
  phpcgi      6103  0.0  0.4 224564 57956          S    Nov22   0:11 /usr/bin/php-cgi
  phpcgi      6815  0.4  0.5 228556 61220          S    00:52   0:19 /usr/bin/php-cgi
  phpcgi      6821  0.3  0.5 228008 61252          S    00:55   0:12 /usr/bin/php-cgi

能夠經過spawn-fcgi來生成phpcgi用戶的遠程或本地FastCGI進程(前提是有這個用戶):

1
# spawn-fcgi -a 127.0.0.1 -p 9000 -u phpcgi -g phpcgi -f /usr/bin/php-cgi

如今能夠配置Apache、Lighthttpd或Nginx Web服務調用運行在127.0.0.1:9000的FastCGI。

 

#15:限制PHP訪問文件系統

open_basedir會限制PHP的運行目錄,例如經過fopen()之類的函數可訪問的目錄。若是訪問的目錄不在open_basedir以內,PHP會拒絕該訪問。不要使用軟連接做爲工做區。例如,只容許訪問/var/www/html而非/var/www、/tmp或/etc目錄:

1
2
3
4
5
6
7
; Limits the PHP process from accessing files outside
  ; of specifically designated directories such as /var/www/html/
  open_basedir= "/var/www/html/"
  ; ------------------------------------
  ; Multiple dirs example
  ; open_basedir= "/home/httpd/vhost/cyberciti.biz/html/:/home/httpd/vhost/nixcraft.com/html/:/home/httpd/vhost/theos.in/html/"
  ; ------------------------------------

 

#16:Session路徑

PHP Session用戶提供數據保存功能,以便後續訪問。這可使應用可定製性更強,提高吸引力。全部Session相關的數據會被保存在session.save_path中。RHEL/CentOS/Fedora Linux的默認設置以下:

1
2
3
session.save_path= "/var/lib/php/session"
  ; Set the temporary directory used for storing files when doing file upload
  upload_tmp_dir= "/var/lib/php/session"

確認這個路徑在/var/www/html以外,且不可被其餘系統用戶訪問:

1
# ls -Z /var/lib/php/

樣例輸出:

1
drwxrwx---. root apache system_u:object_r:httpd_var_run_t:s0 session

注:ls -Z會顯示SELinux的安全信息,如文件模式,user,group,安全信息,文件名等。

 

#17:保證PHP,軟件及操做系統更新到最新

維護Linux、Apache、PHP和MySQL服務器的一項重要工做是更新安全補丁。全部的PHP安全更新應儘快進行審查並更新。可以使用以下命令(若是經過包管理器來安裝PHP):

1
# yum update

1
# apt-get update && apt-get upgrade

能夠配置Red Hat / CentOS / Fedora Linux經過Email發送yum的包更新提醒,或是Debian / Ubuntu Linux下的apticron發送提醒。又或經過cron計劃任務進行更新。

注:查看php.net以獲取最新的PHP版本信息

 

#18:限制文件及目錄訪問

確認以Apache或www這種非root用戶運行Apache。/var/www/html目錄下的owner也應是非root用戶:

1
# chown -R apache:apache /var/www/html/

DocumentRoot下的文件應禁止運行或建立。設置該目錄下的文件權限爲0444(只讀):

1
# chmod -R 0444 /var/www/html/

設置該目錄下的全部文件夾權限爲0445

1
# find /var/www/html/ -type d -print0 | xargs -0 -I {} chmod 0445 {}

 

#19:Apache、PHP、MySQL配置文件的寫入保護

使用chattr命令給這些配置文件加上寫入保護:

1
2
3
4
5
# chattr +i /etc/php.ini
# chattr +i /etc/php.d/*
# chattr +i /etc/my.ini
# chattr +i /etc/httpd/conf/httpd.conf
# chattr +i /etc/

一樣能夠爲/var/www/html目錄加上寫入保護

1
# chattr +i /var/www/html/file1.php# chattr +i /var/www/html/

 

#20:使用Linux安全拓展(如SELinux)

Linux有各類安全方案來防止服務程序的錯誤配置或漏洞。儘量使用SELinux或其餘Linux安全方案限制網絡和程序。例如,SELinux爲Linux內核或Apache Web服務提供不一樣的安全策略。使用下面命令列出全部Apache保護信息:

1
# getsebool -a | grep httpd

樣例輸出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
allow_httpd_anon_write --> off
  allow_httpd_mod_auth_ntlm_winbind --> off
  allow_httpd_mod_auth_pam --> off
  allow_httpd_sys_script_anon_write --> off
  httpd_builtin_scripting --> on
  httpd_can_check_spam --> off
  httpd_can_network_connect --> off
  httpd_can_network_connect_cobbler --> off
  httpd_can_network_connect_db --> off
  httpd_can_network_memcache --> off
  httpd_can_network_relay --> off
  httpd_can_sendmail --> off
  httpd_dbus_avahi --> on
  httpd_enable_cgi --> on
  httpd_enable_ftp_server --> off
  httpd_enable_homedirs --> off
  httpd_execmem --> off
  httpd_read_user_content --> off
  httpd_setrlimit --> off
  httpd_ssi_exec --> off
  httpd_tmp_exec --> off
  httpd_tty_comm --> on
  httpd_unified --> on
  httpd_use_cifs --> off
  httpd_use_gpg --> off
  httpd_use_nfs --> off

取消Apache cgi支持能夠輸入:

1
# setsebool -P httpd_enable_cgi off

詳細參考:Red Hat SELinux guide

 

#21:安裝Mod_security

ModSecurity是一個開源的入侵檢測和防範的Web應用引擎。安裝mod_security能夠保護Apache和PHP應用免受XSS和其餘攻擊:

1
2
3
4
5
6
7
## A few Examples ##
  # Do not allow to open files in /etc/
  SecFilter /etc/
 
  # Stop SQL injection
  SecFilter "delete[[:space:]]+from"
  SecFilter "select.+from"

 

#22:若有可能,在Chroot Jail下運行Apache / PHP

在Chroot Jail下運行Apache / PHP能夠最小化可能受到的損失,使其侷限於文件系統下的一小塊。可使用通常的chroot來配置Apache:chroot kind of setup with Apache。不過我建議使用FreeBSD jails、XEN,KVM或OpenVZ虛擬化。

 

#23:使用防火牆限制傳出鏈接

攻擊者會使用wget之類的工具從你的Web服務器下載文件。使用iptables來阻擋Apache用戶的傳出鏈接。ipt_owner模塊會爲本地數據包的生成者分配不一樣角色。它只對OUTPUT chain有效。下面指令容許vivek用戶經過80端口進行外部訪問:

1
/sbin/iptables -A OUTPUT -o eth0 -m owner --uid-owner vivek -p tcp --dport 80 -m state --state NEW,ESTABLISHED  -j ACCEPT

下面的樣例則是阻擋全部Apache用戶的傳出鏈接,只容許smtp服務及spam識別API服務經過:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# .... 
  /sbin/iptables --new-chain apache_user
  /sbin/iptables --append OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
  /sbin/iptables --append OUTPUT -m owner --uid-owner apache -j apache_user
  # allow apache user to connec to our smtp server
  /sbin/iptables --append apache_user -p tcp --syn -d 192.168.1.100 --dport 25 -j RETURN
  # Allow apache user to connec to api server for spam validation
  /sbin/iptables --append apache_user -p tcp --syn -d  66.135.58.62 --dport 80 -j RETURN
  /sbin/iptables --append apache_user -p tcp --syn -d  66.135.58.61 --dport 80 -j RETURN
  /sbin/iptables --append apache_user -p tcp --syn -d  72.233.69.89 --dport 80 -j RETURN
  /sbin/iptables --append apache_user -p tcp --syn -d  72.233.69.88 --dport 80 -j RETURN
  #########################
  ## Add more rules here ##
  #########################
  # No editing below
  # Drop everything for apache outgoing connection
  /sbin/iptables --append apache_user -j REJECT

 

#24:查看並審查日誌

查看Apache日誌文件:

1
2
3
# tail -f /var/log/httpd/error_log
  # grep 'login.php' /var/log/httpd/error_log
  # egrep -i "denied|error|warn" /var/log/httpd/error_log

查看PHP日誌文件:

1
2
# tail -f /var/log/httpd/php_scripts_error.log
  # grep "...etc/passwd" /var/log/httpd/php_scripts_error.log

查看日誌文件可讓你知道服務器正在承受何種攻擊,並分析當前安全級別是否足夠。啓用審查服務用於系統審查,可審查SELinux時間,驗證事件,文件修改,帳號修改等。建議使用Linux System Monitoring Tools來監控Web服務器。

 

#25:把服務分離到不一樣的服務器或虛擬機

對於比較龐大的安裝配置,建議把運行、數據庫、靜態與動態內容分離到不一樣的服務器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
///////////////
  / ISP /Router /
  //////////////
    \
     |
     Firewall
       \
        |
       +------------+
       | LB01       |
       +------------+                 +--------------------------+
                    |                 | static.lan.cyberciti.biz |
                    +-----------------+--------------------------+
                                      | phpcgi1.lan.cyberciti.biz|
                                      +--------------------------+
                                      | phpcgi2.lan.cyberciti.biz|
                                      +--------------------------+
                                      | mysql1.lan.cyberciti.biz |
                                      +--------------------------+
                                      | mcache1.lan.cyberciti.biz|
                                      +--------------------------+

在不一樣的服務器或虛擬機下運行不一樣的網絡服務,這能夠減小被入侵對其餘服務的影響。例如,一個攻擊者入侵了Apache,那就能夠訪問同一服務器下的其餘服務(如MySQL,email服務等)。但在上述例子中則不會:

    • static.lan.cybercity.biz – 使用lighttpd或nginx存放js/css/images等靜態資源
    • phpcgi1.lan.cyberciti.biz和phpcgi2.lan.cyberciti.biz – Apache Web服務+PHP,用於生成動態內容
    • mysql1.lan.cyberciti.biz – MySQL數據庫服務
    • mcache1.lan.cyberciti.biz – Memcached服務(MySQL的高速緩存系統)。它使用libevent或epoll來適應任意鏈接數。並且它使用的是非阻塞網絡IO。
    • LB01 – 一個Nginx服務器,用於Web及Apache前端的反向代理。全部的訪問鏈接會經過nginx代理服務,被直接處理或分發到相應的Web服務器。LB01提供簡單的負載均衡。
相關文章
相關標籤/搜索