ShiftLeft 学习笔记(二)

上一篇博客简单的对shiftleft的inspect部分进行了说明,inspect适合开发人员对代码的检查,并且能够和github相结合。但是对安全研究人员应用有限。本文忽略了PROTECT部分,直接对OCULAR进行说明

一 基本说明

本文将向您展示如何开始使用Ocular。更具体地说,您将学习如何:下载、安装并启动Ocular;创建您的第一个CPG并将其加载到内存中以供使用。

要求:在继续之前,您必须

安装并通过installed和ShiftLeft进行身份验证之后,您将可以访问ShiftLeft命令行工具。

下载ocular,运行:sl ocular

ShiftLeft自动创建. ShiftLeft /ocular目录,该目录是安装Ocular的位置。

二 基本操作

1 Starting Ocular

下载完Ocular后,再次运行sl ocular来启动程序。当Ocular准备好了,你就会看到了:

 ██████╗  ██████╗██╗   ██╗██╗      █████╗ ██████╗
██╔═══██╗██╔════╝██║   ██║██║     ██╔══██╗██╔══██╗
██║   ██║██║     ██║   ██║██║     ███████║██████╔╝
██║   ██║██║     ██║   ██║██║     ██╔══██║██╔══██╗
╚██████╔╝╚██████╗╚██████╔╝███████╗██║  ██║██║  ██║
 ╚═════╝  ╚═════╝ ╚═════╝ ╚══════╝╚═╝  ╚═╝╚═╝  ╚═╝
Version: 0.3.96
Commands:
loadCpg("name-of-input-file", ["overlay-name", ...])
Welcome to ShiftLeft Ocular/Joern
ocular>

2 创建代码属性图

一旦你启动了目眼,你可以通过运行createCpg(“<inputPath>”)来为你的应用程序创建一个CPG,其中<inputPath>是你想要为其创建一个CPG的应用程序的路径。

例如:createCpg("/Users/john-doe/HelloShiftLeft/target/hello-shiftleft-0.0.1.jar")

您可以运行workspace命令来查看所有的CPG(注意,简单覆盖指的是CPG的各个层)

workspace
res0: Workspace =
 _________________________________________________________________
 | name                     | overlays                    | loaded|
 |================================================================|
 | hello-shiftleft-0.0.1.jar| semanticcpg,dataflow,tagging| false |

3 将CPG加载到内存中

将一个CPG加载到内存中会使它成为活动的CPG,从而使您的操作针对它执行。要做到这一点,就要跑:

loadCpg("<nameOfCpg>")

只要分配了足够的内存,就可以将尽可能多的cpg加载到工作空间中。

此时,您已经准备好开始使用查询研究您的CPG了。

About Ocular and the CPG

Ocular是一组命令行工具,为应用程序安全性提供了一个静态分析框架。它运行在Linux、macOS和Windows操作系统上,可用于为以下编程语言编写的应用程序生成代码属性图(CPG)

C、C++、C#、Go、Java、LLVM、Scala

Ocular使用眼部查询语言(OQL),这是一种简洁而富有表现力的语言,您可以使用它来编写查询。然后,您可以使用这些查询来探索您的代码库并找到存在的漏洞。

要开始使用,请下载免费的14天试用版Ocular

代码属性图(CPG)

代码属性图(CPG)是应用程序代码的一种多层表示,是由Ocular使用最多的。

Deep-Dive: The CPG

所有的ShiftLeft解决方案都利用了CPG。CPG是一种可扩展的、与语言无关的程序代码表示形式,用于增量式和分布式代码分析。它提供并存储代码的中间表示形式以及分析结果。

在单个图中,CPG提供了每个代码版本的多层表示,包括各种抽象级别。来自CPG的独特见解为所有ShiftLeft解决方案提供了详细的细节和对数据流的深入理解。

有关其他信息,请参见对CPG的理解

1 CPG基本模式

CPG是一个有向的、边缘标记的、带属性的多重图,或者简称为属性图。属性图是许多现代图形数据库的通用数据结构。因此,基于属性图的数据表示可以立即适应图形数据库技术。

