雖然已是 2018 年,但網(wǎng)上依然流傳著一些「高危 PHP 函數(shù)流码,請一定要禁用又官!」的標題黨文章(搜索關(guān)鍵字:一些需要禁用的PHP危險函數(shù))。
這些文章的內(nèi)容簡單直接漫试,給出 php.ini
的 disable_functions
的配置(包含一大堆函數(shù))六敬,說這些函數(shù)十分危險,一定要禁用驾荣,有的內(nèi)容甚至和7外构、8年前一模一樣,被開發(fā)者們奉為秘籍播掷,薪火相傳审编。
禁用危險函數(shù)在理論上是可以加強安全性,但這種做法就好比做飯時害怕用菜刀切菜傷到自己而改用手撕歧匈。搞安全一定要重視對入口的控制垒酬,而不是自廢武功,因為禁用某些函數(shù)會導(dǎo)致某些需求很難件炉、甚至不能實現(xiàn)勘究。
舉個例子。
比如 Laravel
中定時任務(wù)功能的底層使用了 Symfony/Process
妻率,其中就依賴 proc_open
函數(shù)來執(zhí)行命令(及其一系列函數(shù))乱顾,如果被禁用,定時任務(wù)就沒法用了宫静。
這里還有個小坑走净。
朋友本來有一個穩(wěn)定運行的 Laravel
項目券时,但某天為了加強安全性,就在 php.ini
里禁用了一堆函數(shù)(網(wǎng)上找來的)伏伯,其中就包含 proc_open
這些橘洞。后來他突然發(fā)現(xiàn)所有的定時任務(wù)都沒有跑了,Laravel
日志和 PHP
錯誤日志也沒有任何異常说搅。后來他猜測應(yīng)該和函數(shù)禁用行為有關(guān)炸枣,于是還原了配置,可是此時定時任務(wù)還是沒有運行弄唧。
這里的坑就在于他的所有定時任務(wù)都設(shè)置了 withoutOverlapping
适肠。當開啟這個設(shè)置之后,Laravel
在運行任務(wù)時會設(shè)置排他鎖:開始的時候檢查有沒有上鎖候引,有鎖則忽略執(zhí)行侯养,否則就上鎖,執(zhí)行命令澄干,執(zhí)行結(jié)束之后解鎖逛揩。上鎖當然沒問題,可是執(zhí)行掛了(這里應(yīng)該是靜默失敗麸俘,普通異常是會被捕捉然后解鎖的)辩稽,后面就自然沒有解鎖,所以配置恢復(fù)之后从媚,開始執(zhí)行時發(fā)現(xiàn)鎖依然存在逞泄,是不會實際執(zhí)行的。
怎么解決呢静檬?Laravel
的鎖使用的系統(tǒng)默認 Cache
炭懊,所以只需要去對應(yīng) Cache
的 driver 中刪掉鎖的緩存文件就好了,或者等待鎖過期之后也行(5.5
默認是 24 小時)拂檩。