upload-labs 17-21

文章目录

  • pass17
  • pass18
    • 例题:Moctf--没时间解释了
  • pass19
  • pass20
  • pass21

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多线程发送请求包,一边上传,一边访问…理论还是比较简单的。

转载一个例子:
条件竞争漏洞是一种服务器端的漏洞,是由于开发者设计应用程序并发处理时操作逻辑不合理而造成。当应用面临高并发的请求时未能同步好所有请求,导致请求与请求之间产生等待时出现逻辑缺陷。该漏洞一般出现在与数据库系统频繁交互的位置,例如金额同步、支付等较敏感操作处。另外条件竞争漏洞也会出现在其他位置,例如文件的操作处理等。

某平台提现功能的业务处理流程为: 用户发起提现 -> 获取用户金额并判断能否提现 -> 提现:生成提现订单->扣除提现金额


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 即可被保存

可以这样设置:
upload-labs 17-21_第1张图片

代码改成这样就好~
upload-labs 17-21_第2张图片

例题:Moctf–没时间解释了

这题反正也是看blog的时候发现的wp我也没时间解释了
考点1.发现这个302跳转 改包发送
2.发包都是两个页面,一个不断上传,一个不断访问


实操:
step1:建一个php

');?>

step2:
upload-labs 17-21_第3张图片
点击上传,抓包

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 看这篇,讲得很清晰了
upload-labs 17-21_第4张图片

你可能感兴趣的:(#,文件上传)