Hed9eh0g

前进的路上总是孤独的

Upload-labs Pass01-10 Writeup

本文共计有7205个字

前言

Upload-labs为文件上传漏洞靶场,一共有20个关卡。此篇文章将持续更新1-10关的解法(下一篇开始更新11-20关),总结出所有关卡的writeup。另外,文中上传的图片文件名默认为1.jpg,php文件名默认为phpinfo.php,其内容默认为<?phpinfo();?>,以能够上传php文件到后台为上传绕过成功的标志。
为了让每一关的知识点不重复且具有递进作用,我只给出一个解题方法,这并不意味着这一关仅仅有这一种解法,相反后面很多的关卡的解法同样适用于当前关卡。

Pass-01

上传图片文件可以通过,当上传php文件时显示:

《Upload-labs Pass01-10 Writeup》
如果有细心观察可以发现,上传过程根本没有向后台发送请求数据,页面没有变化就直接弹出窗口(或者根据F12查看网络也可以发现没有数据的传送)。因此可以推断属于前端对文件后缀的检查,通过F12也可以发现是通过前端语言js来检查文件后缀:

《Upload-labs Pass01-10 Writeup》
因此绕过的思路就是先上传phpinfo.jpg文件,使前端检查后缀名通过,然后再抓包把后缀改为php即可。

Pass-02

上传的要求跟Pass-01一样,与其不同的地方就是这次上传php文件存在数据发送的缓冲时间,因此可以推出是服务器端(也即后台)的检验(后面的关卡已经不存在前端检测了)。
对于后台的检验,首先要判断其检验的方式是什么,先判断是否为文件后缀名的检验,将1.jpg改为1.php,发现上传成功。所以结合无法上传phpinfo.php但可以上传1.php可以推断出后台是对文件类型的检验,文件类型在请求头中属于content-type的内容,所以我们通过改包来实现绕过:

《Upload-labs Pass01-10 Writeup》
因此将content-type中的内容改为image/ipge即可绕过对文件类型的检查。

Pass-03

直接上传php文件,被提示:不允许上传.asp,.aspx,.php,.jsp后缀文件!
很明显就是后台对文件后缀名的检查,且很明显属于黑名单检查,由于php语言除了可以解析以php为后缀的文件之外,还可以解析php3、php5、phtml、pht这些后缀的文件。所以试试在后缀名后面添加数字如php3,发现能够成功上传。

Pass-04

上传jpg文件可以,而上传php,php3,php5文件都会提示:此文件不允许上传!
因此可以得出,与Pass-03相同仍然是对文件后缀名的检查,但不同之处在于我们无法明显知道是白名单检查还是黑名单检查,这个时候可以随意取个后缀名,然后上传该文件(比如1.haha),如果能够通过那么证明应该是黑名单检查,如果无法上传那么证明应该是白名单检查。
结果发现可以通过,那么就是对php,php3,php5,Php等后缀文件的黑名单检查了,这时再上传.htaccess文件试试,结果发现上传成功,那么可以利用它重写解析规则,比如先上传phpinfo.jpg文件之后再上传.htaccess文件,后者文件内容为:

AddType application/x-httpd-php .jpg

这个指令的意思是:将后缀名为jpg格式的文件解析为php文件,所以phpinfo.jpg此时便等效为phpinfo.php。

Pass-05

上传php文件不行,上传1.haha可以通过因此为黑名单检查,但是上传php3、php5、.htaccess等也不行。考虑将后缀名php中的字母改变大小写,如Php、pHp等,发现上传成功,因此本题的利用点就是改变后缀名的大小写。

Pass-06

由于改后缀的情况实在有些多种,所以我们需要通过代码来明确本题想要让我们掌握哪一个知识点:

$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",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".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",".htaccess");
        $file_name = $_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
        
        if (!in_array($file_ext, $deny_ext)) {
            $temp_file = $_FILES['upload_file']['tmp_name'];
            $img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext;
            if (move_uploaded_file($temp_file,$img_path)) {
                $is_upload = true;
            } else {
                $msg = '上传出错!';
            }
        } else {
            $msg = '此文件不允许上传';
        }
    } else {
        $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
    }
}

