溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

php安全配置中有哪些常見的錯誤

發(fā)布時間:2020-12-11 16:10:39 來源:億速云 閱讀:223 作者:Leah 欄目:開發(fā)技術(shù)

這篇文章給大家介紹php安全配置中有哪些常見的錯誤,內(nèi)容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

下面對php.ini中一些安全相關(guān)參數(shù)的配置進行說明

register_globals 
當register_globals = ON時,PHP不知道變量從何而來,也容易出現(xiàn)一些變量覆蓋的問題。因此從最佳實踐的角度,強烈建議設置 register_globals = OFF,這也是PHP新版本中的默認設置。 
 
open_basediropen_basedir 
可以限制PHP只能操作指定目錄下的文件。這在對抗文件包含、目錄遍歷等攻擊時非常有用,應該為此選項設置一個值。 
需要注意的是,如果設置的值是一個指定的目錄,則需要在目錄最后加上一個“/”,否則會被認為是目錄的前綴。 
open_basedir = /home/web/html/
 
allow_url_include = Off 
為了對抗遠程文件包含,請關(guān)閉此選項,一般應用也用不到此選項。同時推薦關(guān)閉的還有allow_url_fopen。 
 
display_errors = Off 
錯誤回顯,一般常用于開發(fā)模式,但是很多應用在正式環(huán)境中也忘記了關(guān)閉此選項。錯誤回顯可以暴露出非常多的敏感信息,為攻擊者下一步攻擊提供便利。推薦關(guān)閉此選項。 
 
log_errors = On 
在正式環(huán)境下用這個就行了,把錯誤信息記錄在日志里。正好可以關(guān)閉錯誤回顯。 
 
magic_quotes_gpc = Off 
推薦關(guān)閉,它并不值得依賴(請參考“注入攻擊”一章),已知已經(jīng)有若干種方法可以繞過它,甚至由于它的存在反而衍生出一些新的安全問題。XSS、SQL注入等漏洞,都應該由應用在正確的地方解決。同時關(guān)閉它還能提高性能。 
 
cgi.fix_pathinfo = 0 
若PHP以CGI的方式安裝,則需要關(guān)閉此項,以避免出現(xiàn)文件解析問題(請參考“文件上傳漏洞”一章)。 
 
session.cookie_httponly = 1 開啟HttpOnly 
 
session.cookie_secure = 1 
若是全站HTTPS則請開啟此項。 
 
sql.safe_mode = Off 
PHP的安全模式是否應該開啟的爭議一直比較大。一方面,它會影響很多函數(shù);另一方面,它又不停地被黑客們繞過,因此很難取舍。如果是共享環(huán)境(比如App Engine),則建議開啟safe_mode,可以和disable_functions配合使用; 
如果是單獨的應用環(huán)境,則可以考慮關(guān)閉它,更多地依賴于disable_functions控制運行環(huán)境安全。 
 
disable_functions = 
能夠在PHP中禁用函數(shù)(如上默認=號后面什么都不配置)。這是把雙刃劍,禁用函數(shù)可能會為開發(fā)帶來不便,但禁用的函數(shù)太少又可能增加開發(fā)寫出不安全代碼的幾率,同時為黑客獲取webshell提供便利。 
一般來說,如果是獨立的應用環(huán)境,則推薦禁用以下函數(shù): 
disable_functions = escapeshellarg, escapeshellcmd, exec,passthru, proc_close, proc_get_status, proc_open, proc_nice,proc_terminate, shell_exec, system, ini_restore, popen, dl,disk_free_space, diskfreespace, set_time_limit, tmpfile, fopen,readfile, fpassthru, fsockopen, mail, ini_alter, highlight_file,openlog, show_source, symlink, apache_child_terminate,apache_get_modules, apache_get_version, apache_getenv,apache_note, apache_setenv, parse_ini_file

php 上傳大文件主要涉及配置upload_max_filesize和post_max_size兩個選項

