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

推荐订阅源

P
Proofpoint News Feed
The Last Watchdog
The Last Watchdog
Security Latest
Security Latest
P
Privacy International News Feed
T
Threat Research - Cisco Blogs
H
Help Net Security
T
The Exploit Database - CXSecurity.com
Know Your Adversary
Know Your Adversary
博客园_首页
S
Securelist
S
Schneier on Security
G
GRAHAM CLULEY
Cisco Talos Blog
Cisco Talos Blog
V
Visual Studio Blog
博客园 - 叶小钗
C
Cybersecurity and Infrastructure Security Agency CISA
有赞技术团队
有赞技术团队
Recent Announcements
Recent Announcements
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Microsoft Azure Blog
Microsoft Azure Blog
A
About on SuperTechFans
博客园 - 三生石上(FineUI控件)
Stack Overflow Blog
Stack Overflow Blog
量子位
L
Lohrmann on Cybersecurity
Hugging Face - Blog
Hugging Face - Blog
Engineering at Meta
Engineering at Meta
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
C
CXSECURITY Database RSS Feed - CXSecurity.com
A
Arctic Wolf
P
Privacy & Cybersecurity Law Blog
Simon Willison's Weblog
Simon Willison's Weblog
S
SegmentFault 最新的问题
The Hacker News
The Hacker News
罗磊的独立博客
博客园 - 司徒正美
D
Darknet – Hacking Tools, Hacker News & Cyber Security
博客园 - 【当耐特】
Microsoft Security Blog
Microsoft Security Blog
K
Kaspersky official blog
人人都是产品经理
人人都是产品经理
博客园 - 聂微东
L
LINUX DO - 热门话题
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
V
V2EX
V
Vulnerabilities – Threatpost
AWS News Blog
AWS News Blog
小众软件
小众软件
Project Zero
Project Zero

LoRexxar's Blog | 信息技术分享

Ghost Bits,Java WAF之殇? AI.Re.(3) - AI到底变了什么?为什么突然井喷? AI.Re.(2) - OpenClaw到底为什么爆火? AI.Re.(1) - AI变革的时代来了吗? 不容错过的2025年度漏洞:React2Shell(CVE-2025-55182)分析 PHP CGI Windows平台远程代码执行漏洞(CVE-2024-4577)分析与复现 人与代码的桥梁-聊聊SAST Joern In RealWorld (3) - 致远OA A8 SSRF2RCE Joern In RealWorld (2) - Jumpserver随机数种子泄露导致账户劫持漏洞(CVE-2023-42820) 深入浅出Joern(四)不常用语法大全 Joern In RealWorld (1) - Acutators + CVE-2022-21724 深入浅出Joern(三)Joern和Neo4j常用语法大全 深入浅出Joern(一)Joern与CPG是什么? 打造自己的AIGC应用(一)入门篇 赛博偶像速成指南(三)- Midjourney 赛博偶像速成指南(二)- SD进阶篇 从0到1的ChatGPT - 进阶篇(五)- Embeddings 从0到1的ChatGPT - 进阶篇(四)- 训练自己的ChatGPT 看上去不起眼的微信机器人以及公众号爬虫 从0到1的ChatGPT - 进阶篇(三)- ChatGPT+?
深入浅出Joern(二)CPG与图数据库
LoRexxar · 2023-08-22 · via LoRexxar's Blog | 信息技术分享

在上篇文章里,我们从Joern入手大致介绍了CPG(Code Property Graph)的设计理念和简单逻辑

但实际上来说,如果想要更深入的了解Joern,CPG和图数据库是绕不开的一个话题。CPG作为一种代码属性图,就必须寻找一种图数据库作为载体,就像我们常用的数据和SQL数据库的关系一样。

旧版本的Joern使用的Gremlin,但后来的开发中换成了OverflowDB,在joern中也完全支持使用OverflowDB的查询语法

但属性图本身没有什么特异性,比较常见的比如Neo4J,OrientDB或者JanesGraph都支持CPG的表现形式。

但,在这之前,我们首先需要知道,为什么是图?

为什么是图?

在上篇文章中,我在讲了CPG的设计思路时曾经提到过一些相关的内容。

如果说CFG(control flow graphs)相比AST来说最大的特点是带有明确数据流向的流向,在数据流分析可能更有优势。

那么CPG相比CFG来说有一个很大的特点就是信息量大,而图最大的特点也在于,就是可以容纳信息量巨大的内容

假设我们有这样一段代码

1
2
3
4
5
a = new A()
b = a.b
c.a = b.a
d.a = c
c.b = d.c

这里简单的几行代码,其实展示了相当复杂的依赖链,abcd几个变量中有着复杂的互相指向关系,如果用文字来表示abcd之间的关系我们可能需要拆分很多部分。

1
2
3
4
a -> A()
b -> A().b
c.a -> A().b.a
c.b -> ....

我甚至很难用文字的方式表达出他们之间的关系,而图在这样的场景下就变得很有优势。

img

当然这只是一个粗浅的例子,但已经很明显的能感觉出来图和文字之间的差距了,图关系可以很轻松的表达出文字很难表达出来的信息量。

Joern与图

Joern用了CPG来储存代码的所有节点关系和属性数据,由于CPG的信息量大,所以Joern甚至提供了官方的生成AST、CFG等其他结构的接口,对于C/C++甚至支持多种自定义的结构。

  • Abstract Syntax Trees (AST)
  • Control Flow Graphs (CFG)
  • Control Dependence Graphs (CDG)
  • Data Dependence Graphs (DDG)
  • Program Dependence graphs (PDG)
  • Code Property Graphs (CPG14)
  • Entire graph, i.e. convert to a different graph format (ALL)

