惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

D
Docker
爱范儿
爱范儿
人人都是产品经理
人人都是产品经理
博客园 - 司徒正美
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
量子位
罗磊的独立博客
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
小众软件
小众软件
C
Cybersecurity and Infrastructure Security Agency CISA
Cyberwarzone
Cyberwarzone
大猫的无限游戏
大猫的无限游戏
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
雷峰网
雷峰网
Simon Willison's Weblog
Simon Willison's Weblog
The Cloudflare Blog
博客园 - 三生石上(FineUI控件)
D
Darknet – Hacking Tools, Hacker News & Cyber Security
C
Cyber Attacks, Cyber Crime and Cyber Security
博客园_首页
博客园 - 叶小钗
V
Vulnerabilities – Threatpost
T
The Exploit Database - CXSecurity.com
T
Tailwind CSS Blog
IT之家
IT之家
博客园 - 聂微东
Spread Privacy
Spread Privacy
V2EX - 技术
V2EX - 技术
S
Security Affairs
宝玉的分享
宝玉的分享
V
V2EX
C
Cisco Blogs
博客园 - Franky
美团技术团队
酷 壳 – CoolShell
酷 壳 – CoolShell
月光博客
月光博客
S
Securelist
J
Java Code Geeks
Webroot Blog
Webroot Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
P
Proofpoint News Feed
Last Week in AI
Last Week in AI
L
LINUX DO - 热门话题
NISL@THU
NISL@THU
WordPress大学
WordPress大学
W
WeLiveSecurity
T
Threatpost
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
腾讯CDC
阮一峰的网络日志
阮一峰的网络日志

Hi, I Am I

[I Am I 年度简报] — 不知终日梦为鱼 初探 ESP32-CAM QQ 聊天记录 MHT 文件转 HTML [I Am I 年度简报] - 草木本无意,荣枯自有时。 Hexo 中实现 Live Photos 支持 写在当下 NKCTF 2024 1z_F0r3ns1c5 Writeup 春秋杯冬季赛 2023 Writeup [I Am I 年度简报] - 2023 某内网渗透内部赛 Writeup 强网拟态 2023 Writeup Github Actions 自动化部署 Hexo 浅析CobaltStrike流量解密 陇剑杯 2023 Writeup CTF线下赛AWDP总结 ISCC 2023 Writeup ISCC 2023 实战题 Writeup CISCN 2023 Writeup 福建闽盾杯网络空间安全大赛 2023 Writeup 天一永安杯宁波市网络安全大赛 2023 Writeup 贵阳大数据及网络安全精英对抗赛 2023 Writeup 红明谷杯 2023 Writeup Confetti 带来有仪式感的鼓励 记一次 JS 逆向密码加密 [I Am I 年度简报] – 2022 PHP 读取 Excel 文件内容并写入数据库 从0开始的 MoeCTF 开发之路 观安杯 2022 Writeup 利用微信服务号实现早安自动化 Cloudflare批量拉黑IP脚本 蓝帽杯 2022 Writeup 为你的网站添加 Do you like me 小组件 ISCC 2022 Writeup CISCN 2022 Writeup ISCC 2022 实战题 Writeup CTF线下赛AWD攻防总结 [I Am I 年度简报] – 2021 记一次 CNVD 通用型漏洞证书挖掘 Google Adsense 收款流程 使用 Digispark 开发板制作 BadUSB 在 Vue 中使用 Axios 获取钉钉群直播回放的 M3U8 地址 Flask 框架学习记录 关于 Ten·API 防火墙的配置 关于最近 关于 Burp Suite 调教这档事 ISCC 2021 Writeup 记一次 CTF 环境和动态独立靶机部署 各大平台图集解析思路 情话总雷同,恨意千万种 HackThisSite Basic Writeup [I Am I 年度简报] - 2020 Kali 设置中文语言和更换镜像源 使用 Python 下载哔哩哔哩视频 PHP使用 CURL 发送网络请求 PHP蓝奏云直链解析源码 从0开始写一个短视频去水印接口 Windows+Ubuntu 双系统之美化 GRUB Windows+Ubuntu 双系统安装 树莓派安装 Aria2 实现24小时不间断的下载机 抖音无水印解析最新PHP源码 API-Admin Ten·API管理后台 树莓派安装 DLNA 实现流媒体服务器 [I Am I 年度简报] - 2019 Hello Hexo Goindex 将 Google Drive 打造成网盘 自用博客评论邮件通知美化模板 使用 IFTTT 长久保留 Google Voice 号码 Telegram MTProxy 代理一键安装脚本 三分钟学会搭建我的世界基岩版服务器 PHP跳转QQ聊天窗口源码 推荐几款开源HTML5(Web)框架 谷歌新出浏览器 Chromium 可以直接翻墙 Live2D!为你的网站添加看板娘 为你的网站添加Gittalk评论 网站数据离奇丢失...... Lsky Pro(兰空图床)—又一款单纯的图床程序 LOL明天解封ヾ(◍°∇°◍)ノ゙ 唔~本站受到DDOS攻击 [I Am I 年度简报] – 2018 死肥宅也要谈恋爱之早安晚安自动化 1024,Hello,world! 宝塔面板 Bt.cn 专业版破解教程 Uptime >>16 years 震惊!坐在家里竟然可以日入百万 免费获取一年的 .ooo 域名 PHP 调用 新浪API 生成短网址 思杰马克丁成 Adobe 中国授权经销商 畅言商业广告上线-去除畅言评论广告 使用网易云音乐官方接口解析VIP音乐 PHP获取QQ昵称和头像API 坦白说查发送人QQ新方法(已失效) 日常水一波 通过微博图片地址溯源上传者 WordPress 评论夜间自动改为必须审核 十步叫你如何无损修复硬盘锁(mbr病毒) [I Am I 年度简报] – 2017 密码破解与心理学 网页屏蔽各种按键的代码分享 网络安全技术专业术语
upload-labs 文件上传漏洞通关记录
2021-02-24 · via Hi, I Am I

