某次实战代码审计出sql注入漏洞记录
字数 1602 2025-08-10 08:28:27

ASP.NET SQL注入漏洞审计实战分析

漏洞背景

在某次实战项目中,审计人员对一套ASP.NET开发的CMS系统进行代码审计时,发现了多处SQL注入漏洞。本文详细记录其中一处较为典型的注入漏洞的发现和分析过程。

系统环境分析

  1. 系统架构:ASP.NET运行环境
  2. 关键文件
    • Global.asax:提供全局可用代码,包括应用程序事件处理程序
    • web.config:基于XML的配置文件,存储数据库连接字符串等
  3. URL重写机制:系统使用URL Rewrite将请求重定向到处理程序(如/api/a/b/c请求会被转发到/api/a/b/c.ashx

漏洞定位过程

  1. API目录结构分析

    • /api/user:需要登录
    • /api/manager:需要登录
    • /api/common:公开访问(最终漏洞点)
  2. 漏洞文件定位

    • /api/common/search.ashx中发现漏洞
    • 后端代码位于xxxxcms.web.dll

代码审计分析

1. 请求处理流程

  1. ProcessRequest()方法:

    • 获取URL中action参数值
    • action=search_tip时调用GetsearchTip()方法
  2. GetsearchTip()方法处理逻辑:

    // 获取并处理POST请求中的val参数
    string val = PostTagValue(context.Request, "val");
    val = UnEscape(val);
    
    // 设置默认types值
    string types = PostTagValue(context.Request, "types");
    if (string.IsNullOrEmpty(types))
        types = "content";
    
    // 将val参数拼接到condition数组
    string[] condition = new string[] { types, val };
    
    // 执行查询
    ResultSet(condition);
    
  3. ResultSet方法最终调用SelectRecords存储过程执行SQL查询

2. 关键安全缺陷

  1. 过滤与解码顺序问题

    • 先使用PostTagValue()过滤危险字符
    • 然后使用UnEscape()进行解码处理
    • 这种顺序导致可以绕过过滤
  2. PostTagValue()过滤函数:

    • 过滤单引号等大量危险字符
    • 但过滤后的数据会被UnEscape()解码
  3. UnEscape()函数功能:

    • 处理两种编码格式:
      1. Unicode编码(%u开头的编码)
      2. URL编码(%后跟两个十六进制数字)
    • 将编码后的字符解码为原始字符

漏洞利用原理

  1. 绕过过滤的方法

    • 将SQL注入payload先进行编码(URL编码+Unicode编码)
    • 将Unicode编码中的\u替换为%u
    • 这样能绕过PostTagValue()的过滤
    • 然后被UnEscape()解码为原始注入语句
  2. 不同Content-Type的处理差异

    • application/x-www-form-urlencoded
      • 后端会先自动URL解码一次
      • 需要将payload双重URL编码
    • 上传格式(如multipart/form-data):
      • 不会自动URL解码
      • 只需单次编码即可

漏洞复现步骤

  1. 构造恶意请求

    POST /api/common/search.ashx?action=search_tip HTTP/1.1
    Content-Type: application/x-www-form-urlencoded
    
    val=%25%37%35%25%36%66%25%36%39%25%36%65%25%36%34%25%36%36%25%37%35%25%36%65%25%36%33%25%37%34%25%36%39%25%36%66%25%36%65%25%32%38%25%32%39%25%32%64%25%32%64
    
  2. 编码解释

    • 原始payload:unionfunction()--
    • 第一次URL编码:%75%6f%6e%69%6f%6e%66%75%6e%63%74%69%6f%6e%28%29%2d%2d
    • 第二次URL编码(针对application/x-www-form-urlencoded):对每个%再次编码为%25
  3. multipart/form-data方式

    • 只需将payload进行一次URL编码+Unicode编码
    • \u替换为%u

修复建议

  1. 代码层面

    • 调整过滤顺序,先解码再过滤
    • 使用参数化查询或ORM框架
    • 对用户输入进行严格类型检查
  2. 架构层面

    • 实施最小权限原则
    • 使用Web应用防火墙(WAF)
    • 定期进行安全审计和代码审查

经验总结

  1. 审计重点

    • 关注用户输入的完整处理流程
    • 特别注意编码/解码与过滤的顺序
    • 注意不同Content-Type的处理差异
  2. 开发启示

    • 安全措施应该放在数据处理的最早阶段
    • 不要依赖单一的安全控制
    • 对用户输入保持零信任原则
  3. 扩展思考

    • 类似问题可能存在于其他解码场景(如base64、HTML实体编码等)
    • 审计时应关注所有数据处理管道中的每个环节
ASP.NET SQL注入漏洞审计实战分析 漏洞背景 在某次实战项目中,审计人员对一套ASP.NET开发的CMS系统进行代码审计时,发现了多处SQL注入漏洞。本文详细记录其中一处较为典型的注入漏洞的发现和分析过程。 系统环境分析 系统架构 :ASP.NET运行环境 关键文件 : Global.asax :提供全局可用代码,包括应用程序事件处理程序 web.config :基于XML的配置文件,存储数据库连接字符串等 URL重写机制 :系统使用URL Rewrite将请求重定向到处理程序(如 /api/a/b/c 请求会被转发到 /api/a/b/c.ashx ) 漏洞定位过程 API目录结构分析 : /api/user :需要登录 /api/manager :需要登录 /api/common :公开访问(最终漏洞点) 漏洞文件定位 : 在 /api/common/search.ashx 中发现漏洞 后端代码位于 xxxxcms.web.dll 中 代码审计分析 1. 请求处理流程 ProcessRequest() 方法: 获取URL中 action 参数值 当 action=search_tip 时调用 GetsearchTip() 方法 GetsearchTip() 方法处理逻辑: ResultSet 方法最终调用 SelectRecords 存储过程执行SQL查询 2. 关键安全缺陷 过滤与解码顺序问题 : 先使用 PostTagValue() 过滤危险字符 然后使用 UnEscape() 进行解码处理 这种顺序导致可以绕过过滤 PostTagValue() 过滤函数: 过滤单引号等大量危险字符 但过滤后的数据会被 UnEscape() 解码 UnEscape() 函数功能: 处理两种编码格式: Unicode编码( %u 开头的编码) URL编码( % 后跟两个十六进制数字) 将编码后的字符解码为原始字符 漏洞利用原理 绕过过滤的方法 : 将SQL注入payload先进行编码(URL编码+Unicode编码) 将Unicode编码中的 \u 替换为 %u 这样能绕过 PostTagValue() 的过滤 然后被 UnEscape() 解码为原始注入语句 不同Content-Type的处理差异 : application/x-www-form-urlencoded : 后端会先自动URL解码一次 需要将payload双重URL编码 上传格式(如multipart/form-data): 不会自动URL解码 只需单次编码即可 漏洞复现步骤 构造恶意请求 : 编码解释 : 原始payload: unionfunction()-- 第一次URL编码: %75%6f%6e%69%6f%6e%66%75%6e%63%74%69%6f%6e%28%29%2d%2d 第二次URL编码(针对application/x-www-form-urlencoded):对每个%再次编码为%25 multipart/form-data方式 : 只需将payload进行一次URL编码+Unicode编码 将 \u 替换为 %u 修复建议 代码层面 : 调整过滤顺序,先解码再过滤 使用参数化查询或ORM框架 对用户输入进行严格类型检查 架构层面 : 实施最小权限原则 使用Web应用防火墙(WAF) 定期进行安全审计和代码审查 经验总结 审计重点 : 关注用户输入的完整处理流程 特别注意编码/解码与过滤的顺序 注意不同Content-Type的处理差异 开发启示 : 安全措施应该放在数据处理的最早阶段 不要依赖单一的安全控制 对用户输入保持零信任原则 扩展思考 : 类似问题可能存在于其他解码场景(如base64、HTML实体编码等) 审计时应关注所有数据处理管道中的每个环节