upload-labs通关记录

测试文件:

我们的任务是上传木马成功webshell。

Pass-01

查看前端源码:

请选择要上传的图片:

发现οnsubmit="return checkFile()",而checkFile是个JS函数且写在了该页面。

删掉οnsubmit="return checkFile()"或浏览器禁用JS或在checkFile的"allow_ext"中加".php"即可。

右键查看源码可获得上传路径:

upload-labs通关记录_第1张图片 upload-labs通关记录_第2张图片

Pass- 02

查看前端源码,发现表单部分没变,但checkFile函数不在该页面,所以浏览器禁用JS不行了。

抓包,改Content-Type即可:

upload-labs通关记录_第3张图片

upload-labs通关记录_第4张图片

Pass-03

自此前端源码就没变过了,不必对此过多在意。

PHP源码:

$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
    if (file_exists(UPLOAD_PATH)) {
        $deny_ext = array('.asp','.aspx','.php','.jsp');
        $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.'/'.date("YmdHis").rand(1000,9999).$file_ext;            
            if (move_uploaded_file($temp_file,$img_path)) {
                 $is_upload = true;
            } else {
                $msg = '上传出错!';
            }
        } else {
            $msg = '不允许上传.asp,.aspx,.php,.jsp后缀文件!';
        }
    } else {
        $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
    }
}

我们发现它对文件扩展名进行了检查,其中限制了".php",但没限制.phtml、.php3等,所以可以通过修改扩展名绕过。(一般用.phtml)

对于.php和.phtml文件,web服务器都会用php解释器进行解析。

首先要改一下配置文件httpd.conf,并将原来的#去掉:

upload-labs通关记录_第5张图片

目的是告诉服务器把含这几个扩展名的文件当php文件来解析。

保存文件,重启phpstudy,上传.phtml文件即可:

upload-labs通关记录_第6张图片

注意php版本!

还可以在AddType里加.jpg,上传简易版图片马info.jpg,访问图片马即可:

upload-labs通关记录_第7张图片

注意php版本!同时注意上传标准图片马会解析失败。 

Pass-04

查看PHP源码,发现它几乎把所有能绕过的文件扩展名都过滤了:

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

但发现并没有过滤.htaccess。

.htaccess是一个配置文件,运行于Apache(一种web服务器)上。当.htaccess文件被放置在一个 "通过Apache Web服务器加载 "的目录中时,.htaccess文件会被Apache Web服务器软件检测并执行。这些.htaccess文件可以用来改变Apache Web服务器软件的配置,以启用或禁用Apache Web服务器软件所提供的额外功能和特性。

.htaccess可以覆盖apache的配置文件。

.htaccess文件提供了针对目录改变配置的方法, 即在一个特定的文档目录中放置一个包含指令的文件, 以作用于此目录及其所有子目录。管理员可以通过 Apache的AllowOverride 指令来设置是否启动.htaccess,若要启动.htaccess配置文件,需要在服务器的主配置文件将 AllowOverride 设置为 All。

首先创建一个.htaccess文件(注意不要文件名,只保留扩展名),写入

SetHandler application/x-httpd-php

目的是让服务器把所有文件当成php文件来解析。

同时修改httpd.conf配置文件,将AllowOverride 设置为 All:

upload-labs通关记录_第8张图片

重启phpstudy,然后先上传.htaccess文件,再上传图片马即可。

访问图片马所在链接,按道理应该会弹出php版本信息,但很不幸图片马解析报错:

upload-labs通关记录_第9张图片 行吧,至少知道这样可行就是了。

Pass-05

查看PHP源码,发现这一关把.htaccess也给禁了。不过还是留了一手的,它没禁.user.ini。

什么是.ini?

.ini 文件是一种初始化文件,是windows的系统配置文件所采用的存储格式,统管windows的各项配置。

也就是说这是系统配置文件的格式,你会看到当你把文件后缀改为.ini时,文件图标会出现一个齿轮。

那.user.ini有什么特别的地方吗?

此类文件仅被 CGI/FastCGI SAPI 处理。 如果使用 Apache,则用 .htaccess 文件有同样效果。

.user.ini则可以覆盖php.ini的配置。

除了主 php.ini 之外,PHP 还会在每个目录下扫描 INI 文件,从被执行的 PHP 文件所在目录开始一直上升到 web根目录。如果被执行的 PHP 文件在 web 根目录之外,则只扫描该目录。

两个新的 INI 指令,user_ini.filename 和 user_ini.cache_ttl 控制着用户 INI 文件的使用。user_ini.filename 设定了 PHP 会在每个目录下搜寻的文件名;如果设定为空字符串则 PHP 不会搜寻。默认值是 .user.ini。user_ini.cache_ttl 控制着重新读取用户 INI 文件的间隔时间。默认是 300 秒(5 分钟)。

