PHP文件上傳功能實(shí)現(xiàn)邏輯分析
目錄
- 文件名字處理
- 文件內(nèi)容處理
- 文件權(quán)限處理
文件名字處理
文件名字得看業(yè)務(wù)要求。不需要保留原始名字,則隨機(jī)生成名字,拼接上白名單校驗(yàn)過的后綴即可。
反之要謹(jǐn)慎處理:
//允許上傳的后綴白名單 $extension_white_list = ["jpg", "pdf"]; //原始文件的名字 $origin_file_name = "xx/xxx/10月CPI同比上漲2.1%.php.pdf"; //提取文件后綴,并校驗(yàn)是否在白名單內(nèi) $extension = strtolower(pathinfo($origin_file_name, PATHINFO_EXTENSION)); if (!in_array($extension, $extension_white_list)) { die("錯(cuò)誤的文件類型"); } //提取文件名 $new_file_name = pathinfo($origin_file_name, PATHINFO_BASENAME); //截取掉后綴部分 $new_file_name = mb_substr($new_file_name, 0, mb_strlen($new_file_name) - 1 - mb_strlen($extension)); //只保留有限長度的名字 $new_file_name = mb_substr($new_file_name, 0, 20); //替換掉所有的 . 避免攻擊者構(gòu)造多后綴的文件,缺點(diǎn)是文件名不能包含 . $new_file_name = str_replace(".", "_", $new_file_name); //把處理過的名字和后綴拼接起來構(gòu)造成一個(gè)名字 $new_file_name = $new_file_name . "." . $extension; print_r($new_file_name); //10月CPI同比上漲2_1%_php.pdf
文件內(nèi)容處理
文件后綴只是表面,一個(gè) php 文件,把后綴改成 jpg,也改變不了它攜帶 php 代碼的事實(shí)。
針對(duì)圖片文件,可以讀取圖片文件頭判斷圖片類型,當(dāng)然我也沒測試過這個(gè)方法,感興趣的可以自測。
另外即便上述方法可行,依然可以繞過,只要在 php 文件的頭部寫入某個(gè)圖片類型的頭部特征的字節(jié)即可偽裝。
針對(duì)圖片文件內(nèi)容處理,真正的大招是重繪圖片。
windows 系統(tǒng)下用 copy 命令可以制作一個(gè)包含 php 代碼的圖片文件,命令如下:
Copy 1.jpg/b + test.php/a 2.jpg
上述命令的意思是,把 test.php 合并到 1.jpg 的尾部,并重新導(dǎo)出到 2.jpg 里面,如此一來,這個(gè) 2.jpg 就是一個(gè)包含 php 代碼的圖片文件,可以用記事本打開它,拖滾動(dòng)條到底部看到 php 代碼。
像這種不干凈的圖片,用重繪圖片的方式可以剔除掉不干凈的部分。下面是重繪圖片的 php 代碼:
try { $jpg = "包含php代碼的.jpg"; list($width, $height) = getimagesize($jpg); $im = imagecreatetruecolor($width, $height); $image = imagecreatefromjpeg($jpg); imagecopyresampled($im, $image, 0, 0, 0, 0, $width, $height, $width, $height); $target = "重繪后干凈的圖片.jpg"; imagejpeg($image, $target); } finally { isset($im) && is_resource($im) && imagedestroy($im); isset($image) && is_resource($image) && imagedestroy($image); }
這個(gè)處理辦法的缺點(diǎn)是,耗費(fèi)內(nèi)存,圖片失真,而且只能處理圖片。
當(dāng)然其它的文件格式,我也不知道能不能用重繪的思路去處理。
文件權(quán)限處理
只討論 Linux 下的權(quán)限,先簡單介紹 Linux 的權(quán)限:
讀取,字母 r 或數(shù)字 4 表示
寫入,字母 w 或數(shù)字 2 表示
執(zhí)行,字母 x 或數(shù)字 1 表示
對(duì)文件來講,rwx 是如下含義:
r:可打開讀取此文件
w:可寫入此文件
x:可執(zhí)行此文件
對(duì)目錄來講,rwx 的含義又有點(diǎn)差別:
r:可讀取此目錄的內(nèi)容列表
w:可在此目錄里面進(jìn)行:增、刪、改文件和子目錄
x:可進(jìn)入此目錄
另外 Linux 里面,針對(duì)一個(gè)文件,用戶是會(huì)被分成三種,分別是:創(chuàng)建該文件的用戶、和創(chuàng)建該文件的用戶處于同一用戶組的用戶、既不是創(chuàng)建者也不是同一個(gè)小組的其它用戶。
有了對(duì) Linux 的權(quán)限了解,針對(duì)上傳的文件所在的目錄,應(yīng)該設(shè)定 755 權(quán)限,表示:
- 創(chuàng)建該目錄的用戶有讀取、寫入、進(jìn)入此目錄的權(quán)限
- 和創(chuàng)建該目錄的用戶處于同一用戶組的用戶有讀取、進(jìn)入此目錄的權(quán)限
- 既不是創(chuàng)建者也不是同一個(gè)小組的其它用戶有讀取、進(jìn)入此目錄的權(quán)限
755 的權(quán)限設(shè)定,可以讓 nginx 代理靜態(tài)文件的時(shí)候不會(huì)報(bào) 403 錯(cuò)誤。
代碼示例:
mkdir($save_path, 0755, true);
針對(duì)上傳的文件,采用更嚴(yán)格的權(quán)限設(shè)定,應(yīng)該設(shè)定 644 權(quán)限,表示:
創(chuàng)建該文件的用戶有讀取、寫入此文件的權(quán)限,無法執(zhí)行
和創(chuàng)建該文件的用戶處于同一用戶組的用戶只有讀取權(quán)限
既不是創(chuàng)建者也不是同一個(gè)小組的其它用戶只有讀取權(quán)限
644 的權(quán)限設(shè)定,可以確保即便是上傳了一個(gè)非法文件也無法串改內(nèi)容、執(zhí)行。
代碼示例:
chmod($file, 0644);
到此這篇關(guān)于PHP文件上傳功能實(shí)現(xiàn)邏輯分析的文章就介紹到這了,更多相關(guān)PHP文件上傳內(nèi)容請(qǐng)搜索以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持!
相關(guān)文章:
