铭飞CMS SQL注入漏洞(CNVD-2024-06148)复现与深度剖析

📅 2026/6/30 0:04:36
铭飞CMS SQL注入漏洞(CNVD-2024-06148)复现与深度剖析
1. 项目概述一次典型的CMS漏洞复现之旅最近在安全圈里铭飞CMS的一个SQL注入漏洞CNVD-2024-06148引起了不小的讨论。作为一名常年和代码、漏洞打交道的安全从业者我习惯性地会去复现这类公开的漏洞这不仅是验证其真实性和危害性的过程更是深入理解其成因、学习防御思路的绝佳机会。今天我就把自己复现这个漏洞的完整过程、技术细节和踩过的坑毫无保留地分享出来。这篇文章适合所有对Web安全、代码审计或渗透测试感兴趣的朋友无论你是想了解一个具体的漏洞如何被利用还是想学习如何从零开始搭建环境进行复现都能在这里找到清晰的路径和可操作的步骤。我们将从环境搭建开始一步步分析漏洞原理构造利用Payload并最终获取数据库信息整个过程力求详尽让你能亲手复现。2. 环境准备与靶场搭建2.1 靶机环境选择与部署漏洞复现的第一步永远是搭建一个与漏洞存在环境尽可能一致的靶场。根据漏洞公告铭飞CMS的多个版本受此漏洞影响。为了最贴近真实情况我选择从官方历史发布页面下载了一个受影响的旧版本例如 某历史版本。这里有个关键点务必使用虚拟机。我推荐使用 VirtualBox 或 VMware 创建一个干净的 Windows 或 Linux 虚拟机将CMS部署在其中。这样做的好处是绝对的隔离性避免测试用的Payload或意外操作影响到你的宿主机或其他网络服务。在虚拟机中我安装了 PHP 5.6与受影响版本兼容、Apache 2.4 以及 MySQL 5.5搭建了一个典型的 LAMP/WAMP 环境。安装过程本身并不复杂按照铭飞CMS的官方安装指引进行即可。但这里有几个注意事项第一数据库配置时建议为这个测试环境单独创建一个数据库用户而不是直接用root这更符合生产环境的习惯也便于我们后续观察注入效果。第二安装完成后务必不要进行任何升级或打补丁操作我们的目的就是保留这个存在漏洞的原始状态。第三记得检查Apache的mod_rewrite模块是否开启因为很多CMS的路由依赖它如果没开一些涉及URL参数的漏洞点可能无法正常访问。2.2 关键工具链配置工欲善其事必先利其器。一次高效的漏洞复现离不开顺手的工具。我的工具链主要包括以下几类浏览器与代理工具Chrome 或 Firefox 是首选配合 Burp Suite Community Edition。Burp Suite 的代理功能、Repeater模块和Intruder模块在测试和利用漏洞时不可或缺。你需要配置浏览器代理指向Burp默认127.0.0.1:8080并安装Burp的CA证书以拦截HTTPS流量。漏洞探测与利用辅助虽然本次以手工注入为主以加深理解但sqlmap这样的自动化工具在验证漏洞存在性和快速获取数据时非常高效。确保你的Python环境已安装好并能正常运行sqlmap。代码审计工具一款好的代码编辑器或IDE能极大提升效率。我常用 VS Code 或 PHPStorm。它们强大的搜索、跳转和代码高亮功能能帮助我们在浩如烟海的CMS源码中快速定位可能存在问题的函数和文件。网络调试工具curl命令在命令行下快速发送HTTP请求、测试参数非常方便。有时图形化界面不方便时它就是利器。将这套环境搭建好就像是外科医生准备好了手术台和无影灯接下来我们就可以开始进行“病灶”定位了。3. 漏洞原理深度剖析与定位3.1 SQL注入漏洞核心原理回顾在深入铭飞CMS这个具体案例前我们有必要快速统一一下对SQL注入本质的理解。简单来说SQL注入就是攻击者通过Web应用程序的输入接口如URL参数、表单字段、HTTP头向后台数据库“注入”恶意的SQL代码片段。如果程序没有对用户输入进行充分的过滤和校验而是直接将其拼接进SQL查询语句中执行那么攻击者注入的代码就会被数据库引擎执行。这可能导致数据泄露如拖库、数据篡改增删改、甚至获取服务器权限等严重后果。其根源在于“数据”和“代码”的边界被模糊了——用户输入的数据被当成了程序代码的一部分来执行。3.2 CNVD-2024-06148漏洞点定位根据公开的漏洞信息和CNVD的简要描述这个漏洞通常存在于铭飞CMS的某个后台或前台的参数过滤不严处。我的定位思路是“由外而内由面到点”黑盒模糊测试首先我使用Burp Suite对安装好的铭飞CMS站点进行爬取收集所有的URL端点、表单和参数。然后我重点关注那些看起来像ID、分类、页码等可能直接代入数据库查询的参数例如id,catid,page。使用Burp的Intruder模块对这些参数点插入一些简单的SQL注入测试Payload如单引号‘、and 11、and 12观察服务器返回的响应是否有差异如错误信息、页面内容变化、响应时间延迟。这个过程能快速缩小可疑范围。白盒代码审计在模糊测试发现可疑参数后就需要深入代码印证。我直接在源码目录中全局搜索接收这些可疑参数的PHP文件。在PHP中获取参数通常通过$_GET$_POST$_REQUEST全局数组。例如如果怀疑URL中的id参数就搜索$_GET[‘id’]或$_REQUEST[‘id’]。找到这些接收点后顺着代码逻辑向下看看这个变量是否被直接传递到了SQL查询函数中比如mysql_query()mysqli_query() 或是框架的查询构造器方法。关键检查点是在拼接进SQL语句前这个变量是否经过了有效的过滤函数铭飞CMS可能自带有过滤类或函数如safeHtml()addslashes()intval()等。需要确认过滤是否彻底或者是否存在绕过可能。以我复现的这个漏洞为例经过审计发现漏洞出现在/controller/目录下的某个控制器文件中。该文件的一个方法在处理前端传递的orderBy或类似排序字段参数时直接将其拼接到了SQL语句的ORDER BY子句后面而没有进行任何过滤。ORDER BY后面跟的是字段名通常程序会认为这是预定义的几个值之一但这里却直接从用户输入中获取造成了注入。3.3 漏洞利用条件与影响范围分析这个漏洞的利用条件相对宽松。由于注入点可能在后台也可能在前台视具体版本和模块而定如果是前台注入点那么攻击者无需登录即可利用危害等级更高。如果是后台注入点则需要先获得一个后台管理员账号这可能通过弱口令、其他漏洞或社会工程学获得。 漏洞的影响范围直接取决于该CMS的使用量。铭飞CMS在国内有一定数量的用户主要用于企业官网、内容展示等场景。成功利用该SQL注入漏洞攻击者至少可以读取数据库中的任意数据包括管理员账号密码通常是加密的但可尝试破解、用户敏感信息、文章内容等。在特定条件下可能通过UNION查询、堆叠查询或利用数据库特性如MySQL的INTO OUTFILE向服务器写入文件从而获取Webshell进一步控制服务器。 因此这个CNVD编号的漏洞被评定为中高危漏洞是合理的。4. 手工注入实战与Payload构造4.1 信息收集与注入类型判断假设我们通过代码审计或模糊测试确定了注入点位于http://target.com/index.php?mcontentcindexalistcatid123中的catid参数。 第一步是判断注入类型。最经典的方法是插入单引号catid123’。提交后如果页面返回了数据库错误如“You have an error in your SQL syntax”这强烈暗示存在SQL注入并且可能是字符型注入。如果页面显示正常或只是内容为空则可能是数字型注入或者单引号被转义了。 为了进一步确认我们使用逻辑测试提交catid123 and 11 页面正常显示。提交catid123 and 12 页面内容消失或与上一条不同因为12为假查询条件不成立。 如果两者响应有明显差异则确认存在基于布尔Boolean的SQL注入。对于数字型注入Payload通常直接拼接如and 11对于字符型则需要考虑闭合引号如123‘ and ’1‘’1。4.2 逐步获取数据库信息确认注入点后我们开始手工获取信息。这个过程就像剥洋葱一层层深入。判断字段数为了后续使用UNION SELECT查询我们需要知道当前SQL查询语句最终SELECT了多少个字段。使用ORDER BY子句递增数字来测试catid123 order by 5--catid123 order by 10--。当ORDER BY后面的数字超过实际字段数时数据库会报错。通过不断调整我们可以确定字段数例如发现order by 7正常而order by 8报错那么字段数就是7。这里的--是SQL注释符用于注释掉原查询后面的语句避免语法错误。探测回显点知道了字段数假设为7我们构造UNION SELECT语句找出哪些字段的内容会显示在页面上。Payloadcatid-123 union select 1,2,3,4,5,6,7--。注意这里把原查询的catid值改为一个不存在的负值或使原查询结果为空以确保页面显示的是我们UNION SELECT的结果。提交后观察页面原本显示文章标题、发布时间等位置可能会被数字“2”、“3”等替代。这些数字就是回显点比如数字2和5出现在了页面可见区域。获取核心数据现在我们可以把回显点替换成我们想查询的数据库函数。查询当前数据库名catid-123 union select 1,database(),3,4,5,6,7-- 数据库名会显示在第二个字段的位置。查询数据库用户和版本catid-123 union select 1,user(),version(),4,5,6,7--。查询所有表名这需要用到数据库的元信息表。在MySQL中通常是information_schema.tables。Payloadcatid-123 union select 1,group_concat(table_name),3,4,5,6,7 from information_schema.tables where table_schemadatabase()--。group_concat()函数将多行结果合并成一个字符串方便查看。执行后你可能会看到一串表名如ms_admin,ms_article,ms_user等。查询特定表如ms_admin的字段名catid-123 union select 1,group_concat(column_name),3,4,5,6,7 from information_schema.columns where table_schemadatabase() and table_name‘ms_admin’--。这里需要注意table_name的值可能需要用十六进制表示来绕过可能的过滤例如0x6d735f61646d696ems_admin的十六进制。最终拖取管理员账号密码catid-123 union select 1,username,password,4,5,6,7 from ms_admin--。这样管理员的用户名和密码哈希值就可能被显示出来。重要提示以上所有操作仅限在你自己搭建的、合法的测试环境中进行。未经授权对任何线上系统进行测试都是非法行为。4.3 使用Sqlmap进行自动化验证手工注入能让我们透彻理解原理但在验证漏洞存在性或需要快速提取大量数据时自动化工具更高效。以sqlmap为例基本命令如下python sqlmap.py -u “http://your-test-site.com/index.php?mcontentcindexalistcatid123” --batch-u指定目标URL。--batch以非交互模式运行自动选择默认选项。 sqlmap会自动识别参数、测试注入类型。如果确认存在注入你可以进一步使用--dbs枚举所有数据库。-D database_name --tables枚举指定数据库的所有表。-D database_name -T table_name --columns枚举指定表的所有列。-D database_name -T table_name -C “username,password” --dump导出指定列的数据。实操心得sqlmap虽然强大但发出的请求特征明显很容易被WAF拦截。在测试时可以结合--tamper参数使用脚本对Payload进行混淆或者使用--delay设置请求延迟降低请求频率。不过在本地测试环境中这些通常不是问题。5. 漏洞根因分析与修复方案5.1 代码层问题溯源通过复现过程我们可以清晰地看到漏洞的根本原因。问题通常出在类似下面的代码片段此为模拟代码说明原理// 漏洞代码示例 $orderField $_GET[‘order’]; // 直接从用户输入获取排序字段 $sql “SELECT * FROM ms_article WHERE catid123 ORDER BY ” . $orderField . “ DESC”; $result mysql_query($sql);开发者原本可能只期望用户传入如“id”“click”这样的合法字段名。但由于$orderField未经任何过滤就直接拼接进SQL语句攻击者可以传入“id DESC,(SELECT 1 FROM (SELECT SLEEP(5))a)”这样的Payload实现时间盲注或者通过UNION等方式进行联合查询注入。 更深层次的原因是开发人员安全意识不足混淆了“数据”和“代码”。在SQL语句中ORDER BY后面的内容虽然是字段名或表达式但它仍然是查询语句的“代码”部分不应该由用户输入直接控制。5.2 安全修复建议修复此类漏洞的核心原则是对所有用户输入进行严格的、白名单式的过滤和校验。白名单过滤首选方案对于像排序字段orderBy这种参数最佳实践是定义一个允许的字段名数组只接受数组内的值。// 修复代码示例白名单过滤 $allowedFields array(‘id’, ‘title’, ‘click’, ‘add_time’); $orderField $_GET[‘order’]; if (!in_array($orderField, $allowedFields)) { $orderField ‘id’; // 提供一个安全的默认值 } $sql “SELECT * FROM ms_article WHERE catid123 ORDER BY ” . $orderField . “ DESC”;参数化查询/预处理语句针对WHERE子句等值条件对于WHERE子句中的条件值必须使用预处理语句PDO或mysqli_prepare。这是防止SQL注入最根本、最有效的方法因为它将SQL语句的结构与数据完全分离。// 使用PDO预处理语句 $pdo new PDO($dsn, $user, $pass); $stmt $pdo-prepare(“SELECT * FROM ms_article WHERE catid :catid”); $stmt-execute([‘:catid’ $_GET[‘catid’]]); $results $stmt-fetchAll();请注意ORDER BY子句中的字段名不能使用预处理语句的参数占位符因为占位符仅用于值value不能用于标识符identifier如表名、字段名。这就是为什么对于ORDER BY必须用白名单。转义函数次要选择不推荐单独使用像mysql_real_escape_string()这样的函数是为字符串值设计的用于转义特殊字符。它不能安全地用于ORDER BY后的字段名因为字段名不是用引号包裹的字符串值。依赖转义来防止所有SQL注入是一种过时且不安全的方法。框架安全机制如果使用现代PHP框架如Laravel ThinkPHP务必使用其提供的查询构造器Query Builder或ORM如Eloquent它们内部通常已经实现了参数绑定能有效避免SQL注入。对于铭飞CMS用户最直接的修复方案是立即升级到官方发布的最新版本。官方在获悉漏洞后通常会发布安全更新补丁。如果因故无法立即升级则应手动根据漏洞公告或自行审计的结果定位到有问题的代码文件应用上述白名单过滤原则进行修改。6. 复现过程中的常见问题与排查6.1 环境搭建与配置问题问题安装CMS后访问页面报错提示数据库连接失败或表不存在。排查首先检查config/目录下的数据库配置文件如database.php中的主机名、用户名、密码、数据库名是否正确。其次确认MySQL服务是否已启动。最后回想安装过程中是否成功执行了SQL脚本来创建数据库表。可以尝试重新运行安装程序。问题使用Burp Suite拦截不到浏览器流量。排查确认浏览器代理设置是否正确指向了Burp127.0.0.1:8080。检查Burp Suite的Proxy - Options 中代理监听器Proxy Listeners是否处于运行状态Running。如果是HTTPS站点确保已在浏览器中安装并信任了Burp Suite的CA证书。6.2 漏洞探测与利用阶段问题问题插入单引号或测试Payload后页面没有变化也没有报错。排查这可能意味着1该参数不存在注入漏洞2参数被严格过滤或转义了3注入点是盲注布尔盲注或时间盲注页面没有直接回显错误但内容有细微差别。此时应尝试布尔盲注的Payload如and 11和and 12仔细对比两次响应内容的长度、某个特定关键词是否存在。也可以尝试时间盲注Payload如and sleep(5)观察响应时间是否显著延迟。问题使用UNION SELECT时页面报错“The used SELECT statements have a different number of columns”。排查这是字段数不一致的典型错误。说明你UNION SELECT后面跟的字段数与原查询字段数不同。需要更精确地使用ORDER BY技术来确定字段数。有时原查询字段数较多需要耐心测试。问题知道表名和字段名但用UNION SELECT查询数据时页面不显示。排查首先确认你选择的回显点是否正确即数字是否显示在了页面可见区域。其次检查你的Payload语法特别是引号的闭合。对于字符型注入闭合非常关键。可以利用Burp Repeater模块方便地修改和重放请求观察原始响应有时数据可能隐藏在HTML注释或JS代码中需要查看网页源代码才能发现。6.3 工具使用相关问题问题Sqlmap跑不出来注入点但手工测试明明有反应。排查可能是sqlmap默认的测试级别和风险等级不够。尝试增加级别--level3 --risk3。Level越高测试的Payload和参数越多Risk越高测试的风险性Payload越多如OR类型的注入。另外检查目标参数是否需要特定的Cookie或HTTP头才能访问使用--cookie或--headers参数提供。如果站点有Token或CSRF防护可能需要更复杂的配置。一个我踩过的坑在一次复现中我手工测试确认了注入点但sqlmap始终检测不到。后来发现是因为该注入点仅在POST请求的某个特定参数中存在而我一开始给sqlmap的是GET请求的URL。使用--data参数将POST数据提交给sqlmap后问题迎刃而解。所以明确HTTP请求方法GET/POST和参数位置至关重要。7. 防御视角下的思考与总结完成整个复现过程后站在防御者的角度我有了更深的体会。SQL注入作为一个“古早”的漏洞类型至今仍频繁出现根本原因在于开发环节的安全意识缺失和安全编码习惯的缺乏。对于企业而言除了在开发阶段推行安全编码规范、使用安全的框架和API外在测试和运维阶段也需要部署多层次的安全防护代码审计定期对核心业务代码进行人工或自动化审计尤其是在项目上线前和重大更新后。WAFWeb应用防火墙在应用前端部署WAF可以拦截大量已知和未知的注入攻击Payload为修复漏洞争取时间。最小权限原则为Web应用程序连接数据库的账户分配最小必要的权限通常只赋予SELECTINSERTUPDATEDELETE权限杜绝DROPFILE等危险权限这样即使发生注入也能将损失降到最低。错误信息处理将生产环境的PHP错误显示关闭display_errors Off并使用自定义错误页面。避免将详细的数据库错误信息直接返回给用户这会给攻击者提供大量线索。最后我想强调的是漏洞复现的意义绝不仅仅是“攻击”。通过亲手搭建环境、分析代码、构造利用过程我们才能最深刻地理解漏洞产生的每一个环节从而在设计、开发和审查代码时本能地避开这些陷阱。对于铭飞CMS这个漏洞希望所有使用者都已及时升级。而对于安全研究者或开发者来说这个案例再次敲响了警钟用户输入的每一份数据都必须被当作潜在的威胁来对待唯有通过严格的白名单校验和参数化查询才能构建起稳固的安全防线。