codeql前置之AST和污点分析简述

admin 2022年3月30日20:08:15评论240 views2字数 5634阅读18分46秒阅读模式

打算学一下codeql,所以对AST和污点分析要有个大概的理解和知道,内容还应该有很多,但是打算codeql边学边学习AST和污点分析,所以先把一些概念性的东西以及如何使用理清楚,内容不多,主要是写一点然后开始尝试去实战codeql慢慢学习。

污点分析

https://www.k0rz3n.com/2019/03/01/%E7%AE%80%E5%8D%95%E7%90%86%E8%A7%A3%E6%B1%A1%E7%82%B9%E5%88%86%E6%9E%90%E6%8A%80%E6%9C%AF/ 

污点分析

简介 污点源:不受信任的数据来源 

汇聚点:产生了敏感数据操作 

无害处理:通过对数据处理或者移除危险操作使数据流变的安全 

个人理解就是污点源就是用户可控的数据源,汇聚点就是漏洞触发点,无害处理就是通过对可控数据处理或者对漏洞触发点处理。导致漏洞被修复或者无法利用。 

污点分析的流程就是白话文就是对接受用户数据以后,分析对数据或者触发流程进行了无害处理,如果未进行则会产生漏洞,如果处理了则不会产生漏洞的这个过程。

流程分析 

一:识别污点源 

识别污点源的办法,根据参考文章来看,大概有三类 

(1)外部程序传参 (2)应用程序调用的API和数据类型手工标记 (3)机器学习+统计

二:污点传播分析 

污点传播分析可以理解为数据流向,分为显示和隐式分析,我们从下图的代码入手进行分析 

污点源 a 汇聚点 add 无害处理 wuhai

real 其中传入的参数a,而b能够因为a造成数据依赖影响,所以为显示影响 

yin 其中传入的参数a,不会直接对b造成数据依赖影响,但是由于a的循环,导致b也会变化,所以为隐式分析。

codeql前置之AST和污点分析简述

三 无害处理 

简单来说就是把不安全的数据变的安全的处理。比如实体编码,过滤函数等。上图中就是保证数据小于或者等于10; 

四 污点传播分析技术 

分为静态和动态污点传播分析 

静态分析 无需更改或者运行代码,通过分析程序间的数据依赖来检测数据的流向。 

动态分析 就是程序运行过程中通过对污点数据监控来看能否达到污点汇聚点 。 

静态分析 

