日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

文件上传漏洞——upload-labs(11-20)

發布時間:2024/9/30 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 文件上传漏洞——upload-labs(11-20) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言:上次文件上傳漏洞學習到第十關,這次繼續學習

第十一關

分析源碼

前面幾行代碼都是對后綴名進行限制,最重要的就是這一句代碼

$img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;

發現save_path用戶是可控的,那么就利用%00截斷來繞過

在此之前,先來了解一下截斷上傳的原理

在url中%00表示ascll碼中的0 ,而ascii中0作為特殊字符保留,表示字符串結束,所以當url中出現%00時就會認為讀取已結束,而忽略后面上傳的文件或圖片,只上傳截斷前的文件或圖片

可以通過一個例子詳解的了解一下

<% path="upload/web/" file="1.jpg" upfilename=path & file '最后的上傳地址 %>

將路徑改為path="upload/web/1.php%00",那么拼接之后,文件上傳時就變成了
"upload/web/1.php%001.jpg",這時上傳便將1.php上傳進去,而1.jpg則被截斷,我理解的就是相對于省略符號,將后面的內容給省略了,相當于MySQL注入語句中的#、--+等

下面就來做題,幾乎是一模一樣

上傳成功

不過在上傳時我才明白,原來截斷了1 .jpg,但是1.jpg的內容是被1.php給繼承過去了,我還一直認為是必須自己創建1.php, 里面包含內容那。。。,這次真的學習到了

方法:%00截斷

附上大師傅們的博客
截斷上傳原理剖析
00截斷原理分析

差點忘記了最重要的一條,要進行配置才能進行%00繞過

