17和18都很重要吧
參考全集1
博客2
pass17
$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);
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的圖片文件!";
}
}
提示是:本pass重新渲染了圖片,要求.gif .jpg .png三種都上傳了纔算成功
imagecreatefromjpeg
這個函數就是用來渲染生成新的圖片的
1…gif文件
gif的文件比較簡單,文件頭(gif89a/gif87a)+gif數據流+終結器。沒有分各種數據塊這樣的。
所以對於gif:上傳一張圖片,然後下載下來與原圖進行對比,把webshell放在沒有被修改的地方就行了
2.png文件
這也是隱寫裏考得多的一類,無損壓縮的位圖,由>3塊組成
misc常規考點有:校驗值計算,修改高寬(IHDR塊的crc值爆破得到寬度)
PNG定義了兩種類型的數據塊,一種是稱爲關鍵數據塊(critical
chunk),這是標準的數據塊,另一種叫做輔助數據塊(ancillary
chunks),這是可選的數據塊。關鍵數據塊定義了3個標準數據塊(IHDR,IDAT, IEND),每個PNG文件都必須包含它們。
一種方式是將webshell寫入PLTE數據塊,也就是數13字節以後,再修改CRC
另一種是寫入IDAT數據塊
3.jpg文件
在隱寫裏也考,有損壓縮,以段來組成,普通考點一般考慮隱寫算法,複習LSB,Jsteg,F5算法,JPhide,Outguess
這個作爲一個菜雞更是難說,還是參考上面的文章
pass18
$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;
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開始)發現上傳完了,再判斷的,決定是不是要刪除(unlink
函數)
1.首先接收上傳的文件
2.然後判斷上傳的文件的文件後綴是否在白名單中
3.在白名單中,則將文件重命名
4.不在白名單則刪除文件
這裏要用到條件競爭
個人認爲條件競爭是一個想法~不一定非要用在文件上傳上面。
bp多線程發送請求包,一邊上傳,一邊訪問…理論還是比較簡單的。
轉載
一個例子:
條件競爭漏洞是一種服務器端的漏洞,是由於開發者設計應用程序併發處理時操作邏輯不合理而造成。當應用面臨高併發的請求時未能同步好所有請求,導致請求與請求之間產生等待時出現邏輯缺陷。該漏洞一般出現在與數據庫系統頻繁交互的位置,例如金額同步、支付等較敏感操作處。另外條件競爭漏洞也會出現在其他位置,例如文件的操作處理等。
某平臺提現功能的業務處理流程爲: 用戶發起提現 -> 獲取用戶金額並判斷能否提現 -> 提現:生成提現訂單->扣除提現金額
<?php
public funtion withdraw($user_id, $withdrawal_amount){
//獲取餘額
$money = $db->FirstRow("SELECT * FROM ".Tb('money')." WHERE user_id='{$user_id}'");
if($money['balance'] == 0) ShowError('金額爲零,無法提現!');
//提現餘額小於等於數據庫的值就提現
if ($withdrawal_amount <= $money['balance']) {
create_withdraw_order($withdrawal_amount, $user_id, time());
$db->Execute("UPDATE ".Tb('money')." SET balance=balance-{$withdrawal_amount} WHERE uer_id='{$user_id}'");
ShowSuccess('提現成功!');
}
else
{
ShowError('提現金額過高!');
}
}
?>
上述代碼在非併發情況下是沒有問題的。
假設現有一個用戶在系統中共有2000元可以提現,他想全部提現。於是該用戶同時發起兩次提現請求,第一次提交請求提現2000元,系統已經創建了提現訂單但還未來得及修改該用戶剩餘金額,此時第二次提現請求同樣是提現2000元,於是程序在還未修改完上一次請求後的餘額前就進行了餘額判斷,顯然如果這裏餘額判斷速度快於上一次餘額修改速度,將會產生成功提現的兩次訂單,而數據庫中餘額也將變爲-2000。而這產生的後果將會是平臺多向該用戶付出2000元。
這個也算支付漏洞了吧
實操步驟:
1.bp開始多線程地上傳(intruder模塊)可以選擇null payload這個type,也可以在user-agent頭後面+數字,使用數字payload
2.跑得時候會發現,地址中的文件會頻繁上傳->被刪除
3.同時使用腳本訪問該文件
使用多線程腳本,頻繁多線程訪問該url 即可被保存
可以這樣設置:
代碼改成這樣就好~
例題:Moctf–沒時間解釋了
這題反正也是看blog的時候發現的wp我也沒時間解釋了
考點1.發現這個302跳轉 改包發送
2.發包都是兩個頁面,一個不斷上傳,一個不斷訪問
實操:
step1:建一個php
step2:
點擊上傳,抓包
step3:intruder模塊跑一下 ok(一定要多,只500次文件影子都沒見到)
然後???我先留個疑問吧
pass19
還是條件競爭
//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 1
if( $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 file
if( $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" );
}
......
......
......
};
pass20
這是個代碼審計。。。。move_uploaded_file 會自動忽略文件末尾的/.
而且文件名是從$_FILES[‘upload_file’][‘tmp_name’]中獲取的,所以用戶是可以進行控制的,所以通過/. 來進行繞過
抓包吧文件名後面加/.吧
也可以用該函數的00截斷繞過
pass21
數組繞過,https://blog.csdn.net/u014029795/article/details/102917199 看這篇,講得很清晰了