CodeQL 从零到精通第 3 部分:使用 CodeQL 进行安全研究

news/2024/9/18 15:03:49/ 标签: 安全, sqlite, 数据库

查询特定的库方法

在上一篇博文中,我们根据名称匹配函数调用、函数和方法调用,例如,在本[挑战](https://github.blog/2023-06-15-codeql-zero-to-hero-part-2-getting-started-with-codeql/#:~:text=Challenge 9—Find all functions with “command” as part of its name)中。不过,可能会发生某个方法调用在多个库中定义的情况,我们希望将结果细化为仅来自一个特定库的方法调用。

例如,在审计新的代码库时,我们可能希望找到对特定库函数或方法的调用,因为我们知道它可能是新的源或接收器(请参阅本系列的第一部分execute())。我们可以使用静态分析和 CodeQL 做到这一点。那么,我们如何编写和查询特定的库方法?让我们以前面的例子为例,假设我们正在审计 Django 应用程序的 SQL 注入,我们对来自且仅来自的调用感兴趣django.db.connection.cursor()

要在 Django 中直接执行自定义 SQL,我们需要通过调用来获取游标对象connection.cursor()django.db.connection然后在其上调用execute()。通常,它看起来像这样:

from django.conf.urls import url
from django.db import connectiondef show_user(request, username):with connection.cursor() as cursor:cursor.execute("SELECT * FROM users WHERE username = %s" % username)

在 Python 版 CodeQL 中,我们使用API图库来引用外部库函数和类。对于动态语言,由于其动态特性,我们无法唯一地确定给定变量的类型,因此 API 图层提供了从导入到潜在用途跟踪类型的机制。

我们可以 使用以下查询execute从库中找到所有方法调用。django.db

/*** @id codeql-zero-to-hero/3-1* @severity error* @kind problem*/import python
import semmle.python.ApiGraphsfrom API::CallNode node
where node =API::moduleImport("django").getMember("db").getMember("connection").getMember("cursor").getReturn().getMember("execute").getACall()andnode.getLocation().getFile().getRelativePath().regexpMatch("2/challenge-1/.*")select node, "Call to django.db execute"

让我们看一下查询中发生的情况。

首先,我们设置查询元数据。其中最有趣的部分是@kind problem。这意味着每个节点的结果将包含接收器所在的文件名,以及我们在子句中指定的字符串select。总之,它使结果显示更漂亮。

然后,我们定义我们正在寻找API::CallNodes,因此在子句中连接到 API 图(请参阅API模块的文档)的节点from

where子句中,我们过滤nodes来自django带有的库API::moduleImport("django")。然后,我们找到对cursor带有的引用.getMember("db").getMember("connection").getMember("cursor")。这将匹配django.db.connection.cursor。由于我们调用execute对象cursor,我们首先需要使用getReturn()谓词来获取表示创建游标对象的结果的节点 - 这将返回我们django.db.connection.cursor()(请注意末尾的括号)。最后,我们得到代表带有execute方法的节点,getMember("execute")并且getACall()我们得到对节点所代表的方法的实际方法调用execute

乍一看可能很复杂,但其实不然。使用几次后,它就变得非常直观。

挑战 1——查找所有名为“execute”且来自django.db库的方法调用 挑战 2 — 编写查询来查找所有os.system方法调用 挑战 3 — 编写查询以查找所有 Flask 请求

获取与给定结果匹配的所有 QL 类型

CodeQL 中有不同的类型来表示代码库的不同方面。例如,Python 版 CodeQL 中的函数具有 Function 类型或字符串文字,而 Python 版 CodeQL 中的字符串文字具有 Str 类型。如果您不确定某些结果可能具有哪些 QL 类型,则可以使用谓词getAQlClass。例如,我们可以将getAQlClass谓词添加到上一个查询的结果中 — 所有django.db要执行的调用。

/*** @id codeql-zero-to-hero/3-4* @severity error* @kind problem*/
import python
import semmle.python.ApiGraphsfrom API::CallNode node
where node = API::moduleImport("django").getMember("db").getMember("connection").getMember("cursor").getReturn().getMember("execute").getACall()
select node, "The node has type " + node.getAQlClass()

单个节点通常会有许多 QL 类,因此如果您运行此查询,您将看到很多结果,例如MethodCallNodeExecuteMethodCallSqlExecution。如果您在查询所需的内容时遇到问题,getAQlClass谓词可能是一个非常有用的调试工具,但请记住不要在最终查询中使用它,因为使用getAQlClass会影响查询性能。在某些语言中,例如 Java,您可能希望使用 getAPrimaryQlClass 谓词,它返回给定元素所属的主要 CodeQL 类。另请参阅其他调试想法。

getAQlClass挑战 4—运行带谓词的查询

CodeQL 中的污点分析—污点追踪

我在 CodeQL zero to hero 第二部分中简要提到了CodeQL 如何实现污点分析。还有一个挑战展示了如何使用污点分析运行内置的 CodeQL 查询,你一定要尝试一下!

现在我们已经了解了 CodeQL 的基础知识,我们可以编写自己的查询来查找从源到接收器的流。

但首先,让我们先了解一下数据流分析和污点流分析之间的区别。污点流分析允许我们跟踪非值保留步骤。数据流分析则不行。例如,如果受污染的字符串与另一个字符串连接在一起,或者被分配给对象的属性,则污点流分析将允许我们继续跟踪该流,而数据流分析则不允许。有关数据流分析和污点分析的更多信息,请参阅CodeQL zero to hero 第 1 部分。

本地数据流

在深入研究污点分析之前,我们需要介绍两种(子)类型的数据流分析:本地数据流和全局数据流,以及本地污点流和全局污点流。

在 CodeQL 中,本地数据流是指在本地跟踪数据流,例如在单个函数内。与全局数据流相比,它的计算成本更低。本地污点流(在 CodeQL 中称为本地污点跟踪)允许我们跟踪非值保留的流程步骤。

例如,使用本地数据流,我们可以通过查询所有不采用字符串文字的 调用来提高分析的准确性django.dbexecute如果execute调用采用字符串文字,例如:

cursor.execute("SELECT * FROM users WHERE username = 'johndoe'")

或者:

query = "SELECT * FROM users WHERE username = 'johndoe'"
cursor.execute(query)

然后,它不接受任何用户输入,并且我们已经知道它不易受到 SQL 注入


http://www.ppmy.cn/news/1516803.html

相关文章

oc记录 - UIView.layer

UIView属性 layer 在 Objective-C 中,UIView 类有一个名为 layer 的属性,它返回一个 CALayer 对象。这个属性允许你直接操作视图的底层图形层,以便更精细地控制视图的外观和行为。 以下是 UIView 的 layer 属性的一些基本用法: …

使用LinkedHashMap实现固定大小的LRU缓存

使用LinkedHashMap实现固定大小的LRU缓存 1. 什么是LRU? LRU是"Least Recently Used"的缩写,意为"最近最少使用"。LRU缓存是一种常用的缓存淘汰算法,它的核心思想是:当缓存满时,优先淘汰最近最少…

在 FPGA 上实现以太网的“低级”指南

如今,我们日常的网络连接大多是通过无线方式进行的,因此很容易忘记以太网。但它仍然是一种有用的标准,是一个可靠的高吞吐量网络链接的好方法。为此,[Robert Feranec] 和 [Stacy Rieck] 编写了一个关于如何在 FPGA 上使用以太网的…

【Mysql】通过Keepalived搭建mysql双主高可用集群

一、环境信息 主机名ip操作系统mysql版本VIP(虚拟ip)hadoop01192.168.10.200centos7_x865.7192.168.10.253hadoop03192.168.10.202centos7_x865.7 二、mysql集群搭建 两台节点,如果未部署mysql服务,部署文档请看【Mysql】mysql…

模型 PMI思考法

系列文章 分享 模型,了解更多👉 模型_思维模型目录。全面评估,三思而后行。 1 PMI思考法的应用 1.1 个人职业发展中的PMI思考法应用 张华是一位有志于提升自己职业竞争力的职场人士。他正在考虑报名参加一个专业认证课程,以期提…

在我的博士科研生活中,SCI的英语写作一直是我的挑战。

在我的博士科研生活中,SCI的英语写作一直是我的挑战。尽管我不断地努力提高自己的语言水平,但每当我提交文章后,审稿人或编辑总是会指出语言表达的不足之处,让我深感苦恼。于是,我开始寻找专业的润色服务来帮助我提升文…

python如何判断回文

打开JUPTER NOTEBOOK,新建一个PYTHON文档。 n input("Please input string: ") print(n) 我们首先让用户输入要进行判断的字符串,然后打印出来查看一下。 n input("Please input string: ") is_palidrome n[::-1] if n is_palid…

单片机中的存储器讲解

单片机中的存储器 目录 单片机中的存储器常用的存储器易失性存储器RAMSRAMDRAM 非易失性存储器ROMMask ROMPROMEPROME2PROMFlashNOR FlashNADN Flash 单片机里全局变量、局部变量、堆、栈的存储区域区域介绍栈区堆区静态区代码区常量区 内存分区分类四个区域 常用的存储器 易失…

QT常用UI控件

目录 一、引言 二、QT常用UI控件概述 1.按钮(QPushButton) 2.文本框(QLineEdit) 3.标签(QLabel) 4.下拉列表(QComboBox) 5.单选按钮(QRadioButton) 6.复选框…

【OpenCV】SIFT(尺度不变特征变换)算法?

关键词:SIFT Algorithm 文章目录 一、介绍二、什么是 SIFT 算法?2.1 SIFT 算法描述2.2 SIFT 算法示例 三、人类与机器识别3.1 SIFT 在计算机视觉中的应用3.2 SIFT 关键点的优势3.3 示例演示 四、关键点定位关键点选择 五、实验任务指导5.1 计算大小和方…

博弈论详解 2(SG函数 和 SG定理)

传送门:博弈论详解 1(基本理论定义 和 Nim 游戏) 什么是 SG 函数 接着上次的讲解,我们来了解一个更通用的模型。我们把每一个状态变成一个点(在 Nim 游戏里就代表 a a a 数组),如果可以从一种…

安装Win10操作系统时找不到任何驱动器的解决方法

安装Win10操作系统时找不到任何驱动器的解决方法 有时候在一台新电脑上使用U盘安装系统时提示:我们找不到任何驱动器。 如下图所示: 解决方法: 一、按F12(不同电脑进入Bios的按键可能不同)将电脑进入Bios画面&#xf…

DataX(Doris同步数据到SelectDB)

背景 由于之前的doris数仓在本地的服务器,当数据量越来越大,服务器的性能达不到要求,查询数据经常超时,故需要把本地的doris数仓部署到云上,本文以阿里云为例,迁移工具使用的阿里开源的datax。 datax官方文…

client网络模块的开发和client与server端的部分联动调试

客户端网络模块的开发 我们需要先了解socket通信的流程 socket通信 server端的流程 client端的流程 对于closesocket()函数来说 closesocket()是用来关闭套接字的,将套接字的描述符从内存清除,并不是删除了那个套接字,只是切断了联系,所以我们如果重复调用,不closesocket()…

20240828 每日AI必读资讯

8岁女孩玩转AI编程,45分钟打造聊天机器人,Karpathy都看呆了 - 新晋顶流AI代码编辑器——Cursor,已经进化到了“0手工代码”阶段。 - 提供了多个AI模型,包括GPT-4、GPT-4o和Claude 3.5 Sonnet等,可以通过跟大模型聊天…

微服务——远程调用

为什么需要远程调用? 在微服务架构中,每个服务都是独立部署和运行的,它们之间需要相互协作以完成复杂的业务逻辑。因此,远程调用成为微服务之间通信的主要方式。通过远程调用,一个服务可以请求另一个服务执行某些操作或…

【Python机器学习】NLP概述——词序和语法

词的顺序很重要,那些在词序列(如句子)中控制词序的规则被称为语言的语法(也被称为文法)。这是之前的词袋或词向量例子中所丢弃的信息。在大多数简短的短语甚至许多完整的句子中,上述词向量近似方法都可以奏…

设计模式 7 桥接模式

设计模式 7 创建型模式(5):工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式结构型模式(7):适配器模式、桥接模式、组合模式、装饰者模式、外观模式、享元模式、代理模式行为型模式&#xff0…

整合sentinel遇到的小问题

1.运行jar包 ,端口为默认8080 正确命令 java -Dserver.port8090 -Dcsp.sentinel.dashboard.server127.0.0.1:8090 -Dproject.namesentinel-dashboard -jar sentinel-dashboard-1.8.6.jar -D这些指令要在 -jar前面 在宝塔部署时,直接复制到运行命令后…

vue事件监听

我们可以使用 v-on 指令 (简写为 ) 来监听 DOM 事件,并在事件触发时执行对应的 1.回车事件(点击回车触发) confirm 适用uni-app keyup.enter 适用vue3 运用场景:通常在文本框输入的时候使用 2.点击事件(鼠标左键…