属性图在通用性上可与散列表和链表相媲美。为了使它们适合于存储、传输和分析代码,主要的挑战是指定一个合适的图模式。特别是,模式必须定义有效的节点和边缘类型、节点和边缘键以及它们的每个域。最后,模式根据节点的类型对可能连接节点的边的类型进行约束。

基本模式提供了所有有效cpg必须满足的最低要求。基本规范涉及到程序的三个方面:

程序结构、类型声明、方法声明

其中,声明包含正式签名,以及定义内容(如方法的方法体或变量定义中的文字值)。

基本模式规范

CPG的基本模式在JSON文件base. JSON中指定。该文件包含一个JSON对象,包含以下成员

nodeKeys/edgeKeys:所有有效节点/边缘属性的列表。每个列表元素都是一个对象,指定属性的ID、名称、类型和注释。

nodeTypes/edgeTypes:的所有节点/边类型列表(即边缘标签在原始属性图的定义),其中每个节点/边类型是由一个对象,该对象指定一个ID、名称、钥匙、评论,以及节点类型(每个音符是需要强制报告类型,由一个节点属性),即将离任的边缘类型都有效。

在五个类别中有19种节点类型:

类别名称

程序结构

FILE, NAMESPACE_BLOCK

类型声明

TYPE_DECL, TYPE_PARAMETER, MEMBER, TYPE, TYPE_ARGUMENT
方法头METHOD, METHOD_PARAMETER_IN, METHOD_RETURN, LOCAL, BLOCK, MODIFIER

方法体

LITERAL, IDENTIFIER, CALL, RETURN, METHOD_REF
元数据META_DATA

有八种边缘类型

名称用法
AST语法树的边缘结构
CFG控制流边缘——执行顺序和条件
REF引用边缘——引用类型/方法/标识符声明
EVAL_TYPE类型边缘—将已知类型附加到表达式
CALL方法调用边缘—调用者/被调用者关系
VTABLE虚方法表边缘——表示虚表
INHERITS_FROM类型继承边缘——OOP继承模型
BINDS_TO绑定边缘——提供类型参数

在三个类别中有17个节点

类别名称
DeclarationsNAME, FULL_NAME, IS_EXTERNAL
Method headerSIGNATURE, MODIFIER_TYPE
Method bodyPARSER_TYPE_NAME, ORDER, CODE, DISPATCH_TYPE, EVALUATION_STRATEGY,LINE_NUMBER, LINE_NUMBER_END, COLUMN_NUMBER,COLUMN_NUMBER_END, ARGUMENT_INDEX
Meta dataLANGUAGE, VERSION

在基本规范中没有边缘键。

注意通过允许内联注释而偏离了JSON标准。前两个非空白字符等于/的任何行都被视为注释,需要在将定义传递给标准JSON解析器之前对其进行删除。

Program Structure

节点类型:FILE, NAMESPACE_BLOCK

程序结构与将程序组织成文件、名称空间和包有关。一个程序由零个或多个文件(类型文件)组成,每个文件包含一个或多个名称空间块(类型为NAMESPACE_BLOCK)。名称空间块包含类型和方法声明(类型TYPE_DECL和方法)。从文件到名称空间块必须存在抽象语法树(AST)边缘。名称空间块下面的结构元素没有通过边缘连接到它们的AST父元素。相反,使用AST_PARENT_TYPE和AST_PARENT_FULL_NAME属性通知后端方法(类型方法)和类型声明(类型TYPE_DECL)的AST关系。因此,属性FULL_NAME必须是三个节点类型方法TYPE_DECL和NAMESPACE_BLOCK的唯一标识符。该图显示了如何在CPG中表示Java类定义。

名称空间块的概念对应于c++编程语言中的等价概念,其中名称空间块用于将声明放入名称空间中。其他语言,例如Java或Python,不提供相同类型的名称空间块。但是,它们允许在源文件开始处进行包声明,目的是将源文件的所有剩余声明放置到名称空间中。包声明被翻译成这些语言对应的名称空间块。因此,名称空间块的名称是块内所有元素的完整名称空间,而名称空间块的全名是特定块的惟一标识符。对于Java,在名称空间前面加上文件名前缀就足够了,因为每个文件只有一个名称空间描述包语句。

