Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
codeql-workshop-cve-2021-21380 — 一个涵盖 CVE-2021-21380 的 CodeQL 工作坊 | Kitploit
工具/GitHubGitHub/rvermeulen/codeql-workshop-cve-2021-21380
静态分析漏洞分析代码分析Web安全学习与教育实验室与实践
GitHubrvermeulen/codeql-workshop-cve-2021-21380

codeql-workshop-cve-2021-21380

一个涵盖 CVE-2021-21380 的 CodeQL 工作坊

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享
查看仓库
12511年前尚未审核

CodeQL Java 工作坊:发现 SQL 注入

在本工作坊中,我们将利用语法和语义推理,在 XWiki 平台的评分组件中发现一个 SQL 注入漏洞,该漏洞记录在 CVE-2021-21380 中。

目录

  • CodeQL Java 工作坊:发现 SQL 注入
    • 目录
    • 前提条件与设置说明
      • 在本地机器上
        • 安装
        • 设置步骤
    • 工作坊
      • 学习要点
      • 问题描述
      • 练习
        • 练习 1
        • 间奏 1
        • 练习 2
        • 练习 3
        • 间奏 2
        • 练习 4
        • 练习 5
        • 间奏 3
        • 练习 6
        • 练习 7
        • 练习 8
    • 下一步做什么?

前提条件与设置说明

在本地机器上

请尽量在工作坊前完成本节内容。

安装

  • 安装 Visual Studio Code。

  • 安装 CodeQL 扩展 for Visual Studio Code。

  • 你不需要安装 CodeQL CLI:扩展会自动处理。

  • 克隆此仓库:

    root@kitploit:~
    git clone https://github.com/advanced-security/codeql-workshop-cve-2021-21380.git
    

设置步骤

  • 导入将在工作坊中使用的 CodeQL 数据库:
    • 在资源管理器视图中右键点击 xwiki-platform-CVE-2021-21380.zip 文件,选择 CodeQL: Set Current Database 命令。
    • 数据库将出现在 CodeQL 数据库视图中,可通过活动栏上的 QL 图标访问。
  • 安装分析 Java 代码以及运行练习和解决方案测试所需的依赖。
    • 从命令面板(Cmd/Ctrl+Shift+P)中,搜索并运行 CodeQL: Install Pack Dependencies 命令。
    • 在 VS Code 窗口顶部,在框中输入 github 以过滤列表。
    • 勾选 cve-2021-21380-exercises、cve-2021-21380-exercises-tests、cve-2021-21380-solutions 和 cve-2021-21380-solutions-tests 旁边的复选框。
    • 点击 OK/Enter。
  • 通过运行解决方案的测试来验证一切正常。
    • 打开测试视图,在解决方案项旁边的运行测试按钮(悬停时显示播放图标)上点击。

工作坊

学习要点

工作坊分为多个练习,介绍 Java 的 QL 语言支持,最后以一个最终查询来发现已知的 SQL 注入。 在这些练习中,你将学会:

  • 如何对语法信息进行推理。
  • 如何对语义信息进行推理。
  • 探索 Java 的 QL 语言支持以表达模式。
  • 探索如何复用和扩展现有建模。
  • 使用多个构建块组合出最终查询。

问题描述

在本工作坊中,我们将寻找 XWiki 平台 评分 API 组件中已知的 SQL 注入漏洞。当外部用户控制的信息进入应用程序代码,这些代码不安全地构造 SQL 查询并执行时,就可能出现此类漏洞。

本工作坊讨论的已知 SQL 注入在 GHSA-79rg-7mv3-jrr5 和 GitHub Advisory Database 中有所记录。为了找到 SQL 注入及其可能的变体,我们将处理以下子问题:

  • 识别不可信信息的来源,并在 QL 中建模。
  • 识别执行 SQL 查询的方法(接收点),并在 QL 中建模。
  • 结合上述解决方案,使用污点跟踪确定来源和接收点之间是否存在信息流。

