原创 | CodeQL与AST之间联系

渗透技巧 1年前 (2023) admin
228 0 0

点击蓝字




关注我们



前言



Part 1

原创 | CodeQL与AST之间联系

为什么要学习Java抽象语法树呢?

在计算机科学中,抽象语法树(abstract syntax tree 或者缩写为 AST),或者语法树(syntax tree),是源代码的抽象语法结构的树状表现形式,这里特指编程语言的源代码。树上的每个节点都表示源代码中的一种结构。

先用一个示例来看看AST作用

package com.github.javaparser;
import java.time.LocalTime;
public class TimePrinter { public static void main(String[] args) { System.out.println(LocalTime.now()); }}

原创 | CodeQL与AST之间联系

可以看到导入包

原创 | CodeQL与AST之间联系

方法声明主体

原创 | CodeQL与AST之间联系

整个类全部信息

可以看出来用树状结构表示一个类的结构是方便的,但即使是这样子,学习AST对安全来说貌似也没啥关系。那我们再来看一个示例

    class Comparator implements java.util.Comparator<PropertySource>, Serializable {        private static final long serialVersionUID = 1L;        @Override        public int compare(final PropertySource o1, final PropertySource o2) {            return Integer.compare(Objects.requireNonNull(o1).getPriority(), Objects.requireNonNull(o2).getPriority());        }    }

如果用ql形式去找上面这个类Comparator,那我们需要的用到ClassOrInterface。首先可以判断实现了Comparator和Serializable接口,那么可以用ClassOrInterface简单判断一下名字是否一致即可。

import java
class MySerializableImpl extends ClassOrInterface{ MySerializableImpl(){ this.getName() = "Comparator" }}predicate isMyClass(Class m){ m.getASourceSupertype() instanceof MySerializableImpl    and m.getASourceSupertype() instanceof TypeSerializable
}

from Class cwhere isMyClass(c)select c

如果ql大部分查询是基于AST语法之上的,通过查看AST语法树的图不难发现所有的实现类都是一个类型ClassOrInterfaceType

原创 | CodeQL与AST之间联系

学习AST可以更好的知道ql的规则,不至于不知道调用啥类型的去查询。并且学习AST可以大大将复杂冗杂且抽象的代码使用树状形式表现更加直观易懂的形式。学习AST适合做代码审计、代码分析、漏洞分析、安全研究等之类人群。


AST——Java导出的几种格式的方法



Part 2

原创 | CodeQL与AST之间联系

直接新建一个maven项目,将下面三个依赖导入。

<dependencies>    <dependency>        <groupId>com.github.javaparser</groupId>        <artifactId>javaparser-core</artifactId>        <version>3.23.1</version>    </dependency>    <dependency>        <groupId>com.github.javaparser</groupId>        <artifactId>javaparser-core-serialization</artifactId>        <version>3.23.1</version>    </dependency>    <dependency>        <groupId>com.github.javaparser</groupId>        <artifactId>javaparser-symbol-solver-core</artifactId>        <version>3.23.1</version>    </dependency></dependencies>

JSON

import com.github.javaparser.ast.CompilationUnit;import com.github.javaparser.serialization.JavaParserJsonSerializer;

import javax.json.Json;import javax.json.stream.JsonGenerator;import javax.json.stream.JsonGeneratorFactory;import java.io.StringWriter;import java.util.HashMap;import java.util.Map;

import static com.github.javaparser.StaticJavaParser.parse;

public class JSONSERDEMO { public static void main(String[] args) {

CompilationUnit cu = parse("class X{java.util.Y y;}"); JavaParserJsonSerializer jsonSerializer = new JavaParserJsonSerializer(); Map<String, ?> config = new HashMap<>(); config.put(JsonGenerator.PRETTY_PRINTING, null); StringWriter writer = new StringWriter(); JsonGeneratorFactory generatorFactory = Json.createGeneratorFactory(config); JsonGenerator jsonGenerator = generatorFactory.createGenerator(writer); jsonSerializer.serialize(cu,jsonGenerator); System.out.println(writer); }}

原创 | CodeQL与AST之间联系

DOT

dot可以使用转化工具转化成png图片,首先运行下面代码会生成X.dot文件。然后我们需要下载Graphviz(Download | Graphviz),配置环境变量后到生成的X.dot文件夹下执行命令dot X.dot -Tpng >X.png

import com.github.javaparser.ast.CompilationUnit;import com.github.javaparser.printer.DotPrinter;
import java.io.FileWriter;import java.io.PrintWriter;
import static com.github.javaparser.StaticJavaParser.parse;

public class DotSerDemo { public static void main(String[] args) { CompilationUnit cu = parse("class X{java.util.Y y;}"); DotPrinter dotPrinter = new DotPrinter(true); dotPrinter.output(cu); try { FileWriter fileWriter = new FileWriter("X.dot"); PrintWriter printWriter = new PrintWriter(fileWriter, true); printWriter.println(dotPrinter.output(cu));
}catch (Exception e){
} }}



原创 | CodeQL与AST之间联系

YAML

import com.github.javaparser.JavaParser;import com.github.javaparser.ast.CompilationUnit;import com.github.javaparser.printer.YamlPrinter;import static com.github.javaparser.StaticJavaParser.parse;
public class YamlSerDEMO { public static void main(String[] args) { CompilationUnit cu = parse("class X{java.util.Y y;}"); YamlPrinter yamlPrinter = new YamlPrinter(true); System.out.println(yamlPrinter.output(cu)); }}