upload-labs 是一个使用 php 语言编写的,专门收集渗透测试和CTF中遇到的各种上传漏洞的靶场。旨在帮助大家对上传漏洞有一个全面的了解。目前一共21关,每一关都包含着不同上传方式。

运行环境

博主使用的 PHPstudy + apache+php5.2 (扩展: php_gd2 , php_exif),自建容易有坑,建议直接下载 releases 方便快速搭建。

第1关

直接上传,弹窗了。盲猜js验证 直接 禁用js 上传成功。

也可以burp抓包修改文件类型(上传 webshell.jpg 修改为 webshell.php)。

image-20210223222306415

image-20210223220706651

第2关

$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
    if (file_exists(UPLOAD_PATH)) {
        // 判断Content-type是否为以下类型 image/jpeg、image/png、image/gif
        if (($_FILES['upload_file']['type'] == 'image/jpeg') || ($_FILES['upload_file']['type'] == 'image/png') || ($_FILES['upload_file']['type'] == 'image/gif')) {
            $temp_file = $_FILES['upload_file']['tmp_name'];
            $img_path = UPLOAD_PATH . '/' . $_FILES['upload_file']['name']            
            if (move_uploaded_file($temp_file, $img_path)) {
                $is_upload = true;
            } else {
                $msg = '上传出错!';
            }
        } else {
            $msg = '文件类型不正确,请重新上传!';
        }
    } else {
        $msg = UPLOAD_PATH.'文件夹不存在,请手工创建!';
    }
}

直接抓包把 application/octet-stream 修改为允许的类型 image/jpeg、image/png、image/gif 即可

image-20210223221238723

也可以用第一关修改后缀的方法上传。

第3关

