惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

B
Blog RSS Feed
K
Kaspersky official blog
Forbes - Security
Forbes - Security
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
P
Proofpoint News Feed
G
GRAHAM CLULEY
V
Vulnerabilities – Threatpost
Security Latest
Security Latest
Scott Helme
Scott Helme
S
Securelist
美团技术团队
T
Threat Research - Cisco Blogs
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
S
SegmentFault 最新的问题
W
WeLiveSecurity
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Apple Machine Learning Research
Apple Machine Learning Research
The Cloudflare Blog
AI
AI
L
Lohrmann on Cybersecurity
S
Security Affairs
Cloudbric
Cloudbric
SecWiki News
SecWiki News
爱范儿
爱范儿
雷峰网
雷峰网
Engineering at Meta
Engineering at Meta
C
Cyber Attacks, Cyber Crime and Cyber Security
大猫的无限游戏
大猫的无限游戏
N
News and Events Feed by Topic
I
InfoQ
S
Secure Thoughts
AWS News Blog
AWS News Blog
A
About on SuperTechFans
Schneier on Security
Schneier on Security
酷 壳 – CoolShell
酷 壳 – CoolShell
The Last Watchdog
The Last Watchdog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
C
Check Point Blog
P
Palo Alto Networks Blog
博客园 - 【当耐特】
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Google DeepMind News
Google DeepMind News
Latest news
Latest news
I
Intezer
博客园_首页
C
CXSECURITY Database RSS Feed - CXSecurity.com
V
V2EX
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
L
LangChain Blog
D
Docker

SumSec's Blog