曾經(jīng)遇到的問題: 
在網(wǎng)站后臺上傳圖片的時候出現(xiàn)一個非常怪的問題,有時候表單提交可以獲取到值,有時候就獲取不到了,連普通的字段都獲取不到了,苦思冥想還沒解決,最后問了師傅, 
師傅看了說挺奇怪的,然后問我 upload_max_filesize的值改了嗎,我說改了啊,師傅也解決不了了。過了一會師傅問 post_max_size改了嗎,我說那個和上傳沒關(guān)系吧, 
師傅沒理我,我還是照著自己的想法繼續(xù)測試,弄了半天還是不行,最后試了師傅提的意見,成功了,原來上傳是和 post_max_size有關(guān)系的。 
  
問題總結(jié) : 
php.ini配置文件中的默認文件上傳大小為 2M,默認upload_max_filesize = 2M ,即文件上傳的大小為 2M,如果你想上傳超過8M的文件,比如 20M, 
  
必須設定 upload_max_filesize = 20M。但是光設置upload_max_filesize = 20M還是無法實現(xiàn)大文件的上傳功能,你必須修改 php.ini配置文件中的post_max_size選項, 
其代表允許 POST的數(shù)據(jù)最大字節(jié)長度,默認為 8M。如果POST 數(shù)據(jù)超出限制,那么 $_POST和$_FILES 將會為空。要上傳大文件, 
你必須設定該選項值大于 upload_max_filesize指令的值,我一般設定upload_max_filesize和 post_max_size值相等。 
另外如果啟用了內(nèi)存限制,那么該值應當小于 memory_limit選項的值。 
  
文件上傳的其他注意事項 : 
在上傳大文件時,你會有上傳速度慢的感覺,當超過一定的時間,會報腳本執(zhí)行超過 30秒的錯誤,這是因為在php.ini配置文件中 max_execution_time 配置選項在作怪, 
其表示每個腳本最大允許執(zhí)行時間 (秒) ,0 表示沒有限制。你可以適當調(diào)整 max_execution_time的值,不推薦設定為0。 
******************************************************************************************************** 
解釋: 
具體可查看 PHP手冊 中的 〔php.ini 核心配置選項說明〕 
upload_max_filesize 所上傳的文件的最大大小。 
post_max_size    設定 POST 數(shù)據(jù)所允許的最大大小。 
memory_limit    設定了一個腳本所能夠申請到的最大內(nèi)存字節(jié)數(shù)。 
 
一般來說:memory_limit > post_max_size > upload_max_filesize 
  
upload_max_filesize是限制本次上傳的最大值 
post_max_size是post數(shù)據(jù)的最大值, 通過POST提交數(shù)據(jù)的最大值 
一般我們在php中用的是POST方式上傳

php.ini中記錄PHP錯誤日志的參數(shù):display_errors與log_errors的區(qū)別

1)display_errors 
錯誤回顯,一般常用語開發(fā)模式,但是很多應用在正式環(huán)境中也忘記了關(guān)閉此選項。錯誤回顯可以暴露出非常多的敏感信息,為攻擊者下一步攻擊提供便利。推薦關(guān)閉此選項。 
 
display_errors = On 
開啟狀態(tài)下,若出現(xiàn)錯誤,則報錯,出現(xiàn)錯誤提示。即顯示所有錯誤信息。 
 
dispaly_errors = Off 
關(guān)閉狀態(tài)下,若出現(xiàn)錯誤,則提示:服務器錯誤,但是不會出現(xiàn)錯誤提示。即關(guān)閉所有錯誤信息 
 
2)log_errors 
在正式環(huán)境下用這個就行了,把錯誤信息記錄在日志里。正好可以關(guān)閉錯誤回顯。 
 
log_errors = On  //注意,log_errors設置為On后,那么dispaly_errors就要設置為Off,這兩個不能同時打開。 
 
error_log = /Data/logs/php/error.log  //注意,log_errors設置為On時,必須要設置error_log的日志文件路徑,并且這個日志文件要能有權(quán)限正常寫入。 
 
也就是說log_errors = On時,必須指定error_log文件,如果沒指定或者指定的文件沒有權(quán)限寫入,那么照樣會輸出到正常的輸出渠道,那么也就使得display_errors 這個指定的Off失效,錯誤信息還是打印了出來。 
 
