tabby 原理学习

文章发布时间:

最后更新时间:

写在前面

开始学习工具化利用了(虽然还有好多漏洞没复现hhh),但是项目要继续推进了,先从工具层面开始分析吧。里面总结一些自己需要学习的基础知识

基本使用

  • 查询所有类方法

    1
    2
    match (source:Method) return *
    match (source:Method {NAME:"exec"}) return *
  • Alias边含义,隐含继承、接口实现关系

    image-20221214212903038

    image-20221214213142916

image-20221214213127089

由于Alias的无指向性,从任何一个结点都可以得到完整的Alias函数别名图

  • Neo4j路径检索插件 apoc.algo.allSimplePaths

    1
    apoc.algo.allSimplePaths(startNode :: NODE?, endNode :: NODE?, relationshipTypesAndDirections :: STRING?, maxNodes :: INTEGER?) :: (path :: PATH?)
    • startNode - 开始节点,也就是Source
    • endNode - 结束节点,也就是Sink
    • relationshipTypesAndDirections - Neo4j的关系边,类型是字符串,可以设置为多个关系。查询时会按照这个关系进行路径图的查找
    • maxNodes - 搜索的最大节点数,也就是路径深度。注意千万不能设太大,尤其是节点很多的时候。

    同时还有一个输出参数:

    • path - 没看到文档有特别说明233,看到文档中给的都是YIELD path, weight
  • 对路径上的结点作限制

    1
    where any(n in nodes(path) where n.NAME="equals" and n.CLASSNAME="java.net.URL")
  • 结合插件进行路径搜索 模板

    1
    2
    3
    4
    5
    6
    // CC3
    match (source:Method) where source.NAME="readObject"
    match (m1:Method) where m1.NAME="newInstance" and m1.CLASSNAME="java.lang.reflect.Constructor"
    call apoc.algo.allSimplePaths(m1, source, "<CALL|ALIAS", 5) yield path
    where any(n in nodes(path) where n.NAME="transform")
    return * limit 100

    image-20221214232233967

    sink规则

    image-20221214232443847

  • 探究底层可以搜索到哪里

    首先Runtime.exec的完整调用链如下

    1
    2
    3
    4
    5
    6
    7
    8
    create:-1, ProcessImpl (java.lang)
    <init>:386, ProcessImpl (java.lang)
    start:137, ProcessImpl (java.lang)
    start:1029, ProcessBuilder (java.lang)
    exec:620, Runtime (java.lang)
    exec:450, Runtime (java.lang)
    exec:347, Runtime (java.lang)
    main:3, RuntimeTest

    增加一点类的限制

    1
    2
    3
    4
    match (source:Method {NAME:"exec"}) where source.CLASSNAME = "java.lang.Runtime"
    match (sink:Method {NAME:"start"}) where sink.CLASSNAME = "java.lang.ProcessBuilder"
    call apoc.algo.allSimplePaths(sink, source, "<CALL|ALIAS", 10) yield path
    return * limit 20

    这里到没有搜到,而且明显搜索时间很短,类似和缓存的效果一样。目前的想法是它这里的污点分析算法由于依赖于先验知识库中的sink点规则,所以相当于这里的查询规则没有匹配到任何路径(因为两个结点都是sink点)

    ProcessImpl.<init>((UNIXProcess.java:386))处调用了native方法

    image-20221214220606010

    规则库中设置的sink点的深度

    image-20221214220240296

    但实际上是soot是导入了native方法的,我认为这里应该是由于污点分析时source点和sink点未能匹配到导致的

    image-20221214221321320

    似乎已经被设置为sink点的类就无法继续往下查

    1
    match (m1:Method {NAME:"exec", CLASSNAME:"java.lang.Runtime"})-[:CALL]->(m2:Method) return * 

    image-20221214234506607

    image-20221214234715967

  • 限制

    • 依赖于sink点和source点的先验知识库
    • 不支持动态代理
    • 由于路径过深查询条数过多都会在一定程度上影响分析也比较吃电脑性能
优化

image-20221217130815444

  • TabbyVariable 代表方法中局部变量的类型

image-20221217125615943

其中TabbyValue类型的对象内部包裹着TabbyStatus类型的对象,保存了污点参数的信息。内部使用时通过下面的方法来获取

image-20221217125810123

架构

image-20221217130443917

流程

image-20221217130404409

核心

image-20221217130540232

函数别名图

image-20221217131642517

自动化方式

image-20221217130619854

参考链接

[1] https://tttang.com/archive/1696/

[2] https://cangqingzhe.github.io/2022/05/03/Tabby%E6%8C%96%E6%8E%98%E5%88%A9%E7%94%A8%E9%93%BE/