PHP編碼安全:上傳文件安全

2021-12-29 計算機與網絡安全

一次性付費進群,長期免費索取教程,沒有付費教程。

進微信群回復公眾號:微信群;QQ群:460500587

 教程列表 見微信公眾號底部菜單 |  本文底部有推薦書籍 

微信公眾號:計算機與網絡安全

ID:Computer-network

在Web系統中,允許用戶上傳文件作為一個基本功能是必不可少的,如論壇允許用戶上傳附件,多媒體網站允許用戶上傳圖片,視頻網站允許上傳頭像、視頻等。但如果不能正確地認識到上傳帶來的風險,不加防範,會給整個系統帶來毀滅性的災難。

在PHP項目中,提供上傳功能並在伺服器端未對上傳的文件格式進行合理的校驗是存在巨大風險的。如果惡意攻擊者利用上傳漏洞上傳一些webshell,則可能完全控制整個網站程序,執行系統命令,獲取資料庫連結字串進行操作資料庫等危險操作。

1、文件上傳漏洞

以下是一個不安全的上傳代碼示例,即文件上傳PHP接收代碼upload.php。

<?php

$upload_dir='uploads'; // 用戶上傳文件保存目錄

$upload_file=$upload_dir.basename($_FILES['userfile']['name']);

if(move_uploaded_file($_FILES['userfile']['tmp_name'],$uploadfile)) {

echo "恭喜您,文件上傳成功";

} else {

echo "文件上傳失敗";

}

?>

以下是文件上傳HTML代碼upload.html。

<form name="upload" action="upload.php" method="POST" ENCTYPE="multipart/form-data">

請選擇上傳文件:

<input type"file" name="userfile">

<input type"submit" name="upload" value="上傳">

</form>

這是一個簡單的上傳文件功能,其中由用戶上傳文件,如果上傳成功,保存文件的路徑為http://伺服器路徑/uploads/文件名稱。

如果攻擊者上傳一個如下內容的hacker.php腳本文件到伺服器:

<?php

system($_GET['shell']);

?>

則攻擊者就可以通過該文件進行URL請求http://伺服器路徑/uploads/hacker.php?shell=ls%20-al,從而可以執行任何shell命令。

圖1所示是惡意腳本的執行結果,其中列出了該目錄下的所有文件。

圖1  上傳漏洞造成的webshell執行結果

2、檢查文件類型防止上傳漏洞

上面例子中的代碼非常簡單,並沒有進行任何的上傳限制。如果要限制,通常的做法是限制文件上傳類型。

下面在PHP代碼中增加了文件類型限制來防止上傳漏洞。

<?php

if($_FILES['userfile']['type']!="image/gif") {

die("請上傳正確的文件類型");

}

$uploaddir='uploads';

$uploadfile=$uploaddir.basename($_FILES['userfile']['name']);

if(move_uploaded_file($_FILES['userfile']['tmp_name'],$uploadfile)) {

echo "恭喜您,文件上傳成功";

} else {

echo "文件上傳失敗";

}

?>

在這種情況下,如果攻擊者試圖上傳shell.php,則應用程式在上傳請求中將檢查文件MIME類型。以下是拒絕上傳的HTTP請求返回數據包。

POST /upload.php HTTP/1.1

TE: deflate,gzip;q=0.3

Connection: TE,close

Host: localhost:8080

User-Agent: Mozilla/5.0(Macintosh: Inter Mac OS X10_13_2)

AppleWebKit/537.36(KHTML,like gecko) Chrome/65.0.3325.181

Safari/537.36

Content-Type: multipart/form-data;boundary=xYzzY

Content-Length:32

--s76f8a7sf8as9f8a9f80as8df--

Content-Disposition: form-data;name="userfile";filename="shell.php"

Content-Type: text/plain

<?php

system($_GET['shell']);

?>

--s76f8a7sf8as9f8a9f80as8df--

HTTP/1.1 200 OK

Date: Thu, 31 May 2019 22:00:01 GMT

Server: Apache

X-Powered-By: PHP/5.6

Content-Length: 30

Connection: close

Content-Type: text/html

請上傳正確的文件類型