對于PHP開發(fā)人員來說,一旦項目上線后,第一件事就是應該將display_errors選項關(guān)閉,以免因為這些錯誤所透露的路徑、數(shù)據(jù)庫連接、數(shù)據(jù)表等信息而遭到黑客攻擊。 
 
--------------------------------------------------- 
一般說來: 
 
測試環(huán)境下的php.ini中的錯誤日志設置:        
error_reporting = E_ALL  
display_errors = On  
html_errors = On  
log_errors = Off  
 
正式環(huán)境下的php.ini中的錯誤日志設置: 
error_reporting = E_ALL &~ E_NOTICE &~ E_WARNING    //注意這個設置,記得有一次因為這個設置有誤,導致了線上一個業(yè)務訪問出現(xiàn)了nginx 500報錯!這個導致了php框架報錯!  
display_errors = Off  
log_errors = On  
html_errors = Off  
error_log = /Data/logs/php/error.log 
ignore_repeated_errors = On  
ignore_repeated_source = On  
 
簡單講解下各個配置的意義: 
error_reporting :設置報告哪些錯誤  
display_errors :設置錯誤是否作為輸出的一部分顯示  
html_errors :設置錯誤信息是否采用html格式  
log_errors :設置是否記錄錯誤信息  
error_log :設置錯誤信息記錄的文件  
ignore_repeated_errors :是否在同一行中重復顯示一樣的錯誤信息  
ignore_repeated_source : 是否重復顯示來自同個文件同行代碼的錯誤

順便記錄下php的頁面老是報時區(qū)錯誤的處理過程:

Warning: phpinfo(): It is not safe to rely on the system's timezone settings. You are 
*required* to use the date.timezone setting or the date_default_timezone_set() 
function. In case you used any of those methods and you are still getting this 
warning, you most likely misspelled the timezone identifier. We selected the 
timezone 'UTC' for now, but please set date.timezone to select your timezone. in
/usr/local/www/zabbix2/phpinfo.php on line 2 
date/time support enabled 
"Olson" Timezone Database Version 2013.8 
Timezone Database internal 
Default timezone UTC 
 
修改php.ini 文件 
# vim /usr/local/php/etc/php.ini 
........ 
[Date] 
; Defines the default timezone used by the date functions 
; http://php.net/date.timezone 
date.timezone = Asia/Shanghai
 
注意必須把要 php.ini 復制一份到/usr/local/php/lib/下,否則 php 服務默認會到這個 lib 目錄下讀取 php.ini 文件,沒有的話,就是默認時區(qū)UTC,這個時區(qū)和北京時間相差8小時。 
[root@i-gxcmjlge lib]# pwd 
/usr/local/php/lib
[root@i-gxcmjlge lib]# ll 
total 72 
drwxr-xr-x 14 root root 4096 Nov 18 01:11 php 
-rw-r--r-- 1 root root 65681 Nov 18 15:01 php.ini 
 
然后重啟php服務和nginx/apache服務

除了php.ini文件,還要注意php-fpm.conf配置,如下:

[root@i-v5lmgh7y etc]# cat php-fpm.conf|grep -v "^;"|grep -v "^$"
[global] 
pid = run/php-fpm.pid  //pid 設置,默認在安裝目錄中的 var/run/php-fpm.pid,建議開啟 
error_log = log/php-fpm.log  //錯誤日志,默認在安裝目錄中的 var/log/php-fpm.log 
log_level = notice   //錯誤級別. 可用級別為: alert(必須立即處理), error(錯誤情況), warning(警告情況), notice(一般重要信息), debug(調(diào)試信息). 默認: notice. 
emergency_restart_threshold = 60 
emergency_restart_interval = 60s //表示在emergency_restart_interval所設值內(nèi)出現(xiàn)SIGSEGV或者SIGBUS錯誤的php-cgi進程數(shù)如果超過 emergency_restart_threshold個,php-fpm就會優(yōu)雅重啟。這兩個選項一般保持默認值。 
process_control_timeout = 0 //設置子進程接受主進程復用信號的超時時間. 可用單位: s(秒), m(分), h(小時), 或者 d(天) 默認單位: s(秒). 默認值: 0. 
daemonize = yes  //后臺執(zhí)行fpm,默認值為yes,如果為了調(diào)試可以改為no。在FPM中,可以使用不同的設置來運行多個進程池。 這些設置可以針對每個進程池單獨設置。 
 
