檔案上傳漏洞

來源:互聯網
上載者:User

標籤:

漏洞描述

開發中檔案上傳功能很常見,作為開發人員,在完成功能的基礎上我們一般也要做好安全防護。
檔案處理一般包含兩項功能,使用者上傳和展示檔案,如上傳頭像。

檔案上傳攻擊樣本
upload.php

<?php$uploaddir = ‘uploads/‘; $uploadfile = $uploaddir . basename($_FILES[‘userfile‘][‘name‘]);if (move_uploaded_file($_FILES[‘userfile‘][‘tmp_name‘], $uploadfile)){    echo "File is valid, and was successfully uploaded.\n";} else {    echo "File uploading failed.\n";}?>

upload.html

<form name="upload" action="upload1.php" method="POST" ENCTYPE="multipart/formdata">Select the file to upload: <input type="file" name="userfile"><input type="submit" name="upload" value="upload"></form>

上述代碼未經過任何驗證,惡意使用者可以上傳php檔案,代碼如下

<?php eval($_GET[‘command‘]);?>

惡意使用者可以通過訪問 如http://server/uploads/shell.php?command=phpinfo(); 來執行遠程命令

Content-type驗證

upload.php

<?phpif($_FILES[‘userfile‘][‘type‘] != "image/gif") {//擷取Http要求標頭資訊中ContentType    echo "Sorry, we only allow uploading GIF images";    exit;}$uploaddir = ‘uploads/‘;$uploadfile = $uploaddir.basename($_FILES[‘userfile‘][‘name‘]);if (move_uploaded_file($_FILES[‘userfile‘][‘tmp_name‘], $uploadfile)){    echo "File is valid, and was successfully uploaded.\n";} else {    echo "File uploading failed.\n";}?>


該方式是通過Http要求標頭資訊進行驗證,可通過修改Content-type ==> image/jpg繞過驗證,可以通過指令碼或BurpSuite、fiddle修改
如下
Content-Disposition: form-data; name="userfile"; filename="shell.php"
Content-Type: image/gif

圖片類型驗證
該方法通過讀取檔案頭中檔案類型資訊,擷取檔案類型

備忘:如JPEG/JPG檔案頭標識為FFD8

upload.php

<?php$imageinfo = getimagesize($_FILES[‘userfile‘][‘tmp_name‘]);if($imageinfo[‘mime‘] != ‘image/gif‘ && $imageinfo[‘mime‘] != ‘image/jpeg‘) {    echo "Sorry, we only accept GIF and JPEG images\n";    exit;}$uploaddir = ‘uploads/‘;$uploadfile = $uploaddir . basename($_FILES[‘userfile‘][‘name‘]);if (move_uploaded_file($_FILES[‘userfile‘][‘tmp_name‘], $uploadfile)){    echo "File is valid, and was successfully uploaded.\n";} else {    echo "File uploading failed.\n";}?>

可以通過圖片添加註釋來繞過此驗證。
如添加註釋<?php phpinfo(); ?>,儲存圖片後將其副檔名改為php,則可成功上傳。
上傳成功後訪問該檔案則可看到如下顯示

 

副檔名驗證

 通過黑名單或白名單對副檔名進行過濾,如下代碼

upload.php

<?php$blacklist = array(".php", ".phtml", ".php3", ".php4");foreach ($blacklist as $item) {if(preg_match("/$item\$/i", $_FILES[‘userfile‘][‘name‘])) {    echo "We do not allow uploading PHP files\n";    exit;}}$uploaddir = ‘uploads/‘;$uploadfile = $uploaddir . basename($_FILES[‘userfile‘][‘name‘]);if (move_uploaded_file($_FILES[‘userfile‘][‘tmp_name‘], $uploadfile)){    echo "File is valid, and was successfully uploaded.\n";} else {    echo "File uploading failed.\n";}?>

當黑名單不全,構造特殊檔案名稱可以繞過副檔名驗證

直接存取上傳的檔案
將上傳檔案儲存在非web root下其他檔案夾下,可以防止使用者通過路徑直接存取到檔案。
upload.php

<?php$uploaddir = ‘d:/uploads/‘;$uploadfile = $uploaddir . basename($_FILES[‘userfile‘][‘name‘]);if (move_uploaded_file($_FILES[‘userfile‘][‘tmp_name‘], $uploadfile)) {  echo "File is valid, and was successfully uploaded.\n";} else {  echo "File uploading failed.\n";}?>

使用者不可以直接通過http://localhost/uploads/ 來訪問檔案,必須通過view.php來訪問
view.php

<?php$uploaddir = ‘d:/uploads/‘;$name = $_GET[‘name‘];readfile($uploaddir.$name);?>

查看檔案代碼未驗證檔案名稱,使用者可以通過例如http://localhost/view.php?name=..//php/upload.php,查看指定的檔案


解決漏洞樣本

upload.php

<?phprequire_once ‘DB.php‘;$uploaddir = ‘D:/uploads/‘; $uploadfile = tempnam($uploaddir, "upload_");if (move_uploaded_file($_FILES[‘userfile‘][‘tmp_name‘], $uploadfile)) {  $db =& DB::connect("mysql://username:[email protected]/database");  if(PEAR::isError($db)) {    unlink($uploadfile);    die "Error connecting to the database";  }  $res = $db->query("INSERT INTO uploads SET name=?, original_name=?,mime_type=?",
      array(basename($uploadfile,basename($_FILES[‘userfile‘][‘name‘]),$_FILES[‘userfile‘][‘type‘]));  if(PEAR::isError($res)) {    unlink($uploadfile);    die "Error saving data to the database. The file was not uploaded";  }  $id = $db->getOne(‘SELECT LAST_INSERT_ID() FROM uploads‘);  echo "File is valid, and was successfully uploaded. You can view it <a href=\"view.php?id=$id\">here</a>\n";} else {  echo "File uploading failed.\n";}?>

  view.php

<?phprequire_once ‘DB.php‘;$uploaddir = ‘D:/uploads/‘;$id = $_GET[‘id‘];if(!is_numeric($id)) {  die("File id must be numeric");}$db =& DB::connect("mysql://[email protected]/db");if(PEAR::isError($db)) {  die("Error connecting to the database");}$file = $db->getRow(‘SELECT name, mime_type FROM uploads WHERE id=?‘,array($id), DB_FETCHMODE_ASSOC);if(PEAR::isError($file)) {  die("Error fetching data from the database");}if(is_null($file) || count($file)==0) {  die("File not found");}header("Content-Type: " . $file[‘mime_type‘]);readfile($uploaddir.$file[‘name‘]);?>

上述代碼檔案名稱隨機更改,檔案被儲存在web root之外,使用者通過id在資料庫中查詢檔案名稱,讀取檔案,可以有效阻止上述漏洞發生

總結

通過以上樣本分析,可總結一下幾點

1.檔案名稱修改,不使用使用者上傳的檔案名稱

2.使用者不可以通過上傳路徑直接存取檔案

3.檔案查看採用資料庫擷取檔案名稱,從而在相應檔案伺服器讀取檔案

4.檔案上傳限制檔案大小,個人上傳數量等

檔案上傳漏洞

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.