注意:.htaccess.user.ini都只能用于访问本目录下的文件时进行覆盖。

此处利用.user.ini的原理:

php.ini 是 php的配置文件,.user.ini 中的字段也会被 php 视为配置文件来处理,从而导致 php 的文件解析漏洞。

要引发 .user.ini 解析漏洞需满足三个前提条件:

1、服务器脚本语言为PHP。

2、服务器使用CGI/FastCGI模式。

3、上传目录下要有可执行的php文件。

多数流行的 HTTP 服务器都支持 FastCGI,包括 Apache 、 Nginx 和 Lighttpd 等。

注意到题目提示

upload-labs通关记录_第10张图片

所以万事俱备,只欠东风。

首先创建一个.user.ini文件 ,写入

auto_prepend_file=test.jpg

写入的内容是什么意思呢?友情链接

我们的路径为"test.jpg"就好了,因为同一目录下有readme.php文件。

其实文件原名为test.php,改为.jpg是为了绕过扩展名的过实际上里面的内容是单纯的php语句。 

所以我们可以想到,当上传完所有文件后,访问readme.php时,页面会加载test.jpg,然后将里面的语句解析,如果里面是"phpinfo();",那就会弹出PHP版本信息。

依次上传.user.ini和test.jpg,上传的.user.ini需要重启phpstudy才能被解析,但是由上述科普知需要等300秒才能进行下一步操作——访问readme.php,有点久,所以干脆找到php.ini配置文件将300改小一点:(记住要先改并保存才重启phpstudy)

upload-labs通关记录_第11张图片

访问readme.php:

upload-labs通关记录_第12张图片

哈,不出所料!

如果test.jpg的内容为@eval($_POST['x']);,便可用蚁剑成功连接l:

upload-labs通关记录_第13张图片

这题还可以用改后缀为.php. .绕过,因为windows系统会自动将其变为.php。所以上传test.php后抓包,把文件名改为.php. .再发也一样可以成功,注意不要先就在自己的电脑上把后缀改了,改不了的,系统会自动转为.php。 


注意看PHP源码,它给出了一套较为完整的配合黑名单检查的流程:

$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); //首尾去空

接下来的Pass-06~Pass-09将围绕这套流程展开。

通过这几题我们意识到黑名单检查安全性并不高,容易疏漏且容易绕过。 


Pass-06

查看PHP源码,它把转换为小写的步骤去掉了,所以这题可以利用扩展名大小写绕过,其改为如.phP即可上传成功。

访问上传文件:

upload-labs通关记录_第14张图片

 注意php版本!

Pass-07

同上,发现它把首尾去空的步骤去掉了,所以可以利用扩展名加空格绕过:(注意得抓包加空格,本地加是不行的)

upload-labs通关记录_第15张图片  

附:本题它把前后两个trim函数都给删了,所以也试了一下用后缀加预定义字符的方法,如.php\n,但发现上传的文件没有了后缀名,看来只能用加空格的方式。

Pass-08

同上,可利用扩展名加.绕过:(注意依旧得抓包改,改为in.php.)

 upload-labs通关记录_第16张图片

Pass-09

同上,可利用扩展名加::$DATA绕过:(注意依旧要抓包改,改为info.php::$DATA)

upload-labs通关记录_第17张图片

为什么可以这样绕呢?

对于Windows系统,如果文件名+"::$DATA",系统会把::$DATA之后的数据当成文件流处理,不会检测后缀名,且保持::$DATA之前的文件名,其目的就是不检查后缀名。

将这样的文件上传到服务器后,由于Windows系统的特性,在磁盘中会忽略"::$DATA并将文件新建。 

upload-labs通关记录_第18张图片

upload-labs通关记录_第19张图片

Pass-10

纵使流程看起来很完备,但还是存在疏漏。

和Pass-05一样,这里可利用扩展名加". ."绕过:

upload-labs通关记录_第20张图片

可以看一下在这个过程中扩展名是怎么变化的:

upload-labs通关记录_第21张图片

upload-labs通关记录_第22张图片

upload-labs通关记录_第23张图片

说一下为什么这样构思吧:

它的操作依次是:删除文件名末尾的点、转换为小写、去除::$DATA、首尾去空,然后就没操作了,那我们是不是可以使它操作完后还存在"bug"呢?当然是可以的!

因为最后一道工序是首尾去空,那么只能用它操作完后是.php.来绕过,最简单的就是构造.php. .了。

Pass-11

查看PHP源码,发现它有个这样的操作:

$file_name = str_ireplace($deny_ext,"", $file_name);

说明它会搜索文件后缀,如果搜索到黑名单里有的就替换为空,所以如果我们上传info.php,那么上传后就变成info了,这显然不行因为它无法被解析。