[www] 
user = nobody   //啟動進程的帳戶 
group = nobody  //啟動進程的組 
listen = 127.0.0.1:9000  //fpm監(jiān)聽端口,即nginx中php處理的地址,一般默認值即可??捎酶袷綖? 'ip:port', 'port', '/path/to/unix/socket'. 每個進程池都需要設置. 
listen.backlog = 1024  //backlog數(shù),,由操作系統(tǒng)決定,-1表示無限制。也可以注釋掉此行。 
listen.allowed_clients = 127.0.0.1 //(可以不設置此行)允許訪問FastCGI進程的IP,如果沒有設置或者為空,則允許任何服務器請求連接。設置any為不限制IP,如果要設置其他主機的nginx也能訪問這臺FPM進程,listen處要設置成本地可被訪問的IP。默認值是any。每個地址是用逗號分隔. 
 
pm = static  //對于專用服務器,pm可以設置為static,如何控制子進程,選項有static和dynamic。如果選擇static,則由pm.max_children指定固定的子進程數(shù)。如果選擇dynamic,則由下開參數(shù)決定: 
pm.max_children = 512  //子進程最大數(shù) 
pm.start_servers = 387 //啟動時的進程數(shù) 
pm.min_spare_servers = 32 //保證空閑進程數(shù)最小值,如果空閑進程小于此值,則創(chuàng)建新的子進程 
pm.max_spare_servers = 387 //保證空閑進程數(shù)最大值,如果空閑進程大于此值,此進行清理 
pm.max_requests = 1024 //設置每個子進程重生之前服務的請求數(shù). 對于可能存在內(nèi)存泄漏的第三方模塊來說是非常有用的. 如果設置為 '0' 則一直接受請求. 等同于 PHP_FCGI_MAX_REQUESTS 環(huán)境變量. 默認值: 0 
pm.status_path = /status  //fpm狀態(tài)頁面的網(wǎng)址. 如果沒有設置, 則無法訪問狀態(tài)頁面. 默認值: none. munin監(jiān)控會使用到 
 
ping.path = /ping  //fpm監(jiān)控頁面的ping網(wǎng)址. 如果沒有設置, 則無法訪問ping頁面. 該頁面用于外部檢測FPM是否存活并且可以響應請求. 請注意必須以斜線開頭 (/)??梢圆辉O置此行。 
ping.response = pong //用于定義ping請求的返回相應. 返回為HTTP 200的text/plain 格式文本. 默認值: pong。可以不設置此行。 
  
slowlog = var/log/slow.log  //慢請求的記錄日志,配合request_slowlog_timeout使用 
request_slowlog_timeout = 0 //設置單個請求的超時中止時間. 該選項可能會對php.ini設置中的'max_execution_time'因為某些特殊原因沒有中止運行的腳本有用. 設置為 '0' 表示 'Off'.當經(jīng)常出現(xiàn)502錯誤時可以嘗試更改此選項。 
request_terminate_timeout = 10s //當一個請求該設置的超時時間后,就會將對應的PHP調(diào)用堆棧信息完整寫入到慢日志中. 設置為 '0' 表示 'Off'??梢圆辉O置此行。 
rlimit_files = 65535  //設置文件打開描述符的rlimit限制. 默認值: 系統(tǒng)定義值默認可打開句柄是1024,可使用 ulimit -n查看,ulimit -n 2048修改。 
rlimit_core = 0  //設置核心rlimit最大限制值. 可用值: 'unlimited' 、0或者正整數(shù). 默認值: 系統(tǒng)定義值. 
catch_workers_output = yes //重定向運行過程中的stdout和stderr到主要的錯誤日志文件中. 如果沒有設置, stdout 和 stderr 將會根據(jù)FastCGI的規(guī)則被重定向到 /dev/null . 默認值: 空.