Type Declarations

节点类型:TYPE_DECL、TYPE_PARAMETER、MEMBER、TYPE、TYPE_ARGUMENT

语言结构是通过类型声明来声明类型的。这些构造的示例包括类、接口、结构和枚举。类型声明由名称、类型参数的可选列表、成员变量和方法组成。与其他类型的继承关系可以在类型声明中进行编码。

在CPG中,每个类型声明都由指定的类型声明节点(type TYPE_DECL)表示,该节点至少有一个全称属性。成员变量(类型成员)、方法声明(类型方法)和类型参数(类型TYPE_PARAMETER)通过AST边连接到类型声明,这些边起源于类型声明。继承关系通过INHERITS_FROM边到零个或多个其他类型声明(类型TYPE_DECL)来表示,这表明源类型声明继承自目标声明。

类型的使用,例如在变量的声明中,由类型节点(类型类型)表示。类型节点通过引用边缘(type REF)连接到相应的类型声明,并通过AST边缘(type AST)连接到类型参数。类型参数节点通过绑定边缘(类型BINDS_TO)连接到类型参数。

Method Declarations

方法声明由方法头和方法体组成,其中声明是方法的输入和输出参数的CPG表示,方法体包含方法的指令/语句。

Method Header

节点类型:METHOD、METHOD_PARAMETER_IN、METHOD_RETURN、LOCAL、BLOCK、MODIFIER

方法这个术语在面向对象的编程语言中用于指与类相关联的过程。这个术语在这里更广泛地用于指任何已命名的代码块。此代码可以定义为与类型关联,也可以不定义为与类型关联。该方法由方法头和方法体组成。方法头由一个名称、一个正式的返回参数和一列正式的输入参数和相应的输出参数给出。方法体只是一个语句块。

在CPG中,每个方法由一个指定的方法节点(type METHOD)表示,该节点特别包含方法名。方法通过AST边缘连接到它们的方法输入参数(type METHOD_PARAMETER_IN)、返回参数(type METHOD_RETURN)、修饰符(type MODIFIER)和局部变量(type LOCAL)。方法节点连接到表示方法体的块节点(type BLOCK)。

Method Body

节点类型:LITERAL、IDENTIFIER、CALL、RETURN、METHOD_REF

方法体包含方法实现,由方法执行的操作给出。方法体被表示为方法调用的控制流图,这种表示形式为跨机器级和高级编程语言使用的指令、语句和表达式概念提供了一个公共基础。因此,方法体表示的核心元素是方法调用(“calls”)和控制流边缘。

在CPG中,方法调用由指定的调用节点(type CALL)表示。参数可以是标识符(type IDENTIFIER)、文字(type LITERAL)、其他调用(type CALL)或方法引用(type METHOD_REF)。每个参数都有一个参数索引属性(type ARGUMENT_INDEX)来指示它与哪个参数相关联。调用通过传出的AST边连接到它们的参数,并通过它们的METHOD_FULL_NAME属性关联到被调用的方法。

除了标识符、文字和调用之外,还允许方法引用(type METHOD_REF)表示代码中方法未被调用但被引用的位置,就像编程语言中方法是一等公民的情况一样。方法引用通过引用边缘(type REF)连接到方法实例。

为方法体中的每个位置创建返回节点(type RETURN),其中的控制返回给调用者。无条件控制流边缘是由之前对返回节点的调用创建的。所有剩余的节点根据执行顺序和约束通过控制流边缘(type CFG)连接。方法节点被视为控制流图的入口节点。最后,为方法体创建一个指定的块节点(type BLOCK),并为与语句对应的所有表达式创建传出AST边。

Background on the Method Body Representation