这一关Pass-05过滤的基础上对诸如后缀名Php、pHp等存在大写字母的均给转化为小写字母,但是它没有过滤后缀名最后一位为空格的情况。因此本题我们要利用点是:如果后缀名的最后一位是空格,Windows系统会自动把空格给删掉,且Unix/linux下没有该特点。
也就是通过抓包把文件’phpinfo.php’改成’phpinfo.php ‘(多了一个空格),即可将该文件上传。又因为Windows本身的解析特点,所以该文件上传入后台之后仍然会被等同为一个php文件。

Pass-07

代码如下

$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",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".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",".htaccess");
        $file_name = trim($_FILES['upload_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 . '文件夹不存在,请手工创建!';
    }
}

这一关添加了首位去空的操作,目的就是为了过滤掉后缀名+空格的绕过方式。然而它与Pass-06缺少的一步操作就是删除文件名末尾的点,因此本关要利用的点仍然是Windows解析特点:如果文件后缀以点”.”结尾,系统在保存文件时会自动去除点和空格。当然Unix/Linux下没有这个特性。
所以类比于上一关,通过改包的方式把’phpinfo.php’改为’phpinfo.php.’即可上传,当到达后台后该文件又会被等同于php文件。

Pass-08

代码如下:

$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",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".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",".htaccess");
        $file_name = trim($_FILES['upload_file']['name']);
        $file_name = deldot($file_name);//删除文件名末尾的点
        $file_ext = strrchr($file_name, '.');
        $file_ext = strtolower($file_ext); //转换为小写
        $file_ext = trim($file_ext); //首尾去空
        
        if (!in_array($file_ext, $deny_ext)) {
            $temp_file = $_FILES['upload_file']['tmp_name'];
            $img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext;
            if (move_uploaded_file($temp_file, $img_path)) {
                $is_upload = true;
            } else {
                $msg = '上传出错!';
            }
        } else {
            $msg = '此文件类型不允许上传!';
        }
    } else {
        $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
    }
}

这一关添加了删除文件名末尾的点这一步操作,目的就是为了过滤掉上一关的后缀名+点的绕过。但是又它与Pass-07少的一步操作就是去除字符串::$DATA,因此本关要利用的点又双叒是Windows的解析特点(罪恶的Windows):文件名+”::$DATA”会把::$DATA之后的数据当成文件流处理,并不会检测后缀名。
所以类比于上一关,通过改包的方式把’phpinfo.php’改为’phpinfo.php::$DATA’即可上传,当到达后台后该文件仍然会被等同于php文件。

Pass-09

代码如下:

$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",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".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",".htaccess");
        $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 . '文件夹不存在,请手工创建!';
    }
}

本关没有新的知识点,而是利用代码后缀名处理的不够严谨:先去除了文件后面的点, 再去除了文件后缀的空格, 但是这两个操作只处理了一次,,所以可以通过上传’phpinfo.php+点+空格+点’的文件进行绕过。

Pass-10

代码如下:

$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 = trim($_FILES['upload_file']['name']);
        $file_name = str_ireplace($deny_ext,"", $file_name);
        $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 = UPLOAD_PATH . '文件夹不存在,请手工创建!';
    }
}

本关仍然是利用代码对后缀名的处理产生的漏洞,漏洞就出现在:
$file_name = str_ireplace($deny_ext,””, $file_name);
这一步进行的是:把文件后缀出现在黑名单里面的,替换为空,也就是想要去除出现的黑名单后缀名,但这一步操作只进行了一次,因此我们可以故意构造一个后缀,使替换之后变成php。
需要注意的是,这一步替换操作是从左到右开始检查的,所以如果后缀名是phphpp是无法实现的(结果会变成hpp,如果是从右到左的话就可以实现),因此我们最终可以构造:phpinfo.pphphp文件。

参考文章

1、http://www.she1don.cn/index.php/archives/38.html#_label11
2、http://www.sec00.cn/index.php/2019/07/20/753.html

点赞

发表评论

电子邮件地址不会被公开。 必填项已用*标注