------------------------Nginx+Php中限制站點目錄防止跨站的配置方案記錄(使用open_basedir)-------------------

方法1)在Nginx配置文件中加入:

fastcgi_param PHP_VALUE "open_basedir=$document_root:/tmp/:/proc/";

通常nginx的站點配置文件里用了include fastcgi.conf;,這樣的,把這行加在fastcgi.conf里就OK了。

如果某個站點需要單獨設置額外的目錄,把上面的代碼寫在include fastcgi.conf;這行下面就OK了,會把fastcgi.conf中的設置覆蓋掉。

這種方式的設置需要重啟nginx后生效。

方法2)在php.ini中加入

[HOST=www.wangshibo.com] 
open_basedir=/home/www/www.wangshibo.com:/tmp/:/proc/
[PATH=/home/www/www.wangshibo.com] 
open_basedir=/home/www/www.wangshibo.com:/tmp/:/proc/

這種方式的設置需要重啟php-fpm后生效。

方法3)在網(wǎng)站根目錄下創(chuàng)建.user.ini文件,并在該文件中寫入下面信息:

open_basedir=/home/www/www.wangshibo.com:/tmp/:/proc/

這種方式不需要重啟nginx或php-fpm服務。安全起見應當取消掉.user.ini文件的寫權(quán)限。

php.ini中建議禁止的函數(shù)如下:

disable_functions = pcntl_alarm, pcntl_fork, pcntl_waitpid, pcntl_wait, pcntl_wifexited, pcntl_wifstopped, pcntl_wifsignaled, pcntl_wexitstatus, pcntl_wtermsig, pcntl_wstopsig, pcntl_signal, pcntl_signal_dispatch, pcntl_get_last_error, pcntl_strerror, pcntl_sigprocmask, pcntl_sigwaitinfo, pcntl_sigtimedwait, pcntl_exec, pcntl_getpriority, pcntl_setpriority, eval, popen, passthru, exec, system, shell_exec, proc_open, proc_get_status, chroot, chgrp, chown, ini_alter, ini_restore, dl, pfsockopen, openlog, syslog, readlink, symlink, popepassthru, stream_socket_server, fsocket, chdir

----------------------------------------------php啟動后,9000端口沒有起來?--------------------------------------------

問題描述:

php服務安裝后,啟動php-fpm,啟動的時候沒有報錯。然后ps -ef|grep php沒有發(fā)現(xiàn)進程起來,lsof -i:9000發(fā)現(xiàn)端口也沒有起來。

查看日志,發(fā)現(xiàn)系統(tǒng)所允許打開的文件數(shù)超過了預定設置。

[root@i-v5lmgh7y etc]# /usr/local/php/sbin/php-fpm 
[root@i-v5lmgh7y etc]# ps -ef|grep php 
[root@i-v5lmgh7y etc]#lsof -i:9000 
[root@i-v5lmgh7y etc]# 
 
查看錯誤日志發(fā)現(xiàn)問題: 
[root@i-v5lmgh7y log]# tail -f php-fpm.log 
[15-Nov-2015 23:53:15] NOTICE: fpm is running, pid 18277 
[15-Nov-2015 23:53:15] ERROR: failed to prepare the stderr pipe: Too many open files (24) 
[15-Nov-2015 23:53:16] NOTICE: exiting, bye-bye! 
[15-Nov-2015 23:53:59] NOTICE: fpm is running, pid 18855 
[15-Nov-2015 23:53:59] ERROR: failed to prepare the stderr pipe: Too many open files (24) 
[15-Nov-2015 23:54:00] NOTICE: exiting, bye-bye! 
 
發(fā)現(xiàn)是系統(tǒng)允許打開的文件數(shù)超了預定的設置。需要調(diào)大這個值: 
[root@i-v5lmgh7y etc]# ulimit -n 
1024 
[root@i-v5lmgh7y etc]# ulimit -n 65535  //臨時解決辦法 
[root@i-v5lmgh7y etc]# ulimit -n 
65535 
 
 
永久解決辦法: 
在/etc/security/limits.conf文件底部添加下面四行內(nèi)容: 
[root@i-v5lmgh7y etc]# cat /etc/security/limits.conf 
......... 
# End of file 
* soft nproc unlimited 
* hard nproc unlimited 
* soft nofile 65535 
* hard nofile 65535 
 