原创 | CodeQL与AST之间联系

XML

import com.github.javaparser.ast.CompilationUnit;import com.github.javaparser.printer.XmlPrinter;import static com.github.javaparser.StaticJavaParser.parse;
public class XmlSerDemo { public static void main(String[] args) { CompilationUnit cu = parse("class X{java.util.Y y;}"); XmlPrinter printer = new XmlPrinter(true); System.out.println(printer.output(cu)); }}

原创 | CodeQL与AST之间联系


AST语法树分析



Part 3

原创 | CodeQL与AST之间联系

前面我们对下面一段源码生成AST语法树图,下面分析一下AST语法树有那些内容。

package com.sumsec.sources.UserDemo;import java.time.LocalTime;public class TimePrinter {public static void main(String[] args) {System.out.println(LocalTime.now());}}

首先是有一个根节点,根节点下面有三个叶子节点,分别是packageDeclarationimportstypes

原创 | CodeQL与AST之间联系

packageDeclaration

packageDeclaration是对应着TimePrinter的包名称,对应ql规则中谓词的hasQualifiedName或者是getQualifiedName

原创 | CodeQL与AST之间联系

举例说明

import java

from Class cselect c.getQualifiedName()

原创 | CodeQL与AST之间联系


imports

imports是对应着导入的包名,示例中导入的包名java.time.LocalTime。对应ql文件中的ImportType模块。

原创 | CodeQL与AST之间联系

举例查看哪里导入org.apache.commons.lang3.compare下的任意类,编写ql规则就能很快找到。

import java
from ImportType i, Class cwhere c.getPackage().getName() = "org.apache.commons.lang3.compare"and i.getImportedType() = cselect i

原创 | CodeQL与AST之间联系

原创 | CodeQL与AST之间联系


Type

原创 | CodeQL与AST之间联系

Type是一个大的模块,除了packageDeclaration和import模块其他所有的内容都属于Types。换一句话说,除了包名和导入的包其他所有的都是属于Type,像Javadoc、method、类名、字段等等。。。

Type模块也是ql重点模块,首先可以type下面的节点是类型是ClassOrInterface,对应是类或者接口主体class f{}

AST的ClassOrInterface是有判断是否是接口,但在ql模块里是没有这个谓词的,将接口和类统一归为Class模块。

总结



Part 4

原创 | CodeQL与AST之间联系

学习AST语法树可以更好程度上了解ql的规则编写与ql开发者对应的编写规则的依据来源,不然有时候确实是有些地方可以无从下手。

虽然ql的语法远不止这些,但学习AST语法树能够让我们从根本上理解为什么ql的规则是这么编写。之前笔者在这块就走了不少弯路,大多数代码审计工具其实多多少少会涉及到AST的知识,另外程序分析里面也有涉及了AST知识。总的来说AST对于有代码分析的需求的研究人员应该是必须的学习之路。

DOT格式导出之后转化成图片,比较直观更加方便、容易获取关键信息。

Update

为了更好的分析AST和CFG,本人写了一款工具。工具官方网站静态程序分析工具主要生成方法的CFG和.java文件的AST(https://spat.sumsec.me/,使用教程也在网站的。是一款开源工具,欢迎大家使用,提交issue和pr。

参考

https://houbb.github.io/2020/05/29/java-ast-04-javaparser-ast

https://javaparser.org/inspecting-an-ast/

https://github.com/javaparser/javaparser/blob/master/javaparser-core-serialization/src/test/java/com/github/javaparser/serialization/JavaParserJsonSerializerTest.java


文末福利

转发此文至朋友圈(不分组,不屏蔽)
即可参与下方抽奖

原创 | CodeQL与AST之间联系


本次奖品是由机械工业出版社独家赞助的《Web漏洞解析与攻防实战》技术书籍。本书是以Web漏洞基本原理为切入点,将相似的漏洞归类,由浅入深、逐一陈述。本书共11章,分别为Web安全概述、计算机网络基础知识、测试工具与靶场环境搭建、传统后端漏洞(上、下)、前端漏洞(上、下)、新后端漏洞(上、下)、逻辑漏洞(上、下),每章以不同的漏洞类型为小节内容,尽可能涵盖已发现和公开的所有重大Web安全漏洞类型。本书配有53个漏洞实战案例,并附赠所有漏洞实战案例的完整源码,方便读者学习,获取方式见封底二维码。

本书可作为代码审计、渗透测试、应急响应、基线核查、红蓝对抗、防御加固等相关工作从业人员的参考资料,亦可作为企业安全管理者开展企业安全建设的技术指南,还可作为大中专院校及Web安全培训班的Web安全培训教材。


原创 | CodeQL与AST之间联系

点击图书封面,了解详


p.s:各位小伙伴注意兑奖时间哦,开奖后2天内未兑奖视为无效。



往期推荐



原创 | Filter内存马及工具检测

原创 | 某厂商数据库审计系统前台RCE挖掘之旅

原创 | XXE利用:结合Local DTD和Error-Based技巧bypass防火墙


原文始发于微信公众号(SecIN技术平台):原创 | CodeQL与AST之间联系

版权声明:admin 发表于 2023年5月10日 下午6:03。
转载请注明:原创 | CodeQL与AST之间联系 | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...