练习

在前几个练习中,我们将利用抽象语法树(AST)对语法信息进行推理,以识别:

  • 安全公告中所述的方法,以建立对漏洞的理解
  • 包含不可信数据的参数,即我们的来源
  • 接受 SQL 语句的方法调用,即我们的接收点

练习 1

通过完成查询 exercise1.ql,找到程序中所有名为 getAverageRating 的方法及其声明类型。

提示
  • java 模块提供了一个 Method 类,用于推理程序中的方法。
  • Method 类提供了成员谓词 getName 和 hasName,用于推理方法的名称。
  • Method 类提供了成员 getDeclaringType,用于推理声明该方法的类型。

解决方案可在查询 exercise1.ql 中找到。

间奏 1

练习 1 的解决方案返回了一个方法列表。其中一些定义在名为 RatingsManager 的接口中,另一些定义在 AbstractRatingsManager 和 RatingsScriptService 类中。

从查询返回的信息以及 XWiki 组件文档 可以推断出:

  • XWiki 采用面向组件的设计,以支持扩展和定制。
  • 易受攻击的方法是某个组件的一部分。
  • 一个组件包含一个用 Role 注解的接口和一个用 Component 注解的实现。
  • 实现 ScriptService 的组件可以通过脚本在 Wiki 页面中访问。

练习 2

通过完成查询 exercise2.ql,找到所有用 Component 注解标注的类。 注意,该注解类型的全限定名为 org.xwiki.component.annotation.Component。

提示
  • /类域类型/,即其超类型的交集,可以在/特征谓词/中使用关键字 this 访问。
  • Class 类提供了一个方法 getAnAnnotation 来获取关联的注解。
  • Annotation 类提供了成员谓词 getType 来推理其类型。
  • Type 类提供了成员谓词 getName 和 hasName 来推理类型的名称。
  • RefType 类(表示类和接口)提供了成员谓词 getQualifiedName 和 hasQualifiedName,用于推理 reftype 的全限定名。

解决方案可在查询 exercise2.ql 中找到。

练习 3

通过完成查询 exercise3.ql,找到所有实现了 ScriptService 接口的组件。

提示
  • Class 类型提供了成员谓词 getASuperType,用于推理类的超类型,即它 extends 或 implements 的类型。

解决方案可在查询 exercise3.ql 中找到。

间奏 2

至此,我们已经从语法上识别出了用户可调用的方法,这些方法的参数将在后续工作坊中被视为不可信数据的来源。

在下个练习中,我们将调查并识别可能的接收点。从练习 1 的结果可以推断出,其中一个实现调用了 getAverageRatingFromQuery 方法。使用类似的查询,我们可以找到 getAverageRatingFromQuery 的声明类型,从而确定 AbstractRatingsManager 类中的实现构造了一个 SQL 语句并将其传递给 search 方法。

search 方法实现在一个依赖中,因此我们无法获得其实现。在下几个练习中,我们将利用可用的类型信息来识别这个 search 方法调用及其声明类型。

练习 4

通过完成查询 exercise4.ql,找到所有对 search 方法的调用,并识别其声明类型。

提示
  • MethodCall 类型为我们提供了推理方法调用的手段。
  • MethodAccess 类型提供了成员谓词 getMethod,用于推理方法调用的目标。

解决方案可在查询 exercise4.ql 中找到。

练习 5

通过完成查询 exercise5.ql,找到所有由接口 XWikiStorageInterface(全限定名 com.xpn.xwiki.store.XWikiStoreInterface)声明的方法的调用。

提示
  • instanceof 关键字可用于声明某个值属于某个类型所表示的值集合。 例如,识别所有对接口方法的调用:

    root@kitploit:~
    import java
    
    from MethodCall ma
    where ma.getMethod.getDeclaringType() instanceof Interface
    select ma
    