在机器级语言中,过程体由指令定义,并由控制流边连接,形成控制流图。每条指令代表机器执行的一项操作,机器可以修改程序状态。相反,高级语言(C和更高级别)通常会取消指令概念,代之以语句。至于指令,语句可以修改程序状态。它们不同于指令,因为它们可以由多个表达式组成。表达式是接收输入并在计算时产生输出值的匿名代码块。表达式的输入可以是文字和标识符,但也可以是其他表达式。实际上,语句的语义可以通过表达式树进行完全编码,并将控制流边缘附加到这些树的根上,以表示语句的控制流语义。

语句表达多个表达式的能力允许简明的程序公式。然而,它对程序分析提出了挑战。虽然可以通过在语句之间引入控制流边缘来创建控制流图,但是这个图并不编码语句内部的控制流。幸运的是,与编程语言的消除歧义规则相结合的树完全可以在语句中对表达式的求值顺序进行编码。这允许用控制流边缘清楚地表示它们的计算顺序。

表达式由语言提供的运算符的方法计算和应用组成。通过将操作符表示为方法,并允许方法接收其他方法的返回值作为输入,所有表达式都可以表示为方法调用。这样就产生了方法体的程序表示,它由由控制流边缘连接的方法调用组成。

元数据块

元数据块(type META_DATA)包含在CPG中,包含两个字段:一个语言字段(key LANGUAGE),表示生成图的编程语言;一个版本字段(key VERSION),包含规范版本。这两个字段都是自由文本字符串。

Understanding the CPG Layers

代码属性图(CPG)是应用程序代码的多层表示。您可以在您的工作空间中使用单独的层,我们有时将其称为覆盖层。

您可以通过API找到关于CPG层的深入信息。

特别值得注意的是基本层、两个默认层:语义CPG和标记,以及安全配置文件层。

基本层:

Ocular的语言前端组件通过底层将应用程序代码转换为CPG。例如,JavaLanguageFrontend将JAR文件的内容转换为CPG。

基础层是CPG的基础,但是对于检查数据流和漏洞来说没有足够的表达能力。

默认层:当您创建一个CPG或加载一个现有的CPG时,这两个默认层将自动创建并加载到内存中。

语义CPG:语义CPG层将应用程序的方法和类型声明链接在一起。当与基层结合使用时,此层中的语义信息:

介绍基于特定于框架的传递的附加信息

按照策略的指定将信息添加到数据流语义到CPG

标记:标记层标识由策略指定的任何可能的攻击者控制的数据源和接收器。

安全配置文件层:安全配置文件层源自您的策略和CPG,它总结了代码中存在的漏洞和数据泄漏。更具体地说,它描述了诸如此类的事情:

Read operations、Write operations、Transformations、Security-relevant data flows、Information flows、Findings

因为在运行时使用安全配置文件非常昂贵,所以必须显式地创建和加载安全配置文件。这与自动创建的基础层和两个默认层不同。

Working with Ocular

如果你以前从未使用过Ocular,我们建议你从快速开始。《快速起步》将向你展示如何下载、安装和启动眼睛,以及如何创建你的第一个CPG,并将其加载到内存中使用。

一旦您熟悉了使用Ocular的基础知识,您就可以阅读下面的文章来学习如何使用它的附加功能和功能

How to Execute Scripts on Ocular Startup

Ocular查询语言(OQL)用于查询代码属性图(CPGs)和安全配置文件。结果可以集成到您的安全工具中,并用于跨软件开发生命周期(SDLC)共享数据。

使用Scala发明者Martin Odersky首次描述的模式,您可以增强OQL,以便与您的代码库或环境一起使用,以保存经常使用的查询,或将多个查询组合为一个查询。

例如,假设您想要将一个名为fooBarMethod的方法添加到查询中

import io.shiftleft.passes.findings.steps.Finding

class MyMethods(finding : Finding) {
    <b>def fooBarMethod = finding.filterOnEnd(x => x.score >= 8 && x.categories.contains("a1-injection"))</b>
}

implicit def conv(findings: Finding) = new MyMethods(findings)

@main def exec(spFilename: String, outFilename: String) = {
    loadCpgWithOverlays("cpg.bin.zip", spFilename)
    sp.findings.fooBarMethod.l |> outFilename
}

当您使用查询时,此方法的计算方式就好像它是内置的语言元素一样。

How to Update Ocular