源码直接写死了禁止上传 .asp .aspx .php .jsp 这四种后缀的文件,这里百度了一番,直接修改后缀为 phtml

  • Apache的解析顺序是从右到左开始解析文件后缀的,如果最右侧扩展名不可识别,就继续往左判断。直到遇到可以解析的文件后缀为止
  • 可以上传例如 php3, phtml 后缀的文件绕过,前提是 Apachehttpd.conf 中配置有如下代码:
    AddType application/x-httpd-php .php .php3 .phtml

image-20210223223312675

image-20210223223440012

第4关

$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
    if (file_exists(UPLOAD_PATH)) {
        $deny_ext = array(".php",".php5",".php4",".php3",".php2",".php1",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".pHp1",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".ini");
        $file_name = trim($_FILES['upload_file']['name']);
        $file_name = deldot($file_name);//删除文件名末尾的点
        $file_ext = strrchr($file_name, '.');
        $file_ext = strtolower($file_ext); //转换为小写
        $file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
        $file_ext = trim($file_ext); //收尾去空

        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 . '文件夹不存在,请手工创建!';
    }
}

这题基本把各种后缀全禁止了 但没有限制 .htaccess

.htaccess 文件是Apache服务器中的一个配置文件,它负责相关目录下的网页配置。

通过 .htaccess 文件,可以实现:网页301重定向、自定义404错误页面、改变文件扩展名、允许/阻止特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能IIS平台上不存在该文件,该文件默认开启,启用和关闭在 httpd.conf 文件中配置。

因此我们可以上传一个 .htaccess 文件内容:

SetHandler application/x-httpd-php

这样所有文件都会被当成PHP来进行解析 接着我们直接上传个图片马。

image-20210223224256529

第5关

黑名单里多了个 .htaccess 少了个 ini

创建一个 .user.ini 文件, 内容如下:

auto_prepend_file=123.gif

.user.ini 上传到服务器, 然后将包含一句话的 php文件 重命名为 123.gif, 上传到服务器

然后访问 upload/readme.php 会自动包含并解析 123.gif 文件

第6关

查看源码发现后缀全限制死了 但是发现少了一行

$file_ext = strtolower($file_ext); //转换为小写

直接后缀大小写混合 绕过上传成功。

image-20210223230623317

第7关

查看源码发现少了

$file_ext = trim($file_ext); //首尾去空

直接后缀后面加个空格绕过。

image-20210223231126124

第8关

查看源码发现这题少了

$file_name = deldot($file_name);//删除文件名末尾的点

利用 windows 特性,会自动去掉后缀名中最后的 .,直接后缀后面加 . 即可绕过。 image-20210223231440263

第9关

查看源码发现少了

$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA

Windows + PHP 的情况下:如果 文件名 + ::$DATA,::$DATA 之后的数据当成文件流处理,不会检测后缀名,且保持 ::$DATA 之前的文件名。

例如 webshell.php::$DATA 变为 webshell.php

直接后缀加上 ::$DATA 绕过上传成功,访问上传的文件是注意去掉地址最后的 ::$DATA

image-20210223232126890

第10关

查看源码后,发现 第15行 拼接的是 $file_name 而不是 $file_ext,而 $file_name 只处理了 文件名末尾的点 所以我们可以输入 . . 来绕过。

这题自我感觉有点绕 写个解析 以备参考。

第6行 使用 trim 先去除了文件前后的空格,第7行 使用 deldot 去除了文件名末尾的 .第8行 使用 strrchr 来寻找 . 来确定文件的后缀

此时请我们输入 webshell.php. . (点空格点) 会匹配为 . (点空格) 从而达到绕过的目的。

image-20210223233057946

第11关

源码 第8行 使用 str_ireplace 进行了匹配替换 如果存在黑名单内的内容 则替换为空且只替换一次例如 webshell.php 替换为 webshell. 我们可以通过双写绕过

image-20210223235759186

第12关

源码 第8行 进行了一次GET传参 修改一句话的后缀名为 .jpg 然后修改URL后直接使用 %00 url终止符进行截断。成功上传访问时记得删除PHP后面的内容