解决方案可在查询 exercise5.ql 中找到。

间奏 3

至此,我们已经使用 QL 从语法上描述了可能的来源和接收点。为了确定信息是否在程序中的这些点之间流动,我们将使用污点跟踪进行语义分析。 我们支持的语言的标准库提供了两种数据流机制:

  1. DataFlow 模块支持保持值的流。
  2. TaintTracking 模块支持即使值被修改也能流动。

后者正是我们感兴趣的,因为在 SQL 注入等注入漏洞中,不可信数据通常会变成更大的语句的一部分,然后被执行。

在本工作坊中,我们将复用现有的 SQL 注入污点跟踪配置,并用我们建模的来源和接收点来扩展它,以找到 SQL 注入。为了理解如何扩展配置,我们先看看下面配置的定义。

root@kitploit:~
class QueryInjectionFlowConfig extends TaintTracking::Configuration {
  QueryInjectionFlowConfig() { this = "SqlInjectionLib::QueryInjectionFlowConfig" }

  override predicate isSource(DataFlow::Node src) { src instanceof RemoteFlowSource }

  override predicate isSink(DataFlow::Node sink) { sink instanceof QueryInjectionSink }

  override predicate isSanitizer(DataFlow::Node node) {
    node.getType() instanceof PrimitiveType or
    node.getType() instanceof BoxedType or
    node.getType() instanceof NumberType
  }

  override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
    any(AdditionalQueryInjectionTaintStep s).step(node1, node2)
  }
}

配置中使用的 isSource 和 isSink 谓词都使用了我们之前见过的 instanceof 关键字。RemoteFlowSource 和 QueryInjectionSink 类都是 abstract 类。 这是标准库中常见的模式,允许我们扩展 RemoteFlowSource 和 QueryInjectionSink 类所表示的值集合。

一个扩展 abstract class 的 QL class 并不会细化超类所表示的值集合,而是将子类表示的值添加到超类中。 在接下来的练习中,我们将实现这些子类并构建最终的查询。

练习 6

通过完成查询 exercise6.ql,将练习 3 中识别的组件类的公共方法的参数添加到 RemoteFlowSource 的值集合中。

提示
  • instanceof 关键字可用于声明某个值属于某个类型所表示的值集合。 例如,识别所有对接口方法的调用:

    root@kitploit:~
    import java
    
    from MethodCall ma
    where ma.getMethod.getDeclaringType() instanceof Interface
    select ma
    

解决方案可在查询 exercise6.ql 中找到。

练习 7

通过完成查询 exercise7.ql,将练习 5 中识别的存储接口方法调用的参数添加到 QueryInjectionSink 的值集合中。

提示
  • exists 公式允许引入临时变量,并在 exists 作用域内进行推理。

    以下示例使用 exists 表达式来将方法集合限定为那些被调用的方法。

    root@kitploit:~
    from Method m
    where m.hasName("foo") and exists(MethodCall ma | ma.getMethod() = m)
    select m
    
  • MethodCall 类提供了成员谓词 getQualifier,用于推理方法访问的限定符。

解决方案可在查询 exercise7.ql 中找到。

练习 8

通过完成查询 exercise8.ql,将前面练习的解决方案组合成最终解决方案。

解决方案可在查询 exercise8.ql 中找到。

下一步做什么?

  • 查询中包含一个用于建模 XWiki 框架部分的模块。将其重构为单独的模块文件,并在查询中使用。
  • 我们将不可信数据来源限制为脚本服务组件。研究如何扩展以包含其他来源。
  • 对于接收点,我们限制为直接使用 XWikiStoreInterface。扩展接收点以包括接口实现的直接使用。Class 类提供了成员谓词 extendsOrImplements,Method 类提供了成员谓词 overridesOrInstantiates,可能会有所帮助。
  • 使用来源的定义,通过查询 'Untrusted data passed to external API' 寻找不可信数据的有趣用途。
下载工具