你不知道的文件上傳漏洞php代碼分析
漏洞描述
開發(fā)中文件上傳功能很常見,作為開發(fā)者,在完成功能的基礎(chǔ)上我們一般也要做好安全防護(hù)。
文件處理一般包含兩項(xiàng)功能,用戶上傳和展示文件,如上傳頭像。
文件上傳攻擊示例
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>
上述代碼未經(jīng)過任何驗(yàn)證,惡意用戶可以上傳php文件,代碼如下
<?php eval($_GET['command']);?>
惡意用戶可以通過訪問 如http://server/uploads/shell.php?command=phpinfo(); 來執(zhí)行遠(yuǎn)程命令
Content-type驗(yàn)證
upload.php
<?php if($_FILES['userfile']['type'] != "image/gif") {//獲取Http請(qǐng)求頭信息中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請(qǐng)求頭信息進(jìn)行驗(yàn)證,可通過修改Content-type ==> image/jpg繞過驗(yàn)證,可以通過腳本或BurpSuite、fiddle修改
如下
Content-Disposition: form-data; name="userfile"; filename="shell.php"
Content-Type: image/gif
圖片類型驗(yàn)證
該方法通過讀取文件頭中文件類型信息,獲取文件類型
備注:如JPEG/JPG文件頭標(biāo)識(shí)為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"; } ?>
可以通過圖片添加注釋來繞過此驗(yàn)證。
如添加注釋<?php phpinfo(); ?>,保存圖片后將其擴(kuò)展名改為php,則可成功上傳。
上傳成功后訪問該文件則可看到如下顯示
文件擴(kuò)展名驗(yàn)證
通過黑名單或白名單對(duì)文件擴(kuò)展名進(jìn)行過濾,如下代碼
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"; } ?>
當(dāng)黑名單不全,構(gòu)造特殊文件名可以繞過擴(kuò)展名驗(yà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); ?>
查看文件代碼未驗(yàn)證文件名,用戶可以通過例如http://localhost/view.php?name=..//php/upload.php,查看指定的文件
解決漏洞示例
upload.php
<?php require_once 'DB.php'; $uploaddir = 'D:/uploads/'; $uploadfile = tempnam($uploaddir, "upload_"); if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) { $db =& DB::connect("mysql://username:password@localhost/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
<?php require_once 'DB.php'; $uploaddir = 'D:/uploads/'; $id = $_GET['id']; if(!is_numeric($id)) { die("File id must be numeric"); } $db =& DB::connect("mysql://root@localhost/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']); ?>
上述代碼文件名隨機(jī)更改,文件被存儲(chǔ)在web root之外,用戶通過id在數(shù)據(jù)庫中查詢文件名,讀取文件,可以有效的阻止上述漏洞發(fā)生
總結(jié)
通過以上示例分析,可總結(jié)一下幾點(diǎn)
1.文件名修改,不使用用戶上傳的文件名
2.用戶不可以通過上傳路徑直接訪問文件
3.文件查看采用數(shù)據(jù)庫獲取文件名,從而在相應(yīng)文件服務(wù)器讀取文件
4.文件上傳限制文件大小,個(gè)人上傳數(shù)量等
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
PHP快速導(dǎo)出百萬級(jí)數(shù)據(jù)到CSV或者EXCEL文件
這篇文章主要介紹了PHP快速導(dǎo)出百萬級(jí)數(shù)據(jù)到CSV或者EXCEL文件,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11Laravel框架自定義驗(yàn)證過程實(shí)例分析
這篇文章主要介紹了Laravel框架自定義驗(yàn)證過程,結(jié)合實(shí)例形式分析了Laravel框架自定義驗(yàn)證的相關(guān)原理、路由、模型等操作技巧,需要的朋友可以參考下2019-02-02laravel 輸出最后執(zhí)行sql 附:whereIn的使用方法
今天小編就為大家分享一篇laravel 輸出最后執(zhí)行sql 附:whereIn的使用方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-10-10phpStudy配置多站點(diǎn)多域名方法及遇到的403錯(cuò)誤解決方法
這篇文章主要介紹了phpStudy配置多站點(diǎn)多域名方法及遇到的403錯(cuò)誤解決方法,需要的朋友可以參考下2017-10-10PHP的fsockopen、pfsockopen函數(shù)被主機(jī)商禁用的解決辦法
這篇文章主要介紹了PHP的fsockopen、pfsockopen函數(shù)被主機(jī)商禁用的解決辦法,一是使用stream_socket_client函數(shù)代替,二是寫一個(gè)類似fsockopen功能的自定義函數(shù),需要的朋友可以參考下2014-07-07自定義Laravel (monolog)日志位置,并增加請(qǐng)求ID的實(shí)現(xiàn)
今天小編就為大家分享一篇自定義Laravel (monolog)日志位置,并增加請(qǐng)求ID的實(shí)現(xiàn),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-10-10php生成隨機(jī)密碼自定義函數(shù)代碼(簡(jiǎn)單快速)
創(chuàng)建大量用戶時(shí)一個(gè)一個(gè)想密碼是讓人頭疼的事,使用php隨機(jī)生成一個(gè)安全可靠的密碼,又方便又快捷,可以添加自己想的字符串,可以用在FTP密碼、Mysql密碼、網(wǎng)站后臺(tái)密碼等地方2014-05-05