然后再次啟動php-fpm程序,9000端口就能正常啟動了 
[root@i-v5lmgh7y etc]# /usr/local/php/sbin/php-fpm 
[root@i-v5lmgh7y etc]# ps -ef|grep php 
root 21055 1 0 00:12 ? 00:00:00 php-fpm: master process 
(/usr/local/php/etc/php-fpm.conf) 
nobody 21056 21055 0 00:12 ? 00:00:00 php-fpm: pool www 
nobody 21057 21055 0 00:12 ? 00:00:00 php-fpm: pool www

----------------------------下面梳理幾個常見的php不恰當配置引發(fā)的問題-----------------------------

1)request_terminate_timeout的值如果設置為0或者過長的時間,可能會引起file_get_contents的資源問題。 
如果訪問請求的遠程資源反應過慢,php-cgi進程就會一直卡在那里不會超時。雖然php.ini文件里面max_execution_time可以設置PHP腳本的最大執(zhí)行時間,但是,在php-cgi(php-fpm) 中該參數(shù)不會起效。真正能夠控制PHP腳本最大執(zhí)行時間的是php-fpm.conf配置文件中的request_terminate_timeout參數(shù)。 
 
request_terminate_timeout默認值為0秒,也就是說,PHP腳本會一直執(zhí)行下去。這樣當所有的php-cgi進程都卡住時,這臺Nginx+PHP的WebServer已經(jīng)無法再處理新的PHP請求了,Nginx 將給用戶返回“502 Bad Gateway”。 
修改該參數(shù),設置一個PHP腳本最大執(zhí)行時間是必要的,但是治標不治本。例如改成30s,如果發(fā)生訪問獲取網(wǎng)頁內(nèi)容較慢的情況,這就意味著150個php-cgi進程,每秒鐘只能處理5個請求,WebServer同樣很難避免”502 Bad Gateway”。 
 
解決辦法是request_terminate_timeout設置為10s或者一個合理的值。 
 
2)max_requests參數(shù)配置不當,可能會引起間歇性502錯誤 
設置每個子進程重生之前服務的請求數(shù). 對于可能存在內(nèi)存泄漏的第三方模塊來說是非常有用的. 
如果設置為0,則一直接受請求,等同于php_fcgi_max_requests環(huán)境變量。默認值為 0. 
比如:pm.max_requests = 1000 這個配置的意思是,當一個 php-cgi 進程處理的請求數(shù)累積到500個后,自動重啟該進程。 
 
但是為什么要重啟進程呢? 
一般在項目中,多多少少都會用到一些PHP的第三方庫,這些第三方庫經(jīng)常存在內(nèi)存泄漏問題,如果不定期重啟php-cgi進程,勢必造成內(nèi)存使用量不斷增長。因此php-fpm作為php-cgi的管理器,提供了這么一項監(jiān)控功能,對請求達到指定次數(shù)的php-cgi進程進行重啟,保證內(nèi)存使用量不增長。正是因為這個機制,在高并發(fā)的站點中,經(jīng)常導致502錯誤, 
目前解決方法是,把這個值盡量設置大些,盡可能減少php-cgi重新SPAWN的次數(shù),同時也能提高總體性能。在實際的生產(chǎn)環(huán)境中發(fā)現(xiàn),內(nèi)存泄漏如果不明顯,可以將這個值設置得非常大(比如204800)。要根據(jù)自己的實際情況設置這個值(比如我們線上設置1024),不能盲目地加大。 
話說回來,這套機制目的只為保證php-cgi不過分地占用內(nèi)存,為何不通過檢測內(nèi)存的方式來處理呢?通過設置進程的峰值內(nèi)在占用量來重啟php-cgi進程,會是更好的一個解決方案。 
 
3)php-fpm的慢日志,debug及異常排查神器 
request_slowlog_timeout設置一個超時的參數(shù),slowlog設置慢日志的存放位置

關(guān)于php安全配置中有哪些常見的錯誤就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI