代码审计如何排查漏洞

wen 网络安全 30

本文目录导读:

代码审计如何排查漏洞

  1. 核心审计流程(方法论)
  2. 常见漏洞类型排查清单(按优先级排序)
  3. 高效辅助工具(但不要完全依赖)
  4. 审计报告(输出什么?)
  5. 关键原则总结

代码审计(Code Review)是识别安全漏洞的重要手段,主要目标是在开发阶段发现并修复安全隐患,而非等到生产环境被攻击,以下是系统性地排查漏洞的思路、方法论和常见漏洞点。

核心审计流程(方法论)

好的审计不是漫无目的地“看代码”,而是有策略地“找数据流”。

  1. 明确审计范围与目标

    • 是白盒审计(有源码)还是黑盒/灰盒? 白盒能看逻辑,灰盒能看接口。
    • 关注点: 是寻找特定类型漏洞(如SQL注入),还是全面安全评估?是审计核心业务模块(如支付、登录)还是第三方组件?
  2. “数据流”分析法(最核心)

    • 入口: 追踪所有用户可控的输入点
      • HTTP参数(GET/POST/Body/Header/Cookie)
      • 文件上传
      • 第三方回调、WebSocket消息
      • 环境变量、命令行参数
    • 传递: 数据如何经过过滤、编码、拼接、序列化?是否到达了“危险函数”?
    • 出口/处理: 数据最终被如何处理?
      • 数据库 -> SQL注入
      • 操作系统命令 -> 命令注入
      • 浏览器(HTML/JS) -> XSS
      • 文件系统 -> 路径遍历/文件上传漏洞
      • XML解析器 -> XXE
      • 内部逻辑(如加密、校验) -> 逻辑漏洞
  3. “关键函数/关键字”搜索法(快速扫描)

    • grepripgrep 或 IDE 的全局搜索功能,查找危险函数和敏感关键字。
    • 输出类: printechoinnerHTMLresponse.write
    • 执行类: evalexecsystemshell_execRuntime.getRuntime()subprocess.call
    • SQL类: select…wheremysql_queryPDO::query(特别是未预处理的情况)、EntityManager.createQuery(JPQL拼接)
    • 文件类: file_get_contentsincluderequireInputStreamreadfileunlink
    • 反序列化类: unserializereadObjectpickle.loadsObjectInputStream.readObject()
    • 弱密码/硬编码: password= “123456”key= “hardcoded_key”

常见漏洞类型排查清单(按优先级排序)

SQL注入(最常见、最严重、最经典)

  • 排查点:
    • 动态拼接SQL: 直接使用 “SELECT * FROM users WHERE id = ” + userId 这种形式。
    • 不安全的ORM用法: 某些ORM的 raw()nativeQuery() 方法,或拼接了用户输入的HQL/JPQL。
    • 存储过程: 如果存储过程内部使用了 EXECUTE 拼接字符串。
  • 修复检查:
    • 是否全部使用了参数化查询/预编译(PreparedStatement、参数化查询、ORM的内置查询方法)?
    • 对于 LIKE 子句,是否对输入的 、 进行了转义?

跨站脚本(XSS)

  • 排查点:
    • 反射型: 用户输入(如 $_GET[‘name’])直接不经过滤,出现在 echo 或响应体中。
    • 存储型: 用户提交的评论、文章标题等存入数据库,被其他用户读取时未转义。
    • DOM型: 前端JavaScript直接操作DOM:document.innerHTML = urlParameval(location.hash)$('#output').html(userInput)
  • 修复检查:
    • 是否在输出处进行了上下文相关编码(HTML实体编码、JS编码、URL编码)?而不是仅在输入端过滤(输入过滤不可靠,因为输出场景不同)。
    • 是否设置了 Content-Security-Policy(CSP)头?

文件上传漏洞

  • 排查点:
    • 后缀名白名单: 仅允许 jpg,但攻击者可能上传 .php.jsp.war.exe
    • 内容验证: 是否只检查了 Content-Type(客户端可控)?应检查文件头(Magic Number)或使用图片二次处理库。
    • 路径可控: 上传路径是否包含用户输入(如 导致目录穿越)?
    • 执行权限: 上传目录是否有执行脚本的权限(Web服务器配置)?
  • 修复检查:
    • 文件重命名(使用随机字符串+白名单后缀)。
    • 文件存储在Web根目录外或云存储(如OSS)。
    • 使用专业的上传组件(如 apache-commons-fileupload)。

命令注入

  • 排查点:
    • 系统调用:Runtime.getRuntime().exec(“ping ” + userInput)system(“curl ” + url)
    • ProcessBuilder 参数被拼接。
  • 修复检查:
    • 优先避免调用系统命令。
    • 必须调用时,使用数组形式传递参数(如 exec([“ping”, “-c”, “4”, userInput]))而不是拼接字符串。
    • 严格白名单校验参数内容(只允许IP格式、域名格式)。

路径遍历(Path Traversal)

  • 排查点:
    • 文件读取:readFile(“/var/data/” + fileName)fileName 可为 ../../etc/passwd
    • 文件包含:include(“/templates/” + tplName)
  • 修复检查:
    • 正规化路径(realpath()/ Path.normalize())并检查是否在允许的基目录内(必须加前缀,如 /var/data/)。
    • 使用白名单或ID映射方式选择文件。

反序列化漏洞

  • 排查点:
    • Java:ObjectInputStream.readObject()readResolve()FastJsonJacksonenableDefaultTyping()
    • PHP:unserialize()
    • Python:pickle.loads()yaml.load()
    • .NET:BinaryFormatter.Deserialize()JavaScriptSerializer
  • 修复检查:
    • 避免对不可信数据反序列化。
    • 使用白名单机制(如 ObjectInputFilter(Java)、safe_load() 替代 yaml.load())。
    • 升级有漏洞的序列化库(如Jackson、FastJson、Log4j)。

逻辑漏洞(最难静态检测,需理解业务)

  • 排查点:
    • 权限绕过: 修改 useridrole 参数是否能查看到其他用户数据(水平越权)?普通用户操作管理员接口(垂直越权)?
    • 验证码/重放: 优惠券、红包、抽奖、登录次数未做幂等性限制?Token未失效?
    • 支付逻辑: 修改价格参数(负数、小数)、修改数量参数(整数溢出)、修改支付状态(未支付改为已支付)?
    • 竞争条件: 多次并发请求(如提现、领奖、购买限量商品)是否导致库存扣减错误?
  • 修复检查(需结合业务):
    • 服务端校验: 所有敏感操作(修改、删除、查询)必须二次校验当前用户是否拥有权限(即:永远不要相信客户端传过来的 user_id 作为权限依据)。
    • 原子性操作: 库存、余额操作应使用数据库锁(乐观锁/悲观锁)或分布式锁。

不安全的依赖库/组件

  • 排查点:

    使用了过时的、已知漏洞的第三方库(如 Log4j <=2.14.1、Struts 2 某些版本、低版本 jQuery)。

  • 修复检查:
    • 使用工具检测:OWASP Dependency-CheckSnykTrivy、GitHub Dependabot。
    • 建立依赖库版本管理策略,及时打补丁。

高效辅助工具(但不要完全依赖)

工具能帮你发现规律性的漏洞(如SQL注入、XSS),但逻辑漏洞、业务漏洞、权限漏洞仍需人工判断。

  1. 静态代码分析工具(SAST)
    • 商业: Fortify、Checkmarx、Veracode。
    • 开源: SonarQube(+安全插件)、Semgrep(可自定义规则)、CodeQL(GitHub出品,规则强大)。
  2. IDE/插件
    • VS Code + Semgrep 插件。
    • IntelliJ IDEA + Qodana。
  3. 依赖分析
    • OWASP Dependency-Check(Maven/Gradle插件)。
    • npm auditpip audit

审计报告(输出什么?)

一个高质量的审计报告应包含:

  1. 漏洞详情: 漏洞名称、风险等级、所在文件/行号。
  2. 复现步骤(POC/Demo): 清晰说明如何触发,最好附带请求示例或代码片段。
  3. 影响分析: 攻击者能利用它做什么?(拿数据、提权、控制服务)
  4. 修复建议: 具体的代码修改建议(如:“将第58行拼接SQL改为PreparedStatement”)。
  5. 修复方案: 如果业务无法修改,可提供的临时缓解措施(如WAF规则、配置文件加固)。

关键原则总结

  1. 信任边界: 永远不要信任用户输入

    所有来自客户端、网络请求、第三方API、文件系统的数据,默认都是“恶意”的,直到被证明是安全的。

  2. 深度防御:

    • 输入端做校验(格式、长度、类型)。
    • 转换层(如数据库)做参数化
    • 输出层(如浏览器、系统命令)做编码
  3. 最小权限:

    • 给代码分配最小的数据库权限。
    • 给文件系统分配最小的读写权限。
    • 给用户分配最小的功能权限。
  4. 自动化辅助 + 人工分析。

    • 工具负责扫描明显的、具有语法特征的漏洞。
    • 人负责分析逻辑流、权限控制、业务上下文

开始实战审计时的一个高效技巧:最近改动核心业务接口入手,追踪一个用户输入的参数从 “入口”(HTTP请求) 到 “出口”(数据库、文件、浏览器、系统调用) 的完整路径,通过检查每一步是否被正确处理,能快速发现绝大多数漏洞。

抱歉,评论功能暂时关闭!