截斷條件:

  • php版本要小于5.3.4
  • magic_quotes_gpc需要為Off狀態


  • 找到并修改即可

    第十二關

    分析源碼

    和十一關的代碼基本相同,但是有一個點是不同的$_POST['save_path'],save_path是通過post傳進來的,只是傳進來的方式不同,繞過的方法應該還是%00截斷

    但是這次不能直接抓包在后面加上%00,因為post不會像get一樣對%00進行自動解碼,所以得換另一種方法進行%00繞過,查看大師傅的做法才知道要在二進制中進行修改


    將70 68 70后面的2b改為00即可繞過

    上傳成功

    方法:%00截斷

    第十三關

    那就先來做圖片木馬

    輸入命令

    copy 1.jpg /b + 1.php /a shell.jpg

    一句話木馬確實已經插入

    接下來就結合文件包含漏洞將圖片中的php文件進行解析

    upload-labs自帶有文件包含漏洞

    http://127.0.0.1/upload/include.php?file=upload/2020190806155326.jpg


    解析成功

    分析一下源碼

    function getReailFileType($filename){$file = fopen($filename, "rb");//fopen() 函數打開文件或者 URL,"r" 只讀方式打開,將文件指針指向文件頭$bin = fread($file, 2); //只讀2字節fclose($file);$strInfo = @unpack("C2chars", $bin); $typeCode = intval($strInfo['chars1'].$strInfo['chars2']); $fileType = ''; switch($typeCode){ case 255216: $fileType = 'jpg';break;case 13780: $fileType = 'png';break; case 7173: $fileType = 'gif';break;default: $fileType = 'unknown';} return $fileType; }$is_upload = false; $msg = null; if(isset($_POST['submit'])){$temp_file = $_FILES['upload_file']['tmp_name'];$file_type = getReailFileType($temp_file);if($file_type == 'unknown'){$msg = "文件未知,上傳失敗!";}else{$img_path = UPLOAD_PATH."/".rand(10, 99).date("YmdHis").".".$file_type;if(move_uploaded_file($temp_file,$img_path)){$is_upload = true;} else {$msg = "上傳出錯!";}} }

    可以看出做出限制的是這一段代碼

    $bin = fread($file, 2); //只讀2字節

    通過讀文件的前2個字節判斷文件類型,沒有其他防護,所以可以上傳圖片馬解析即可

    第十四關

    用十三關的圖片馬一樣可以解析

    分析一下源碼

    function isImage($filename){$types = '.jpeg|.png|.gif';if(file_exists($filename)){$info = getimagesize($filename);//getimagesize() 函數用于獲取圖像大小及相關信息$ext = image_type_to_extension($info[2]);//image_type_to_extension — 根據指定的圖像類型返回對應的后綴名。if(stripos($types,$ext)>=0){return $ext;}else{return false;}}else{return false;} }$is_upload = false; $msg = null; if(isset($_POST['submit'])){$temp_file = $_FILES['upload_file']['tmp_name'];$res = isImage($temp_file);if(!$res){$msg = "文件未知,上傳失敗!";}else{$img_path = UPLOAD_PATH."/".rand(10, 99).date("YmdHis").$res;if(move_uploaded_file($temp_file,$img_path)){$is_upload = true;} else {$msg = "上傳出錯!";}} }

    進行限制的是這兩段代碼

    $info = getimagesize($filename);$ext = image_type_to_extension($info[2]);

    通過使用getimagesize()檢查是否為圖片文件,所以還是可以用第十三關的圖片馬繞過

    第十五關

    查看一下源碼

    function isImage($filename){//需要開啟php_exif模塊$image_type = exif_imagetype($filename);switch ($image_type) {case IMAGETYPE_GIF:return "gif";break;case IMAGETYPE_JPEG:return "jpg";break;case IMAGETYPE_PNG:return "png";break; default:return false;break;} }$is_upload = false; $msg = null; if(isset($_POST['submit'])){$temp_file = $_FILES['upload_file']['tmp_name'];$res = isImage($temp_file);if(!$res){$msg = "文件未知,上傳失敗!";}else{$img_path = UPLOAD_PATH."/".rand(10, 99).date("YmdHis").".".$res;if(move_uploaded_file($temp_file,$img_path)){$is_upload = true;} else {$msg = "上傳出錯!";}} }

    做出限制的代碼為:

    $image_type = exif_imagetype($filename);

    exif_imagetype函數獲取圖片類型,使用exif_imagetype()檢查是否為圖片文件
    ,所以還是可以用第十關的方法,這幾關可以了解一些獲取圖片類型的函數

    第十六關

    如果還使用第十三關的圖片馬,發現其中的PHP代碼沒有解析出來,分析一下源碼,看下源碼都做出了那些限制

    $is_upload = false; $msg = null; if (isset($_POST['submit'])){// 獲得上傳文件的基本信息,文件名,類型,大小,臨時文件路徑$filename = $_FILES['upload_file']['name'];$filetype = $_FILES['upload_file']['type'];$tmpname = $_FILES['upload_file']['tmp_name'];$target_path=UPLOAD_PATH.'/'.basename($filename);// 獲得上傳文件的擴展名$fileext= substr(strrchr($filename,"."),1);//判斷文件后綴與類型,合法才進行上傳操作if(($fileext == "jpg") && ($filetype=="image/jpeg")){if(move_uploaded_file($tmpname,$target_path)){//使用上傳的圖片生成新的圖片$im = imagecreatefromjpeg($target_path); //imagecreatefromjpeg():創建一塊畫布,并從 JPEG 文件或 URL 地址載入一副圖像if($im == false){$msg = "該文件不是jpg格式的圖片!";@unlink($target_path);}else{//給新圖片指定文件名srand(time());$newfilename = strval(rand()).".jpg";//顯示二次渲染后的圖片(使用用戶上傳圖片生成的新圖片)$img_path = UPLOAD_PATH.'/'.$newfilename;imagejpeg($im,$img_path);@unlink($target_path);$is_upload = true;}} else {$msg = "上傳出錯!";}}else if(($fileext == "png") && ($filetype=="image/png")){if(move_uploaded_file($tmpname,$target_path)){//使用上傳的圖片生成新的圖片$im = imagecreatefrompng($target_path);if($im == false){$msg = "該文件不是png格式的圖片!";@unlink($target_path);}else{//給新圖片指定文件名srand(time());$newfilename = strval(rand()).".png";//顯示二次渲染后的圖片(使用用戶上傳圖片生成的新圖片)$img_path = UPLOAD_PATH.'/'.$newfilename;imagepng($im,$img_path);@unlink($target_path);$is_upload = true; }} else {$msg = "上傳出錯!";}}else if(($fileext == "gif") && ($filetype=="image/gif")){if(move_uploaded_file($tmpname,$target_path)){//使用上傳的圖片生成新的圖片$im = imagecreatefromgif($target_path);if($im == false){$msg = "該文件不是gif格式的圖片!";@unlink($target_path);}else{//給新圖片指定文件名srand(time());$newfilename = strval(rand()).".gif";//顯示二次渲染后的圖片(使用用戶上傳圖片生成的新圖片)$img_path = UPLOAD_PATH.'/'.$newfilename;imagegif($im,$img_path);@unlink($target_path);$is_upload = true;}} else {$msg = "上傳出錯!";}}else{$msg = "只允許上傳后綴為.jpg|.png|.gif的圖片文件!";} }

    先來了解一下代碼中出現的一些函數

    imagecreatefromgif():創建一塊畫布,并從 GIF 文件或 URL 地址載入一副圖像 imagecreatefromjpeg():創建一塊畫布,并從 JPEG 文件或 URL 地址載入一副圖像 imagecreatefrompng():創建一塊畫布,并從 PNG 文件或 URL 地址載入一副圖像 imagecreatefromwbmp():創建一塊畫布,并從 WBMP 文件或 URL 地址載入一副圖像 imagecreatefromstring():創建一塊畫布,并從字符串中的圖像流新建一副圖像 move_uploaded_file() 函數將上傳的文件移動到新位置。

    上面的代碼判斷了文件后綴和content-type,而且后面的代碼又考察了二次渲染
    看了很多大師傅們的博客,都說這道題考查的是圖像的二次渲染,但同時這段代碼是存在邏輯漏洞的

    if(move_uploaded_file($tmpname,$target_path))

    用move_uploaded_file()作if條件做判斷時,如果返回true,上傳的文件不管是否符號要求,到可以上傳到服務器,不過這里主要考察的是二次渲染,接下來就用最簡便的GIF圖片來繞過二次渲染

    上傳GIF圖片馬

    上傳發現沒有解析成功,將上傳的圖片下載下來,用winhex打開觀察一下

    經過二次渲染,發現文件名已經改變而且末尾的PHP代碼已經被去除,既然后面插入不了那就對比一些上傳前和上傳后的圖片,看看那些部分是沒有改變的,將一句話插入其中

    經過對比,這一段都是相同的,可以將代碼插入其中,發現上傳后的圖片依然有PHP代碼,上傳成功


    還有JPEG和PNG圖片上傳,但是都需要腳本,這里就暫時先不用這兩種方法了,不過可以參考大師傅的博客,upload-labs之pass 16詳細分析

    方法圖片對比,在winhex將代碼插入到相同的部位進行繞過

    第十七關

    提示:需要代碼審計!

    那就來分析代碼

    $is_upload = false; $msg = null;if(isset($_POST['submit'])){$ext_arr = array('jpg','png','gif');$file_name = $_FILES['upload_file']['name'];$temp_file = $_FILES['upload_file']['tmp_name'];$file_ext = substr($file_name,strrpos($file_name,".")+1);$upload_file = UPLOAD_PATH . '/' . $file_name; //in_array() 函數搜索數組中是否存在指定的值。 //rename() 函數重命名文件或目錄。if(move_uploaded_file($temp_file, $upload_file)){if(in_array($file_ext,$ext_arr)){$img_path = UPLOAD_PATH . '/'. rand(10, 99).date("YmdHis").".".$file_ext;rename($upload_file, $img_path);$is_upload = true;}else{$msg = "只允許上傳.jpg|.png|.gif類型文件!";unlink($upload_file);}}else{$msg = '上傳出錯!';} } if(move_uploaded_file($temp_file, $upload_file)){if(in_array($file_ext,$ext_arr)){$img_path = UPLOAD_PATH . '/'. rand(10, 99).date("YmdHis").".".$file_ext;rename($upload_file, $img_path);$is_upload = true;

    這一段代碼先將文件上傳到服務器,再判斷后綴名,如果合法則保留下來,如果不合法,后面這段代碼則起刪除作用,刪除在服務器的文件

    $msg = "只允許上傳.jpg|.png|.gif類型文件!";unlink($upload_file);

    unlink() 函數刪除文件

    所以根據這個流程,可以通過條件競爭的方式在unlink()函數刪除之前,訪問上傳文件,在此之前先來了解一下條件競爭

    條件競爭漏洞是一種服務器端的漏洞,由于服務器端在處理不同用戶的請求時是并發進行的,因此,如果并發處理不當或相關操作邏輯順序設計的不合理時,將會導致此類問題的發生。

    接下來就利用條件競爭刪除文件的時間差繞過

    在burp中不斷發送上傳webshell的數據包,然后不斷在瀏覽器中訪問,發現通過競爭可以訪問到,設置多線程控制攻擊請求的并發數,但是我的burp有問題,無法設置多線程,所以沒有辦法復現出來

    方法:條件競爭

    第十八關

    隨便上傳圖片馬,發現

    審計一下代碼

    //index.php $is_upload = false; $msg = null; if (isset($_POST['submit'])) {require_once("./myupload.php");$imgFileName =time();$u = new MyUpload($_FILES['upload_file']['name'], $_FILES['upload_file']['tmp_name'], $_FILES['upload_file']['size'],$imgFileName);$status_code = $u->upload(UPLOAD_PATH);switch ($status_code) {case 1:$is_upload = true;$img_path = $u->cls_upload_dir . $u->cls_file_rename_to;break;case 2:$msg = '文件已經被上傳,但沒有重命名。';break; case -1:$msg = '這個文件不能上傳到服務器的臨時文件存儲目錄。';break; case -2:$msg = '上傳失敗,上傳目錄不可寫。';break; case -3:$msg = '上傳失敗,無法上傳該類型文件。';break; case -4:$msg = '上傳失敗,上傳的文件過大。';break; case -5:$msg = '上傳失敗,服務器已經存在相同名稱文件。';break; case -6:$msg = '文件無法上傳,文件不能復制到目標目錄。';break; default:$msg = '未知錯誤!';break;} }//myupload.php class MyUpload{ ...... ...... ...... var $cls_arr_ext_accepted = array(".doc", ".xls", ".txt", ".pdf", ".gif", ".jpg", ".zip", ".rar", ".7z",".ppt",".html", ".xml", ".tiff", ".jpeg", ".png" );...... ...... ...... /** upload()**** Method to upload the file.** This is the only method to call outside the class.** @para String name of directory we upload to** @returns void**/function upload( $dir ){$ret = $this->isUploadedFile();if( $ret != 1 ){return $this->resultUpload( $ret );}$ret = $this->setDir( $dir );if( $ret != 1 ){return $this->resultUpload( $ret );}$ret = $this->checkExtension();if( $ret != 1 ){return $this->resultUpload( $ret );}$ret = $this->checkSize();if( $ret != 1 ){return $this->resultUpload( $ret ); }// if flag to check if the file exists is set to 1if( $this->cls_file_exists == 1 ){$ret = $this->checkFileExists();if( $ret != 1 ){return $this->resultUpload( $ret ); }}// if we are here, we are ready to move the file to destination$ret = $this->move();if( $ret != 1 ){return $this->resultUpload( $ret ); }// check if we need to rename the fileif( $this->cls_rename_file == 1 ){$ret = $this->renameFile();if( $ret != 1 ){return $this->resultUpload( $ret ); }}// if we are here, everything worked as planned :)return $this->resultUpload( "SUCCESS" );} ...... ...... ...... };

    先是 $ret = $this->move();,進行了一次文件保存,然后再 $ret = $this->renameFile();,進行了一次更改文件名,所以可以用條件競爭來進行繞過

    方法:條件競爭

    第十九關

    發現和之前有些不一樣

    查看一下源碼

    $is_upload = false; $msg = null; if (isset($_POST['submit'])) {if (file_exists(UPLOAD_PATH)) {$deny_ext = array("php","php5","php4","php3","php2","html","htm","phtml","pht","jsp","jspa","jspx","jsw","jsv","jspf","jtml","asp","aspx","asa","asax","ascx","ashx","asmx","cer","swf","htaccess");$file_name = $_POST['save_name'];$file_ext = pathinfo($file_name,PATHINFO_EXTENSION); //pathinfo() 函數以數組的形式返回文件路徑的信息。if(!in_array($file_ext,$deny_ext)) {$temp_file = $_FILES['upload_file']['tmp_name'];$img_path = UPLOAD_PATH . '/' .$file_name;if (move_uploaded_file($temp_file, $img_path)) { $is_upload = true;}else{$msg = '上傳出錯!';}}else{$msg = '禁止保存為該類型文件!';}} else {$msg = UPLOAD_PATH . '文件夾不存在,請手工創建!';} }

    查看大師傅的博客,
    發現move_uploaded_file會忽略掉文件末尾的/.
    而且文件名是從$_FILES['upload_file']['tmp_name']中獲取的,所以用戶是可以進行控制的,所以通過/. 來進行繞過


    上傳成功

    除此之外那也可以用用move_uploaded_file函數的00截斷漏洞繞過


    第二十關

    來源一道CTF題,需要審計代碼,目前自己還審計不了,就參考大師傅們的,暫時先留到這,等水平提高了,再回頭看這道題

    總結:通過upload-labs又學習到了很多很好玩的知識,接下來學習又關密碼學的知識,少年,繼續加油!

    參考博客:
    Upload-labs 20關通關筆記
    Upload-labs通關手冊

    總結

    以上是生活随笔為你收集整理的文件上传漏洞——upload-labs(11-20)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。