這裡成功地通過檢測類型防止了非授權類型文件的上傳,伺服器拒絕接收文件。

但是如果只進行上傳文件類型的檢查也是不夠的,攻擊者通過修改POST數據包中Content-Type:text/plain欄位為Content-Type:image/gif,然後發送數據包,即可成功實現惡意腳本的上傳。

3、檢查文件擴展名稱防止上傳漏洞

除了檢查文件類型外,研發人員最常用的防範方法之一,就是基於白名單或者黑名單,驗證所傳文件的擴展名稱是否符合。以下代碼通過黑名單方式對文件類型進行限制。

<?php

$blacklist=array(".php","phtml",".php3",".php4"); // 黑名單

$uploaddir='uploads/';

$uploadfile=$uploaddir.basename($_FILES['userfile']['name']);

$item==substr($_FILES['userfile']['name'],-4);

if(in_array($item,$whitelist)) {

die("請上傳正確的文件類型");

}

if(move_uploaded_file($_FILES['userfile']['tmp_name'],$uploadfile)) {

echo "恭喜您,文件上傳成功";

} else {

echo "上傳失敗";

}

?>

以下是白名單模式限制文件類型的代碼示例。

<?php

$whitelist=array(".jpg",".gif","png"); //白名單

$uploaddir='uploads/';

$uploadfile=$uploaddir.basename($_FILES['userfile']['name']);

$item==substr($_FILES['userfile']['name'],-4);

if(!in_array($item,$whitelist)) {

die("請上傳正確的文件類型");

}

if(move_uploaded_file($_FILES['userfile']['tmp_name'],$uploadfile)) {

echo "恭喜您,文件上傳成功";

} else {

echo "上傳文件失敗";

}

?>

從黑名單和白名單兩種不同的驗證方法來看,白名單方式絕對要比黑名單安全得多。但是,並不是說採用白名單方式驗證就足夠安全了。

IIS服務存在一個漏洞(Microsoft Internet Infomation Server 6.0 ISAPI Filename Analytic Vulnerability),如上傳一個名為hacker.php;.gif的文件到伺服器,PHP腳本文件因限制最後4個字符,所以本文件是合法的,但是當上傳後瀏覽該文件——http://伺服器路徑/uploads/hacker.php;.gif時,就可以繞過Web程序的邏輯檢查,從而能導致伺服器以IIS進程權限執行任意惡意用戶定義的腳本。此漏洞只針對於IIS特定版本。

在Apache程序中,同樣存在一個由擴展名解析的漏洞。當惡意攻擊上傳一個有多個擴展名的PHP腳本文件時,如果最後的擴展名未定義,就會解析前一個擴展,比如hacker.php.2018文件。當將該文件上傳時,如果是以白名單、黑名單方式進行驗證,就可以繞過驗證,上傳非法文件到伺服器,當瀏覽http://伺服器路徑/uploads/hacker.php.2018時,就會被當成PHP腳本執行。

4、文件上傳漏洞的綜合防護

以上例子說明,不可以只通過一種安全手段來阻止攻擊者進行非法文件上傳,應該同時綜合應用檢測文件類型、檢查文件後綴、黑白名單、使用隨機文件名稱等多種方法進行防範。下面的代碼是綜合應用示例。

<?php

/**

* 生成隨機字符串

* @param int $len

* $return string

*/

function genRandomString($len) {

$chars=array("a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","0","1","2","3","4","5","6","7","8","9");

$charsLen=count($chars)-1;

shuffle($chars); // 將精妙絕倫打亂

$output="";

for($i=0;$i<=$len;$i++) {

$output.=$chars[mt_rand(0,$charsLen)];

}

return $output;

}

$whitelist=array(".jpg",".gif","png"); //白名單

$item==substr($_FILES['userfile']['name'],-4);

if(!in_array($item,$whitelist)) {

die("請上傳正確的文件類型");

}

if($_FILES['userfile']['type']!="image/gif") { // 校驗文件MIME類型

die("請上傳正確的文件類型");

}

$uploaddir='/tmp/uploads'; // 將用戶上傳的文件放到項目目錄之外

$uploadfile=$uploaddir.genRandomString(20).$item; // 使用隨機文件名