您可以通过运行命令行工具来更新您的眼部副本:

sl update ocular

更新时,目视会自动备份工作区中的文件,包括自定义策略。将向您提供有关备份过程的信息,并要求您检查新下载的文件与备份目录中的现有文件之间的差异。

Memory Size Recommendations for Using Ocular

(内存大小推荐)

Ocular规定系统内存的比例,视操作系统而定。例如,Linux的默认配置是25%(例如,如果机器有16g的RAM,那么默认配置是4g)。

为代码属性图(CPGs)启用了磁盘溢出。只有当内存中的条目数量超过最大内存分配时,磁盘溢出才会将缓存条目移动到磁盘。根据查询,ShiftLeft Ocular标识需要加载到RAM中的CPG部分。CPG的所有其他部分都临时存储到磁盘中。

但是,在分析大型应用程序时,磁盘溢出会降低性能。相反,您可以通过内存和磁盘大小的适当组合来优化ShiftLeft Ocular性能,方法可以是您的服务器自动提供,也可以是手动提供。

请注意,估计必要的内存量并不是小事。

您的服务器自动提供

在使用Ocular检查特定的应用程序或应用程序版本之前,请使用以下脚本估计所需的内存大小:

./ocular.sh --script scripts/memory-recommendation.sc --params artifactPath=<inputPath>

确保将<inputPath>替换为应用程序的路径。

在输出的最后一行,眼部返回您需要的推荐堆大小(以MB为单位),以便在该应用程序中运行Ocular,如:

script finished successfully
3633

在上面的例子中,Ocular估计您需要的堆大小为3633兆字节。我们建议您使用一个包含额外20%的堆大小,以确保您的服务器上有足够的物理内存来满足其他需求(例如,Java)。因此,对于本例,您需要使用大约4000兆字节的堆大小。

每次启动目视系统时,可以将以下内容附加到start命令,以确保正确的内存分配:-J-Xmx<heapsize>

你启动Ocular的命令看起来是这样的:./ocular.sh -J-Xmx4000m

手动提供

当您创建和加载一个CPG时,Ocular会确定所需的内存数量并显示此信息。