AI Agent 工程的必然演进:CLI、Skills、Harne… 从安全角度谈Java反射机制--前章 · SUMSEC 从安全角度谈Java反射机制--终章 · SUMSEC 逆向学习fastjson反序列化始 · SUMSEC 2020年研究回顾总结 · SUMSEC Abstract syntax tree classes for … Analyzing data flow in Java · SUM… Annotations in Java · SUMSEC Basic query for Java code · SUMSEC BypassSuper使用介绍说明 · SUMSEC CodeQL Create OpenJdk/Jdk8 Databa… CodeQL library for Java · SUMSEC Navigating the call graph · SUMSEC Overflow-prone comparisons in Jav… Types in Java · SUMSEC Working with source locations · S… Aliases · SUMSEC Expression · SUMSEC Formulas · SUMSEC Javadoc · SUMSEC Modules · SUMSEC Predicates · SUMSEC Queries · SUMSEC Type · SUMSEC Variables · SUMSEC 一道shiro反序列化题目引发的思考 · SUMSEC 修改ysoserial使其支持任意代码执行 · SUMSEC 自定义 ClassLoader 隔离运行不同版本jar包的方式 ·… 2020网鼎杯---Java文件上传wp · SUMSEC CNVD-2020-10487(CVE-2020-1938)tom… JDSRC安全课笔记 · SUMSEC Java反序列化链回显解决方案 · SUMSEC Skipped breakpoint because it hap… Windows Terminal 配置文件 · SUMSEC bypass 学习笔记之绕安全狗bypass safedog · … 一次意外的代码审计----JfinalCMS审计 · SUMSEC 一篇文章读懂Java代码审计之XXE · SUMSEC 从安全角度谈Java反射机制--序章 · SUMSEC 小楼昨夜又春风,你知ysoserial-Gadget-URLDNS… 春眠不觉晓,RCE知多少? · SUMSEC 漫谈Commons-Collections反序列化 · SUMSEC 漫谈Java反序列化 · SUMSEC 白头搔更短,SSTI惹人心! · SUMSEC 记一次面试题 · SUMSEC About Me 关于我 · SUMSEC Apache Flink任意Jar包上传导致远程代码执行 · SU… CVE-2019-1388 UAC提权复现 · SUMSEC CVE-2019-16097 || Harbor任意管理员注册漏洞… Python加密shellcode免杀 · SUMSEC Telegram机器人作为渗透测试框架 · SUMSEC VM虚拟机无法安装vmtools解决|本程序需要您将此虚拟机上安装… 谁能想到,电视遥控器竟成了 Vibe Coding 神器 · SU… 从手改 Skill 到自动进化:评测结果和执行轨迹如何让 Agen… 模型人人都能用,什么才是你能带走的?我的答案是一个可进化的SKIL… 模型人人都能用,什么才是你能带走的?我的答案是一个可进化的Skil… AI 时代 ShiroAttack2 5.x:修改了什么 · SU… 在 AGI 降临前,先给 AI 开一条”脑内弹幕”通道 · SUM… 一篇博文,三种时间:网页幻灯与 Remotion 动效的交付逻辑 … 🔍 别让大模型”想太多”:SKILL开发中的语义陷阱与抗幻觉设计 … 2022 年年度总结 · SUMSEC Java Swing To RCE 漏洞分析 · SUMSEC SpringBoot GatewayEL表达式漏洞分析 · SUM… Sensitive keys in codebases · SUM… 论如何优雅注入 Java 内存马 · SUMSEC SUMSEC 知识点 · SUMSEC VMWare Workspace ONE Access Auth … Spring Framework RCE CVE-2022-229… 相似度算法调研 · SUMSEC CVE-2022-33891 Apache Spark shell… 正则匹配配置不当 · SUMSEC Spring Data MongoDB SpEL CVE-2022… CodeQl Usage Tricks · SUMSEC Spring Boot RCE到内存马探索 · SUMSEC Shiro后渗透拓展面 · SUMSEC shiro反序列化漏洞攻击拓展面–修改key · SUMSEC GitHub Java CodeQL CTF · SUMSEC Hack-Tools 转化成Web · SUMSEC CodeQL与Shiro550碰撞 · SUMSEC CodeQL初见Shiro550 · SUMSEC Java加载动态链接库 · SUMSEC Log4j2 漏洞分析 · SUMSEC Interprocedural-Analysis 过程间分析 · … Data Analysis Foundation 数据分析基础 ·… Data Flow Analysis · SUMSEC Intermediate Representation 中间代表(… PII泄露–用CodeQL识别日志中的PII数据 · SUMSEC CodeQL workshop for Java: Unsafe … 前言 · SUMSEC 漏洞环境的搭建 · SUMSEC Fastjson回显 · SUMSEC Tomcat通用回显学习笔记 · SUMSEC 从Java反序列化漏洞题看CodeQL数据流 · SUMSEC 概述 · SUMSEC 记一次Log4j失败的Gadget挖掘记录 · SUMSEC Ysoserial改造记录 · SUMSEC JNDI注入 · SUMSEC shiro JRMP gadget · SUMSEC Fastjson MySQL gadget复现 · SUMSEC 2021年度总结 · SUMSEC
CodeQL与AST之间联系 · SUMSEC
2023-01-09 · via SumSec's Blog

前言

为什么要学习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());
    }
}

image-20211227104045005

可以看到导入包

image-20211227105053110

方法声明主体

time

整个类全部信息

可以看出来用树状结构表示一个类的结构是方便的,但即使是这样子,学习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 c
where isMyClass(c)
select c 

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

image-20211228101944016

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


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

直接新建一个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);
        
    }
}

image-20211228110649571

DOT

dot可以使用转化工具转化成png图片,首先运行下面代码会生成X.dot文件。然后我们需要下载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){

        }
    }
}

image-20211228111241967

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));
    }
}

image-20211228111647854

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));
    }
}

image-20211228111817441


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

image-20211228143811027

packageDeclaration

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

image-20211228144236650

举例说明

import java

from Class c
select c.getQualifiedName()

image-20211228145616981


imports

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

image-20211228145720020

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

import java

from ImportType i, Class c
where c.getPackage().getName() = "org.apache.commons.lang3.compare"
and i.getImportedType() = c
select i

image-20211228152327119

image-20211228152318395


Type

image-20211228152811903

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

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

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


总结

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

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

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


Update

为了更好的分析AST和CFG,本人写了一款工具。工具官方网站静态程序分析工具 主要生成方法的CFG和.java文件的AST,使用教程也在网站的。是一款开源工具,欢迎大家使用,提交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