在Joern的命令行你可以直接使用相应的命令生成对应的格式

1
2
3
4
cpg.method($name).dotAst.l // output AST in dot format
cpg.method($name).dotCfg.l // output CFG in dot format
...
cpg.method($name).dotCpg14.l // output CPG'14 in dot format

img

有个很有意思的是,如果你的电脑装了Graphviz,Joern还可以调用Graphviz来绘图,虽然生成的图很难看。

安装Graphviz之后我们可以通过命令来绘图

1
2
3
4
cpg.method($name).plotDotAst // plot AST
cpg.method($name).plotDotCfg // plot CFG
...
cpg.method($name).plotDotCpg14 // plot CPG'14

img

说实话,不太实用,但是很方便

Neo4J

相比Graphviz这种仅仅用来临时展示图的应用来说,Neo4J则是标准而且非常成熟的图数据库,不但性能强,而且还实用。

你可以在官网下载免费的neo4j,其中包括服务端和客户端版本,服务端版本启动后会默认跑到7474端口上。

Neo4j使用的查询语言叫做Cypher,这是一种声明式的图查询语言,我个人觉得Cypher其实算是比较反人类的一种语言,具体的语法可以看对应的文档。

简单来讲Cypher中对应SQL的语句关系有几个比较特别的,首先就是MATCH和where。

1
2
3
4

select Person from user where born = 'beijing'

MATCH (a:Person)-[:BORN]->(b:Location {city:'beijing'}) RETURN a,b

MATCH和where在两种查询语句中是类似的功能,其中的区别就是MATCH匹配的是图中节点之间的关系。Cypher语法比较强调节点之间的关系,比如-就是无方向关系,->就是有方向关系。

1
2
3
4
5
6
match 
(node)-[relationship]->(node)
where
(node | relationship)
return
(node | relationship)

其他的比如创建节点、删除节点、创建关系、搜索匹配的节点以及关系等等就不赘述了,算是比较符合理解的语言逻辑。

而相对于普通的数据库来说,图数据库有着可能是一种优势的特性,就是可以直接通过Neo4j的浏览器直接操作图内容以及结构。

img

直接用鼠标点击各个节点查看对应的属性以及它们之间的关系,并且可以直接拖动他们。

img

点击节点下面的按钮,可以直接查看到节点连接到的其他节点,很方便也很直观。

Joern与Neo4J

前面说了,Joern使用了自己做的OverflowDBl来作为图数据库存储CPG,但CPG本身没有什么特异性,也就意味着他可以在任意一种图数据库上导入。

而Joern本身是自带了这个功能的,就是joern-export。它支持你导出Joern的CPG到neo4j , graphml, graphson 和 graphviz dot。

1
2
3
4
./joern-export --repr=all --format=neo4jcsv
./joern-export --repr=all --format=graphml
./joern-export --repr=all --format=graphson
./joern-export --repr=all --format=dot

要使用joern-export导出数据的话,需要指定CPG的位置,这个东西会存在Joern目录下的workspace当中,并且需要指定output,默认是./out。

img

img

img

然后我们可以想办法把这些csv文件导入到Neo4j当中。当然你可以用一些自己的方式导入,但joern的这个图还挺麻烦的,主要是neo4j导入复杂结构数据需要指定好各种csv文件的关联。

但joern当然也给出了导入的办法,在生成文件的时候会给出一个导入命令的范例,照着范例就可以搞定了。

img

首先joern导入数据是有限制的,只能导入import目录下的文件,这个import文件一般会在对应链接的server目录下面,如果你使用的是neo4j的desltop浏览器,那么你可以直接打开对应的import目录,并把文件复制过去。

img

img

除了文件以外,还有就是这个/bin/cypher-shell的位置,这个脚本就在对应链接目录的bin下

img

然后构造对应的find命令生成执行导入即可,其实它的原理也比较简单,就是依次执行*_cypher.csv文件中的命令,然后导入header和data。

img

最终导入的数据就是这样的

img

用cypher在Neo4J上查询漏洞

当我们把CPG导入到Neo4J上之后,理论上来说我们可以用cypher来完成我们在Joern中做的所有工作。

这里还是拿上篇文章中用到的RCE代码来举例子。

img

对应Joern的语句为

1
2
3
def source = cpg.method.where(_.annotation.name(".*Mapping")).parameter

def sink = cpg.call.name("exec")

首先匹配注解节点满足.*Mapping的

1
MATCH (n:ANNOTATION) where n.NAME=~".*Mapping" RETURN n LIMIT 25

img

然后找这些对应节点关联的方法

1
MATCH (m:METHOD)-[:AST]->(n:ANNOTATION) where n.NAME=~".*Mapping" RETURN n LIMIT 25

img

然后找一下对应调用exec方法的节点

1
MATCH (n:CALL) where n.NAME="exec" RETURN n LIMIT 25

img

然后我们把两个节点连接起来,并查找最短路径,这里的[*..10]表示最长不超过10个关系

1
MATCH (p1:METHOD)-[:AST]->(n:ANNOTATION),(p2:CALL),p=shortestpath((p1)-[*..10]-(p2)) where n.NAME=~".*Mapping" and p2.NAME="exec" RETURN p LIMIT 25

img

这里范例算是比较简单的,所以用这个还算比较简单的语句就可以查询到结果,正好对应漏洞利用链。