createCpg("yourApp.jar")
// ...
// debug output from java2cpg
// ...
The cpg.bin.zip you are loading is 63MB on disk and requires approximately 12712MB heap, but the current maximum heap size is 455MB. It is suggested that you provide a larger `-J-Xmx` setting, e.g. `ocular.sh `-J-Xmx14g` to ensure that your machine has sufficient free physical memory available. Otherwise, disk overflow is automatically enabled, slowing performance.

当这种情况发生时,您可以使用CTRL-c取消当前CPG的加载。然后,使用CTRL-c关闭ShiftLeft,然后用更多的内存(./ocular.sh -J-Xmx14g)重新启动它。

如果可用堆不够,您将看到类似下面的输出,表明部分CPG存储在磁盘上,这将降低Ocular的性能:

INFO heap usage (after GC) was 0.87 -> scheduled to clear 100000 references (asynchronously)
INFO attempting to clear 100000 references

Using the Workspace

工作空间是所有Ocular数据的容器(在内存或磁盘上)。工作空间允许您使用多个代码属性图(cpg),可以使用安全性配置文件(SP),也可以不使用。您可以同时加载、处理和组合针对多个cpg的查询。

当您第一次创建一个CPG时,Ocular会自动创建您的工作空间。

查看工作区的内容:

以查看工作区的内容:

workspace

您将看到关于CPG、它们的覆盖(或层)以及特定CPG是否已加载到内存中的信息:

ocular> workspace
res0: Workspace =
 _________________________________________________________________
 | name                     | overlays                    | loaded|
 |================================================================|
 | hello-shiftleft-0.0.1.jar| semanticcpg,dataflow,tagging| false |

测定活性CPG:默认情况下,您执行的所有操作都将在上次加载到内存中的CPG上执行(这被认为是活动的CPG)。您可以确定活动的CPG运行workspace。列表底部的CPG是活动的CPG。

重置您的工作区:要清除工作空间(即从内存和磁盘中删除所有cpg和层):workspace.reset

重置活动的CPG:您只能使用workspace.deleteCurrentRecord 重新创建它的活动CPG来重置它

Interactive vs. Non-Interactive Mode

Ocular 允许您在两种模式中执行代码分析:交互式的(例如,使用REPL)、非交互式的(例如,使用脚本)

交互式

read eval print loop (REPL)是一种交互式shell,可以与可视化查询语言(OQL)一起使用。REPL提供了一些实用程序,用于将安全分析结果导出为纯文本或JSON格式、readline支持和tab-completion等。它是基于Ammonite,所以它的许多记录的特点适用。

底层shell本质上是一个交互式Scala shell,支持以下键盘命令:

命令描述
CTRL-c取消当前操作/清除外壳。不退出
CTRL-dQuits Ocular (shell must be clear)
TAB自动完成
UP浏览命令历史记录
CTRL-LEFT/RIGHT逐句执行命令(而不是逐个字符)
CTRL-r搜索命令历史。使用CTRL-r(或UP/DOWN)来循环匹配

动态导入其他脚本:您可以在任何时候动态加载其他脚本。

作为一个例子,让我们假设有一个名为MyScript.sc的文件。只包含val elite = 31337。您可以按如下方式导入脚本:

import $file.MyScript
MyScript.elite
res1: Int = 31337

如果文件在子文件夹中(如scripts),使用点语法:import $file.scripts. myscript。要向上移动一个目录,使用^。

动态地向JVM类路径添加依赖项:

// java dependency
import $ivy.`com.michaelpollmeier:versionsort:1.0.1`
versionsort.VersionHelper.compare("2.1.0", "2.0.10")
// res: Int = 1

// scala dependency
import $ivy.`com.michaelpollmeier::colordiff:0.9`
colordiff.ColorDiff(List("a", "b"), List("a", "bb"))
// color coded diff

如果依赖项不在Maven Central上,则可以添加一个解析器

interp.repositories() ++= Seq(coursierapi.MavenRepository.of("https://shiftleft.jfrog.io/shiftleft/libs-snapshot-local"))

浏览的结果是类似较少的查看器

browse(cpg.method.name.l)

在运行计算时测量时间

time { 
  println("long running computation")
  Thread.sleep(1000)
  42
}
// res: (42, 1000332390 nanoseconds)

非交互式

在非交互模式下使用。您将通过指定为参数的脚本执行命令和操作,而不是在视觉提示之后手动输入它们。Ocular 运行命令在您的脚本和退出时完成。

作为一个例子,假设您在test.sc中包含以下内容:

@main def exec(cpgFile: String, outFile: String) = {
   loadCpg(cpgFile)
   cpg.namespace.name.l |> outFile
}

您可以在test中包含Scala代码。并使用|>操作符将输出管道传输到文件中。然后脚本按如下方式运行

./ocular.sh --script test.sc --params cpgFile=/src.path.zip, outFile=output.log

导入其他脚本:如果您的脚本依赖于来自一个或多个附加脚本的代码,那么您可以使用——import参数,它接受一个逗号分隔的输入脚本列表

./ocular.sh --script test.sc --params cpgFile=/src.path.zip, outFile=output.log --import scripts/hello.sc

How to Create a Code Property Graph (CPG)

本文展示了如何使用Ocular 创建应用程序的代码属性图(CPG)。第一部分向您展示了创建CPG的最简单方法,随后的部分将介绍如何根据应用程序的独特需求创建CPG。

创建代码属性图(CPG)

一旦你启动了Ocular ,你可以通过运行createCpg(“<inputPath>”)来为你的应用程序创建一个CPG,其中<inputPath>是你想要为其创建一个CPG的应用程序的路径。

例如:createCpg("/Users/john-doe/HelloShiftLeft/target/hello-shiftleft-0.0.1.jar")

可以在名为CPG.bin.zip的文件中以二进制格式找到新创建的CPG。它是在当前工作空间中创建的,并自动加载到内存中。ShiftLeft将把它视为活动的CPG。

为多个应用程序创建单个CPG

您可以为多个应用程序(例如,一个应用程序及其依赖项)创建单个CPG。为此,在createCpg命令中包含所有文件的路径:

createCpg("hello-shiftleft-0.0.1-SNAPSHOT.jar", "dependency1", "dependency2"

创建代码属性图(CPG)和安全配置文件(SP)

在默认情况下,Ocular 只会为你的应用程序创建一个带有基本层和默认层的CPG;如果您希望它也创建一个安全配置文件,请使用createCpgAndSp命令:

createCpgAndSp(<inputPath>)

CPG和安全配置文件都是在您的工作区中创建并加载到内存中。x_securityprofile文件包含二进制格式的安全配置文件。

创建包含由名称空间组织的对象的CPG:如果您的应用程序使用名称空间(例如Java包)来组织对象,您可以指定包含您希望在CPG中表示的代码的名称空间

createCpg(<inputPath>, <namespace>)

<namespace>是您希望包含在CPG中的一个或多个名称空间(以逗号分隔):createCpg("hello-shiftleft-0.0.1-SNAPSHOT.jar", List("org.foo", "org.bar"))

How to Create a Security Profile (SP)

安全配置文件是总结应用程序代码中存在的漏洞和数据泄漏的CPG层。它是信息如何流动的高级抽象。更具体地说,安全配置文件进行了以下描述:

Read operations、Write operations、Transformations、Security-relevant data flows、Information flows

Ocular 根据应用程序的默认策略生成安全配置文件,并将其表示为CPG的一个层。可以使用查询和自定义策略更新安全配置文件。

与基本层和两个默认的CPG层不同,您必须显式地创建安全配置文件。

生成安全配置文件

安全配置文件以二进制格式包含在名为x_securityprofile的文件中,它可以通过以下三种方式之一生成。

1 在创建CPG时创建安全配置文件

可以使用命令createCpgAndSp(<inputPath>)创建CPG并同时生成SP,其中<inputPath>是应用程序的路径。

2 在创建CPG之后创建安全配置文件

如果您已经创建了一个CPG,并且希望在以后创建SP,那么您可以使用createSp(<nameOfCpg>),将<nameOfCpg>替换为您希望使用的特定CPG的名称。

3 在创建CPG之后,将安全配置文件创建为一个层

使用createCpgAndSp()命令的另一种方法是在创建CPG时明确地将SP生成为一个层

createCpg(<inputPath>, List(<layer>))

<layer>是你想要创建的;如果您想创建多个层,可以使用逗号分隔它们。例如,下面的命令生成CPG,以及两个默认层和SP层

createCpg(subjects/hello-shiftleft-0.0.1-SNAPSHOT.jar", List("semanticcpg", "tagging", "securityprofile"))

Loading a Security Profile

在使用安全配置文件(SP)之前,必须将其加载到内存中。当您生成安全配置文件时,它会自动加载到内存中。

但是,您可以通过运行loadSp(<app.sp>)在任何时候加载现有的安全配置文件。一旦你加载了SP,你就可以像运行其他CPG层一样对它运行操作。

How to Load / Unload a CPG

您创建的所有层都将自动保存到您的工作区并加载到内存中,在那里它们被视为活动的CPG。您执行的任何操作都将在活动的CPG上执行(通常,最近加载到内存中的CPG是活动的CPG)。

将CPG加载到内存中

将一个CPG加载到内存中会使它成为活动的CPG,从而使您的操作针对它执行。要做到这一点,就要跑:loadCpg("<nameOfCpg>")

只要分配了足够的内存,就可以将尽可能多的cpg加载到工作空间中。

从内存中卸载一个CPG

卸载一个CPG会从内存中删除它,但不会从磁盘中删除它。当您卸载一个CPG时,第二个最近加载的CPG将成为活动的。

要卸载CPG,运行unloadCpg。

如果有多个CPG加载到内存中,您可以通过在命令中包含它的名称来卸载特定的CPG: unloadCpg(“<nameOfCpg>”)。

从磁盘中删除一个CPG

从磁盘删除CPG也会将它从工作空间中删除。当您删除一个CPG时,最近加载的第二个CPG将变为活动的。

要删除活动的CPG: deleteCpg

要删除特定的CPG: deleteCpg(<nameOfCpg>)

How to Query a CPG

一旦Ocular 为您的应用程序创建了一个代码属性图(CPG),您就可以使用查询来仔细检查CPG(以及您的应用程序)。

在Ocular ,有两种类型的查询:默认和自定义。

注意:在研究数据流时,我们建议使用策略来代替查询。本文的最后将包含关于查询和策略之间关系的高级信息。

查询:查询是使用可视化查询语言(OQL)编写的。您可以仅对活动的CPG或已加载到工作区的内存中的所有CPG运行查询。您还可以组合查询,每个查询都适用于一个或多个cpg。

下面的示例演示了如何使用OQL来编写查询以及如何使用查询。

得到活动的CPG:活动CPG是您的工作空间中最近加载的CPG。您可以使用CPG .method. fullname .l获得活动的CPG。

如果您的工作空间中有多个cpg,那么您可以使用CPGs.flatmap(_.method.fullName.l)查询它们并连接结果。请注意,此查询将连续针对单个cpg运行;cpg没有被合并。

组合多个cpg的查询

要组合来自多个cpg的查询,请使用:cpgs.flatMap{cpg => cpg.method.l }

调查安全性配置文件

安全配置文件包含发现的技术漏洞的摘要。与CPG的其他层不同,您必须手动生成和加载安全配置文件。

您可以使用以下命令查询安全配置文件:

cpg.finding.p.<finding>
or
cpg.finding.toJsonPretty

结果查询

如果您的查询结果是广泛的,您可以使用以下命令来打开一个类似于lesslike (pager)的应用程序并滚动结果:browse(<query>)。请确保将<query>替换为您的实际查询。

将查询结果写入文件

创建一个新文件并将结果写入文件,使用  <query>.l |> "output.txt"

如果希望将结果附加到现有文件(例如,output.txt),请运行   <query>.l |>> "output.txt"

关于列表格式的注意事项:Ocular 使用.l(而不是.p)来生成特定于Scala的列表格式的输出。

如果你用.l 将结果写入文件(如cpg.finding.l |> "test.txt")。该命令附加对象引用。因此,我们建议您附加所有字符串,例如由cpg.method.toJsonPretty这样的查询产生的字符串。

查询和政策

策略只是查询的集合。有默认策略和自定义策略。

默认策略用于确定应用程序如何与外部世界通信、数据上存在哪些转换以及哪些信息流应该被视为安全违规。通过运行默认查询获得的结果被合并到您的安全配置文件中,该配置文件通过汇总漏洞和数据泄漏来自动进行代码分析。

自定义策略是由您创建的,以构建在由Ocular 自动生成的结果上。例如,您可能对您的代码有额外的了解,您希望通过Ocular 系统来考虑这些信息——这些信息将通过自定义策略来提供。

How to Enhance the Ocular Query Language (OQL)

当启动Ocular ,你可以选择有脚本自动执行。

为特定的会话执行脚本

您可以为特定的会话执行初始化脚本

举个例子,假设你有一个脚本,myScript1.sc,内容如下

echo 'def foo = 42' > scripts/myScript1.sc

使用sl目镜启动Ocular ,加载CPG,并使用runScript命令

cpg.runScript("scripts/myScript1.sc")

在运行脚本时,您将看到以下响应

ocular> foo
res0: Int = 42

为所有会话执行脚本

要在每次启动Ocular时执行初始化代码,请将其写入~/中的.sc文件。shiftleft /Ocular目录中。我们建议将您的文件命名为predef.sc。但在默认情况下,当目录启动时,Ocular会执行该目录中扩展名为.sc的所有文件。

例如,假设您已经创建了predef.sc文件如下

echo 'def foo = 42' > ~/.shiftleft/ocular/predef.sc

开始使用sl Ocular

You'll see the results of the file having been run:

```scala
ocular> foo
res0: Int = 42

Tutorials

下面的教程将向您展示如何使用Ocular识别漏洞,调查运行时问题,等等。(后续待翻译)

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值