截断条件:PHP版本小于5.3.4,PHP的magic_quotes_gpc为OFF状态 否则magic_quotes_gpc会在敏感字符前加上反斜杠(\)

image-20210224000947285

第13关

和上一关唯一的区别就是 GET 变为了 POST

我们使用00截断

img

img

第14关

function getReailFileType($filename){
    $file = fopen($filename, "rb");
    $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 = "上传出错!";
        }
    }
}

查看源码后,第3行 读取上传文件的前两个字节,接着使用 unpack 解码后,intval 转换为10进制,根据转换后的结果进行 case

CMD生成图片马

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

shell.jpg 就是生成的图片马,直接上传即可。直接访问图片并不能把图片当做PHP解析,利用文件包含解析图片马里的PHP语句,file 为我们的图片马位置。

<?php
/*
本页面存在文件包含漏洞,用于测试图片马是否能正常运行!
*/
header("Content-Type:text/html;charset=utf-8");
$file = $_GET['file']; //这里是传参
if(isset($file)){
    include $file;
}else{
    show_source(__file__);
}
?>

image-20210224003601737

第15关

同上一关 直接用上一关的图片马上传即可

查看源码 第4行 使用 getimagesize 获取图片类型,打印一下返回了一个数组

array(7) {
  [0]=> //图像宽度像素值
  int(50)
  [1]=> //图像高度像素值
  int(52)
  [2]=> //图像类型,1=GIF,2=JPG,3=PNG,4=SWF,5=PSD,6=BMP,7=TIFF_II,8=TIFF_MM,9=JPC,10=JP2,11=JPX,12=JB2,13=SWC,14=IFF,15=WBMP,16=XBM,17=ICO,18=COUNT
  int(2)
  [3]=> //图像宽度和高度的字符串
  string(22) "width="50" height="52""
  ["bits"]=> //图像的每种颜色的位数,二进制格式
  int(8)
  ["channels"]=> //图像的通道值
  int(3)
  ["mime"]=> //图像的MIME信息
  string(10) "image/jpeg"
}

第16关

这里用的 php_exif 扩展来判断的上传的文件类型 同上一关 直接用上一关的图片马上传即可

第17关

$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的图片文件!";
    }
}

判断了文件后缀与类型 利用 imagecreatefromgif 判断是否为 gif 图片,最后再做了二次渲染,具体可以参考 upload-labs Pass17

第18关

$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 = '上传出错!';
    }
}

这里是条件竞争 先将文件上传到服务器 第9行 拼接了文件上传后的路径,第11行 使用 move_uploaded_file 把上传的文件移动到临时目录

然后判断文件是否在白名单内 在的话使用 rename 进行重命名,否则使用 unlink 删除文件 这里我们直接赶在删除前 去访问文件 写入一个shell就行了

这里可以使用burp的 Intruder 不断上传文件,然后我们不断的访问刷新该地址。

<?php fputs(fopen('webshell.php','w'),'<?php phpinfo(); ?>');?>

image-20210224165225438

第19关

看了下 upload-labs 的介绍 Pass-19 必须在linux下运行,直接上传了图片马 然后利用前几关的文件包含漏洞…

第20关

$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);

        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 . '文件夹不存在,请手工创建!';
    }
}

这题给了黑名单 但是能自定义上传的文件名,我们直接用前几关的知识绕过就行了 文件名后面加个 空格/点/::$DATA 都可以。

第21关

先检查 Content-type,接着检查文件名,保存名称为空的就用上传的文件名,接着 !is_array 判断文件名是否为数组,不是的话就使用 explode 通过 . 号分割成数组。然后获取后缀名,进行白名单验证。符合条件就拼接数组的第一个和最后一个作为文件名,保存。

具体参考:https://blog.csdn.net/Fly_hps/article/details/99660226

写在后面

增加了大量奇怪的上传姿势,也增加了防御的各种思路。部分题参考了网上的题解,其他差不多都是用 burp 的重发器和 var_dump() 打印函数慢慢调的 有几题没做出来 学习中…