import java.io.IOException;
public class testRCE { String cmd; public testRCE(String cmd){ this.cmd=cmd; }
private static String filter(String cmd){ if (cmd.equals("calc")){ cmd =""; } return cmd; }
public void exec() throws IOException { filter(this.cmd); Runtime.getRuntime().exec(this.cmd); }
public static void main(String[] args) throws IOException { String cmd = "notepad.exe";//模拟从web端获取到的输入 testRCE t = new testRCE(cmd); t.exec(); }}

我们用一段代码来分析 上图比较能够分辨出来 

污点源 cmd 无害处理 filter 

我们分析污点传播,当我们获取到了输入,污点标记通过testRCE()赋值给了testRCE.cmd,然后通过无害处理,最终走到了污点汇聚exec()方法处,调用了 Runtime.getRuntime().exec(this.cmd)导致了命令执行漏洞。

AST抽象语法树

https://www.geeksforgeeks.org/abstract-syntax-tree-ast-in-java/ https://houbb.github.io/2020/05/29/java-ast-01-javaparser https://houbb.github.io/2020/05/29/java-ast-05-javaparser-flying-visit

解释

AST 主要用于编译器以检查代码的准确性。如果生成的树有错误,编译器会打印一条错误消息。是java编译期间对源代码进行语法分析之后,语义分析之前的操作。用树形结构标识源代码,用元素来标识树的节点。我们可以通过AST对代码进行扫描,并进行逻辑写入,也就是通俗的修改代码。

java编译

java编译主要是以下三个阶段

java源文件->语法java语法分析->生成AST(树形图)->语义分析->编译字节码生成二进制文件

java语法分析

语法分析主要是通过分析源文件中的字符,将其转化为一个规范的token,包含以下三种类型

关键字 public private staticfinal自定义名称 包名,类名,方法变量名等运算符号 +-*/&&||等

涉及库以及类

JavaParser 提供用于生成AST的完整API com.github.javaparserStaticJavaParser 提供快速生成AST的简单API com.github.javaparser.StaticJavaParserCompilationUnit AST的根Visitor 查找AST特定部分的类

JavaParser

<dependency>
<groupId>com.github.javaparser</groupId>
<artifactId>javaparser-symbol-solver-core</artifactId>
<version>3.15.21</version>
</dependency>

CompilationUnit

代表着已经解析完整且语法正确的源代码的java表示,可以看成一个根节点,可以利用这个根节点访问所有的子节点

example
CompilationUnit cu = StaticJavaParser.parse("class e0mlja { int e0m; }");

其中StaticJavaParser能根据下图看出,接收File,Path,code,Reader,Inputstream类型的参数。

(1)CompilationUnit cuFile = StaticJavaParser.parse(new File("C:\Users\yzc\Desktop\untitled2\src\main\java\example.java"));
(2)CompilationUnit cuPath = StaticJavaParser.parse(Paths.get("C:\Users\yzc\Desktop\untitled2\src\main\java\example.java"));
(3)CompilationUnit cuCode = StaticJavaParser.parse("class example {n" +
" public static void main(String[] args) {n" +
" int i=0;n" +
" System.out.println("e0mlja");n" +
" }n" +
"}");
(4)CompilationUnit cuInput = StaticJavaParser.parse(new FileInputStream(new File("C:\Users\yzc\Desktop\untitled2\src\main\java\example.java")));
(5)CompilationUnit cuReader = StaticJavaParser.parse(new InputStreamReader(new BufferedInputStream(new FileInputStream(new File("C:\Users\yzc\Desktop\untitled2\src\main\java\example.java")))));
#### Visitor
可以通过Visitor,来找到我们特定需要修改或者需要寻找的地方。根据下图2可以看各种node部分。当我们需要查找某个节点的时候,只需要在Visitor中重写visit()方法。下图是实例,简要分析一下代码
* 获取需要查找的类的CompilationUnit
* 获取方法并打印出来
* 获取方法的列表并返回
我们对于需要获取或者更改的,通过上图的节点去寻找,这里就举例file和Method。
##### example
import com.github.javaparser.StaticJavaParser;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.body.FieldDeclaration;
import com.github.javaparser.ast.body.MethodDeclaration;
import com.github.javaparser.ast.visitor.VoidVisitorAdapter;
import sun.reflect.generics.visitor.Visitor;

import java.io.*;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.PublicKey;
import java.util.ArrayList;
import java.util.List;

public class ASTtest {
public static void main(String[] args) throws IOException {
CompilationUnit cuFile = StaticJavaParser.parse(new File("C:\Users\yzc\Desktop\untitled2\src\main\java\example.java"));
CompilationUnit cuPath = StaticJavaParser.parse(Paths.get("C:\Users\yzc\Desktop\untitled2\src\main\java\example.java"));
CompilationUnit cuCode = StaticJavaParser.parse("class example {n" +
" public static void main(String[] args) {n" +
" int i=0;n" +
" System.out.println("e0mlja");n" +
" }n" +
"}");
CompilationUnit cuInput = StaticJavaParser.parse(new FileInputStream(new File("C:\Users\yzc\Desktop\untitled2\src\main\java\example.java")));
CompilationUnit cuReader = StaticJavaParser.parse(new InputStreamReader(new BufferedInputStream(new FileInputStream(new File("C:\Users\yzc\Desktop\untitled2\src\main\java\example.java")))));

VoidVisitorAdapter<?> methodVisitor = new MethodNamePrinter();
methodVisitor.visit(cuFile,null);

List<String> methodNames = new ArrayList<>();
VoidVisitorAdapter<List<String>> methodNameCollector = new methodNameCollector();
methodNameCollector.visit(cuFile,methodNames);
methodNames.forEach(value-> System.out.println("Method Name Collected: " + value));

VoidVisitorAdapter FiledVisit = new FiledPrinter();
FiledVisit.visit(cuFile,null);

}

private static class MethodNamePrinter extends VoidVisitorAdapter<Void> {
@Override
public void visit(MethodDeclaration md, Void arg) {
super.visit(md, arg);
System.out.println("Method Name Printed: " + md.getName());
}
}
private static class methodNameCollector extends VoidVisitorAdapter<List<String>> {
@Override
public void visit(MethodDeclaration md, List<String> arg) {
super.visit(md, arg);
arg.add(md.getNameAsString());
}
}

private static class FiledPrinter extends VoidVisitorAdapter<Void> {
@Override
public void visit(FieldDeclaration md, Void arg) {
super.visit(md, arg);
System.out.println("Field Name Printed: " + md.getVariables());
}
}
}

codeql前置之AST和污点分析简述

codeql前置之AST和污点分析简述

codeql前置之AST和污点分析简述

原文始发于微信公众号(e0m安全屋):codeql前置之AST和污点分析简述

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年3月30日20:08:15
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   codeql前置之AST和污点分析简述http://cn-sec.com/archives/854120.html

发表评论

匿名网友 填写信息