Web安全_檔案上傳總結(前端js驗證、後端驗證)
一、檔案上傳思路
首先我們通過一個網站上傳一個非法格式的檔案
- 在瀏覽載入檔案,但還未點選上傳按鈕時便彈出對話方塊,內容如:只允許上傳.jpg/.jpeg/.png字尾名的檔案,而此時並沒有傳送資料包。
- 如果網頁未彈窗,而在頁面彈窗,則考慮後端驗證
所以就圍繞前端驗證繞過和後端驗證繞過這兩方面展開討論
二、前端驗證
JavaScript驗證的幾種繞過方式:
- 2.1 通過瀏覽器審查元素對網頁的程式碼檢視,找到對檔案格式或大小的限制然後修改即可;
- 2.2 通過Burpsuite工具對瀏覽器進行代理,抓包對包裡的內容進行修改。
- 2.3
三、後端驗證
在學後端驗證的時候先簡單瞭解一下php中關於檔案的函式
檔案操作函式
-
開啟檔案函式fopen()
語法:fopen(檔名,檔案開啟方式);
返回值:若開啟成功則返回檔案,若開啟失敗則返回false
-
返回開啟檔案資訊函式fstat()
格式:fstat(檔名);
-
關閉檔案函式fclose()
格式:fclose(檔名);
返回值:成功則返回 true,如果失敗則返回false。 -
讀檔案函式fread()
格式:fread(a,b);
a為檔案系統指標,b為讀取的最大位元組數
返回值:成功則返回讀取的內容,失敗返回false
示例:讀取指定長度的檔案
<?php
$file=fopen("1.txt","r");//此時的$file為檔案系統指標
$contents = fread($file,"10");//讀取10位元組的內容
fclose($file);
?>
示例:讀取整個檔案
<?php
$file = fopen("test.txt","r");
$contents = fread($file,filesize("test.txt"));//filesize()函式返回指定檔案的大小(位元組)
fclose($file);
?>
- 關於全域性陣列$_FILE
通過使用 PHP 的全域性陣列 $_FILES,你可以從客戶計算機向遠端伺服器上傳檔案。
第一個引數是表單的 input name,第二個下標可以是 “name”, “type”, “size”, “tmp_name” 或 “error”。就像這樣:
$_FILES[“file”][“name”] - 被上傳檔案的名稱
$_FILES[“file”][“type”] - 被上傳檔案的型別
$_FILES[“file”][“size”] - 被上傳檔案的大小,以位元組計
$_FILES[“file”][“tmp_name”] - 儲存在伺服器的檔案的臨時副本的名稱
$_FILES[“file”][“error”] - 由檔案上傳導致的錯誤程式碼
提交表單的具體結構如下圖所示:我們主要關注中間的處理程式,分析其對檔案的限制
upload.php
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<form action="uploadprocess.php" method="post" enctype="multipart/form-data">
<label for="file">檔名:</label>
<input type="file" name="file" id="file"><br>
<input type="submit" name="submit" value="提交">
</form>
</body>
</html>
uploadprocess.php
<?php
// 允許上傳的圖片字尾
$allowedExts = array("gif", "jpeg", "jpg", "png");//定義一個允許使用者上傳檔案的字尾的陣列
$temp = explode(".", $_FILES["file"]["name"]);explode函式的作用就算將第二個引數的檔名通過第一個引數為標準將其分割為多個數組
$extension = end($temp); // 獲取檔案字尾名,end表示提取陣列中最後一個元素。這裡恰好提取到字尾
//判斷MIME型別
if ((($_FILES["file"]["type"] == "image/gif")
|| ($_FILES["file"]["type"] == "image/jpeg")
|| ($_FILES["file"]["type"] == "image/jpg")
|| ($_FILES["file"]["type"] == "image/pjpeg")
|| ($_FILES["file"]["type"] == "image/x-png")
|| ($_FILES["file"]["type"] == "image/png"))
//對檔案大小進行限制
&& ($_FILES["file"]["size"] < 204800) // 小於 200 kb
&& in_array($extension, $allowedExts))//in_array函式的作用是檢視第二個陣列中是否存在第一個引數內容
{
if ($_FILES["file"]["error"] > 0)
{
echo "錯誤:: " . $_FILES["file"]["error"] . "<br>";
}
else
{
echo "上傳檔名: " . $_FILES["file"]["name"] . "<br>";
echo "檔案型別: " . $_FILES["file"]["type"] . "<br>";
echo "檔案大小: " . ($_FILES["file"]["size"] / 1024) . " kB<br>";
echo "檔案臨時儲存的位置: " . $_FILES["file"]["tmp_name"];
}
}
else
{
echo "非法的檔案格式";
}
?>
3.1黑名單限制與白名單限制
- 3.1.1黑名單限制
簡單的來說就是我不允許哪些格式上傳,其他的格式我不管。比如:不允許.php .asp格式上傳,如果你上傳的檔案的字尾與我所規定的格式匹配則會上傳失敗。
可以嘗試php3 、php4、php5、phptml或者利用伺服器解析漏洞 - 3.1.2白名單限制
白名單就是我只允許這些格式檔案上傳,其他檔案的格式我一律不允許。如:我只允許上傳jpg、png格式的檔案,假如你上傳一個php格式的檔案,則會上傳失敗。也就是說只有使用者上傳的檔案的格式與我所規定的格式匹配才會上傳成功。
顯然,白名單限制要比黑名單限制更加安全
3.2繞過的思路
- 3.2.1 截斷
截斷的原理可以類比程式設計裡的分號,如我們一條語句要以分號結尾,或者相當於把空位元組之後的內容註釋掉。具體的原理講解可參考以下博文:
[基本實驗] %00截斷攻擊的探索
CTF實驗吧-上傳繞過【0x00截斷】 - 3.2.2 MIME型別修改
伺服器除了對檔案字尾進行判斷外,還有可能對其MIME型別進行判斷。MIME型別我把它簡單理解為檔案的字尾在伺服器傳輸過程中的一個對映,如果有理解不對的地方歡迎指出。大致就是說,我檔案為jpg或者png等等格式的,抓包檢視包中的內容,檔案的型別就是image/jpeg
直接在工具中進行修改然後轉發就可以 - 3.2.3 大小寫繞過
有些網站對檔案字尾名進行限制,可以嘗試大小寫進行繞過,如:限制php,可以採用Php。
未完待學…
上傳圖片的思路:
- 判斷圖片是否感染(上傳之後再將其下載檢視裡面的程式碼是否還在)
- 判斷伺服器是否解析php(如果上傳的伺服器為單獨的圖片伺服器則有可能不會解析php等型別的程式碼)