当然这个函数是可以绕过的,str_ireplace函数是将字符串从左到右搜索,先搜到谁就替换谁。那么我们绕过时要注意后缀的构造,例如.phphpp不行(替换后会变为xx.hpp),.phpphp也不行(替换后会变为.)。

将info.php改为info.pphphp即可:

upload-labs通关记录_第24张图片

upload-labs通关记录_第25张图片

Pass-12

查看PHP源码,分析代码逻辑,寻找可利用的漏洞:

upload-labs通关记录_第26张图片

首先它设置了一个白名单,然后通过substr、strrpos函数获取上传文件的后缀,接下来判断该后缀是否在白名单内,如果存在则获取上传文件名和拼接上传路径,最后进行文件转移完成上传。

靠拼接生成的上传路径并不安全,可以利用00截断绕过。

首先对00截断及利用做个了解:

%00截断和0x00截断都属于00截断。

php解释器是C语言编写的,C语言中字符串的结尾以ASCII码的0为标志。

0x00是十六进制表示方法,系统是按16进制读取文件(或者说二进制),遇到ASCII码为0的位置就停止,而ASCII码的0的在16进制中是00,用0x开头表示16进制,也就是所说的0x00截断。

以GET方式传输时,服务器会对url进行解码(而POST不会),在url中%00表示ASCII码中的0 ,所以当url中出现%00时就会认为读取已结束 ,%00其实是被服务器解码为0x00发挥了截断作用。

PHP的00截断是5.2.x版本的一个漏洞,%00截断有两个条件:php版本小于5.3.4和magic_quotes_gpc为off状态。 如果这时我们将magic_quotes_gpc改为on那么就不能截断了,因为开启magic_quotes_gpc后%00会被加上一个反斜杠转义掉

所以首先将php版本降下来,并在phpstudy2018的"其他选项菜单->php扩展及设置->参数开关设置"里找到"magic_quotes_gpc"并将其关闭再进行下一步操作。

上传info.php抓包,修改如下几个地方:

upload-labs通关记录_第27张图片

放包后结果如下:

upload-labs通关记录_第28张图片

upload-labs通关记录_第29张图片

成功!

讲一下原理吧:

修改文件名为info.png和修改Content-Type是为了通过白名单检测。

我们将save_path修改后,PHP执行时会如下:

$file_ext是.png,成功通过白名单检测,$temp_file为info.png,$img_path为../upload/info.php%00/xxx.png,执行move_upload_file(info.png, ../upload/info.php%00/xxx.png),由于php解释器是C语言写的,该函数存在00截断,所以保存文件名时%00后的会被全部忽略,最终为../upload/info.php,内容正是info.png的内容。

Pass-13

此题与上题类似,只不过save_path是通过POST传递的,因为POST不会对url解码,所以需要我们手动解码。

首先抓包,更改这些地方:

upload-labs通关记录_第30张图片

在info.php后需要加一个字符占"00"的位置,然后在Hex里找到该字符对应的码(如%是25),将其改为00再发包即可:

upload-labs通关记录_第31张图片

upload-labs通关记录_第32张图片

upload-labs通关记录_第33张图片

注意依旧要降php版本和关magic_quotes_gpc;原理同上题。

Pass-14

查看PHP源码,发现其中不含getimagesize函数,所以可使用简易版图片马绕过:

upload-labs通关记录_第34张图片

将文件后缀改为.jpg再上传即可。

然后利用靶场自带的文件包含来检测成功性:

upload-labs通关记录_第35张图片

Pass-15

这题加上了getimagesize函数,只能靠标准版图片马绕过:(制作方法参见:传送门)

利用靶场自带的文件包含来检测成功性:

upload-labs通关记录_第36张图片

注意需要把php扩展里的php_exif模块<来判断文件类型>关了,不然将是像这样的:

upload-labs通关记录_第37张图片

Pass-16

这题跟上题类似,虽然没有getimagesize函数,但却有exif_imagetype函数,这俩都跟图像处理有关,需要标准版图片马才能绕过。

这两题注意php版本不能太低,同时php_exif模块要关掉。

upload-labs通关记录_第38张图片

Pass-17

查看PHP源码结合提示,此题对上传的图片进行了二次渲染。

什么是二次渲染?

二次渲染就是后端重写文件内容,我们发现PHP源码中有imagecreatefromgif函数,这是进行二次渲染的核心函数。

imagecreatefromgif():创建一块画布,并从 GIF 文件或 URL 地址载入一副图像
imagecreatefromjpeg():创建一块画布,并从 JPEG 文件或 URL 地址载入一副图像
imagecreatefrompng():创建一块画布,并从 PNG 文件或 URL 地址载入一副图像

如何绕过? 参考:友情链接。