if(move_uploaded_file($_FILES['userfile']['tmp_name'],$uploadfile)) {

echo "恭喜您,文件上傳成功";

} else {

echo "上傳文件失敗";

}

?>

驗證上傳文件的擴展名,以白名單、黑名單方式為主,但最好使用白名單。

除了在代碼邏輯中防止上傳漏洞外,同時也可以在項目部署時將上傳目錄放到項目工程目錄之外,當作靜態資源文件處理,並且對文件的權限進行設定,禁止文件的執行權限。

當用戶上傳文件到伺服器保存時,一定要使用隨機文件名進行存儲,並保證所存儲的擴展名合法。保證文件名的唯一性,也保證了存儲的安全性,可以防止上傳文件非法擴展進行解析。

微信公眾號:計算機與網絡安全

ID:Computer-network

相關焦點

  • 安全從我做起--PHP安全編碼
    1.1 PHP中驗證用戶的輸入這裡特別要注意php.ini中的register_globals的設定,在早期的php版本中是默認開啟的,這會導致很嚴重的安全問題:更安全的代碼應該給$admin賦默認FALSE值:上面這段代碼看起來是安全的,但是如果register_globals開啟了的話,在訪問的url
  • PHP編碼安全:請求偽造攻擊
    很多網站提供了通過用戶指定的URL上傳圖片和文件的功能,可以將第三方的圖片和文件直接保存在當前的Web系統上,如果用戶輸入的URL是無效的,大部分的Web應用會返回錯誤信息。攻擊者可以輸入一些不常見但有效的URL,比如以下URL。
  • 【php安全】--文件讀取漏洞
    等,可以利用PHP輸入輸出流php://filter/來讀取文件。Phpcmsv9在2012年被爆出任意文件讀取漏洞,當時也有很多企業因為這個漏洞被入侵,漏洞文件/phpcms/modules/search/index.php  public_的get_suggest_keyword函數,代碼如下:public        function public_get_suggest_keyword(){        $url
  • 從建站打拿站 -- PHP(文件上傳)
    李白寫過那麼多詩,他自己會背麼?
  • web安全篇(一):PHP文件包含漏洞姿勢總結
    文件包含漏洞的形成,簡單來說,需要滿足兩個條件:2、include()等函數通過動態變量的方式引入需要包含的文件`0×02 涉及文件上傳的危險函數php中引發文件包含漏洞的通常是以下四個函數:include()include_once
  • 滲透測試 對文件上傳安全檢測與webshell分析
    前段時間我們SINE安全收到客戶的滲透測試服務委託,在這之前,客戶網站受到攻擊,數據被篡改,要求我們對網站進行全面的滲透測試,包括漏洞的檢測與測試,邏輯漏洞.垂直水平越權漏洞,文件上傳漏洞.等等服務項目,在進行安全測試之前,我們對客戶的網站大體的了解了一下,整個平臺網站,包括APP,安卓端,IOS端都採用的JSP+oracle資料庫架構開發,前端使用VUE,伺服器是linux
  • PHP任意文件上傳漏洞(CVE-2015-2348)
    在上傳文件的時候只判斷文件名是合法的文件名就斷定這個文件不是惡意文件,這確實會導致其他安全問題。並且在這種情況下,在你自己的文件中檢查漏洞很不現實,因為這個漏洞可以繞過你對文件名後綴、文件類型(Content-Type)、Mime type、文件大小等的檢查,所以僅僅依靠這些檢查是救不了你的。
  • PHP上傳文件和下載
    4、$_FILES["myfile"]["tmp_name"]中的值是:文件被上傳後在伺服器存儲的臨時全路徑。5、$_FILES["myfile"]["error"]中的值是:文件上傳的錯誤代碼-php 4.2以後增加的功能。關於 error 文件上傳的錯誤代碼:UPLOAD_ERR_OK其值為 0,沒有錯誤發生,文件上傳成功。
  • php文件包含漏洞 - 乾貨
    php中上傳文件,會創建臨時文件。在linux下使用/tmp目錄,而在windows下使用c:\winsdows\temp目錄。在臨時文件被刪除之前,利用競爭即可包含該臨時文件。由於包含需要知道包含的文件名。
  • [網絡安全] 十五.文件上傳漏洞 (4)Upload-labs靶場及CTF題目01-10
    Upload-labs是一個使用php語言編寫,專門收集滲透測試和CTF中遇到的各種上傳漏洞的靶場,旨在幫助大家對上傳漏洞有一個全面的了解。目前一共20關,每一關都包含不同的上傳方式。項目地址:運行環境:文件上傳漏洞的思維導圖如下所示,詳細覆蓋了我們前面三篇文章的各種方法。
  • 【每日小知識】3 PHP文件上傳方法詳解及其信息解析
    文章來自:PHP中文網用php實現文件上傳功能在PHP項目開發中是比較常見的,但是對於一些新手來說或許有些難度
  • PHP代碼安全
    ,用base64_decode可以解密獲取 加密主鍵、載荷等重要信息,所以通常需要對JWT的token進行二次加密限制上傳文件的類型對於一個圖片上傳的接口,如果沒有對上傳文件的格式做限制,攻擊者很有可能把 .php後綴的文件上傳到public/images目錄下,然後通過根目錄執行這個文件。
  • PHP 文件包含漏洞姿勢總結
    ./ 上一級目錄,這樣的遍歷目錄來讀取文件包含圖片木馬命令行下執行:copy x.jpg /b + s.php /b f.jpg上傳 f.jpg、找到 f.jpg 路徑、包含 f.jpg包含日誌利用條件:需要知道伺服器日誌的存儲路徑,且日誌文件可讀。
  • Web安全之文件包含漏洞
    4、文件包含漏洞危害1、讀取web配置文件以及敏感的數據2、web伺服器的文件被外界瀏覽導致信息洩露;3、與文件上傳漏洞組合getshell,將惡意代碼執行解析一般來說,遠程文件包含漏洞危害更大二、文件包含漏洞利用1、偽協議利用file://http://php://僅能夠對伺服器本地的文件進行包含
  • Linux寶塔面板創建站點PHP+MySQL及寶塔面板站點上傳文件教程
    PHP版本,一般選擇php-54就可以了。寶塔面板創建站點後,在根目錄會自動生成下面四個文件,其中index.html文件打開後如下圖所示:index.html這個沒有用,可以刪除,其他三個不要動江邊鳥主機 的網站站點就是這樣創建的,但是寶塔面板創建站點後如何上傳文件呢
  • php使用ftp實現文件上傳與下載功能
    (商務合作聯繫QQ號:2230304070)http://www.jb51.net/article/120024.htm本文實例為大家分享了php ftp文件上傳與下載的具體代碼,供大家參考,具體內容如下ftp文件上傳
  • 原創 | "白話"PHP文件包含漏洞
    接下來聊聊什麼是文件包含漏洞(以下探究,力求用最基本的環境去闡述漏洞產生的原理)在上面的實例中,可以知道include()函數靜態包含了functions.php文件,也就是,客戶端的用戶是不能隨意修改的,但是如果include()採用動態包含的方式去包含文件,且未做好安全措施,就有可能產生文件文件包含漏洞,下面來看一個採用include()動態包含文件的例子。
  • PHP實現多個文件上傳的簡單方法有哪些?
    在此知識內容介紹之前,我們在前面的文章【PHP文件上傳方法詳解及其信息解析】中已經為大家詳細介紹了php實現單個文件上傳的具體方法,那麼這篇文章和今天要介紹的知識點是有關聯的,需要的朋友可以先參考學習下。
  • 【技術分享】從淺入深學習PHP文件包含
    >zip://文件路徑/zip文件名稱#壓縮包內的文件名稱 (使用時注意將#號進行URL編碼)phar://文件路徑/phar文件名稱/phar內的文件名稱phar://協議與zip://類似,同樣可以訪問zip格式壓縮包內容
  • PHP文件包含漏洞利用思路與Bypass總結手冊(完結)
    session.upload_progress.enabled = on:默認開啟這個選項,表示upload_progress功能開始,PHP 能夠在每一個文件上傳時監測上傳進度。這個信息對上傳請求自身並沒有什麼幫助,但在文件上傳時應用可以發送一個POST請求到終端(例如通過XHR)來檢查這個狀態。