看过后我们知道,使用gif文件是最简单的。

首先上传标准图片马,将该图从上传文件夹下载下来,将它与原图用16进制查看器打开对比:

upload-labs通关记录_第39张图片

upload-labs通关记录_第40张图片

我们会发现经二次渲染后,图片马末尾的php语句消失了,但是其他部分还是不变的。

所以我们可以找一个gif文件,用16进制查看器打开,在文件中间部分插入一句话木马:

upload-labs通关记录_第41张图片

这样二次渲染就不会渲走它了。

将其上传,使用靶场自带的文件包含来检测成功性:

upload-labs通关记录_第42张图片

Pass-18

这题可通过上传图片马解出,但是解析图片马需要配合文件包含漏洞,如果恰巧文件包含做得很好呢?那上传的图片马也就没什么用。

审PHP源码,分析代码思路,寻找漏洞:

upload-labs通关记录_第43张图片

我们发现它会先将文件保存再检查后缀,如果后缀不符合则删除文件。这前后两步的执行是存在一定间隔时间的,而如果我们能卡在这段时间做一些小动作,那就能成功上传php文件,这个叫条件竞争。

首先创建test.php写入

'); ?>

上传抓包,将包送到Intruder板块,利用Intruder板块(爆破时用到的,原理就是快速地不断地发包)进行无字典无限次爆破:

upload-labs通关记录_第44张图片

 upload-labs通关记录_第45张图片

接下来访问test.php(http://localhost/upload-labs/upload/test.php ),同样地抓包进行无字典无限次爆破:

upload-labs通关记录_第46张图片

upload-labs通关记录_第47张图片

等跑出200状态码时说明upload文件夹就出现info.php了,表明我们成功绕过了条件竞争上传了webshell文件。

它的原理是这样的:

我们通过无限次发包(test.php) 创造间隔时间,同时无限次访问test.php,如果有一刻刚好在间隔时间里访问到了test.php,那么将会执行test.php——在同目录下创建info.php并写入,那么条件竞争绕过,成功"上传"了木马文件。

奈何这是一个概率事件,我的机子都快冒烟了还没跑出200的响应包。。。

Pass-19


首先修复个bug,找到myupload.php加上如下内容:

upload-labs通关记录_第48张图片

不然会是这样:

upload-labs通关记录_第49张图片

看着不舒服。


审PHP源码(此处省略若干字符,因为源码太长了),虽然我有点审不明白但是我们发现它大致是进行了后缀白名单过滤、检查文件、移文件(到上传文件夹)、重命名,由白名单知我们只能上传图片马。

我觉得作者出这题的用意是:当上传时对文件做了重命名时怎么webshell——依旧是条件竞争,赶在重命名之前结合文件包含把图片马解析、执行其中的php语句,如创建一个攻击者设置的webshell文件。

首先做个图片马test.png,php语句为

'); ?>

然后操作步骤同上一题,只不过访问test.png时是:http://localhost/upload-labs/include.php?file=upload/test.png

Pass-20

这题有意思,它告诉了我们保存文件名(虽然后缀是.jpg),所以直接利用文件包含就行。

但如果没又文件包含模块呢?

查看PHP源码,可以看到它对文件后缀放得很松,只有一个黑名单检测。

所以之前用到过的奇葩魔改后缀基本上都可般过来,如大小写、加点、加空格,当然还可以加"/.",这是利用了move_upload_file函数会忽略文件末尾的"/."的特性,同时还可以利用POST00截断来做。

此处省略演示。

Pass-21

审源码,分析代码逻辑:

upload-labs通关记录_第50张图片

如果我们上传一个info.php,抓包该Content-Type绕文件类型检测,(不论上传什么名字,或者上传图片)最终到upload文件夹的名字都是upload-20.jpg(save_name),如果不适用文件包含将无法解析我们上传的木马。

我们来分析以下代码逻辑:

upload-labs通关记录_第51张图片

因为文件名是拼接而成的,所以可使它不按开发者的想法拼接,抓包魔改(看对比):

 upload-labs通关记录_第52张图片

upload-labs通关记录_第53张图片

1、该Content-Type绕类型检测。

2、将save_name改为数组,绕过explode函数,那么也就绕过了开发者构思的拼接方式。

3、end函数返回save_name[3]->png,成功绕过后缀检测。

4、reset函数返回save_name[0]->info。

5、count[$file]返回3,所以$file[count($file) - 1]为save_name[2]->php。

综上,文件名拼接结果为info.php

upload-labs通关记录_第54张图片  

访问info.php:

upload-labs通关记录_第55张图片

怎么样,这题很棒吧。 


啊啊啊,终于打通关了!

感谢给我用做测试的图片们!

你可能感兴趣的:(靶场,经验分享)