• CodeQL分析python代码7使用 API 图


    API 图是一个用于引用外部库中定义的函数,类和方法的统一接口

    关于本文

    本文介绍如何使用API图来引用python第三方库代码中定义的类和函数。在定义例如flask的用户输入这种外部输入流等内容时,我们可以使用API图来更方便地引用外部库函数。

    模块导入

    API图中最常见的入口点是导入外部模块的modulepackage。我们可以使用模块semmle.python.ApiGraphs中定义的方法API::moduleImport访问与re库对应的API图节点,如下

    import python
    import semmle.python.ApiGraphs
    
    select API::moduleImport("re")
    

    该查询会显示与我们所输入模块(这里是re)对应的API图节点。该节点表示re模块是否被导入这件事,并不是程序中发生导入的某一个位置,同时每个项目最多会有一个结果。

    当然这不是我们想要的,我们往往想要获得某一个模块在程序中调用的具体的位置,这时候我们可以使用getAUse()方法,查询对于re模块的所有引用

    import python
    import semmle.python.ApiGraphs
    
    select API::moduleImport("re").getAUse()
    

    需要注意的是,getAUse()方法考虑了局部数据流,因此my_re_compile在以下代码段中被正确识别为对re.compile函数的引用

    from re import compile as re_compile
    
    my_re_compile = re_compile
    
    r = my_re_compile(".*")
    

    如果我们只需要立即使用而不考虑局部数据流,可以使用getAnImmediateUse()方法

    需要注意的是,传入的模块名称不得包含任何点。所以如果我们想要导入flask.views的时候,如果使用API::moduleImport("flask.views"),那么结果往往是错误的。这时我们应该分解为views对API图节点flask成员的访问,这也是马上要介绍的内容

    访问属性

    给定API图中的一个节点,我们可以使用getMember方法访问其属性,比如对上面上面的代码来说,我们要找到re.compile的引用

    import python
    import semmle.python.ApiGraphs
    
    select API::moduleImport("re").getMember("compile").getAUse()
    

    除了getMember()方法外,我们还可以使用getUnknownMember()方法查找对静态名称未知的API组件的引用。我们也可以使用getAMember()访问所有成员,包括已知成员和未知成员

    调用和类实例化

    要跟踪外部库中定义的类的示例,或调用外部定义函数的结果,我们可以使用getReturn()方法,下面我们查找所有使用re.compile()作为返回值的地方

    import python
    import semmle.python.ApiGraphs
    
    select API::moduleImport("re").getMember("compile").getReturn().getAUse()
    

    需要注意的是,查询结果包括了所有对re.compile的使用,包括可通过局部数据流访问的那些。要获得对re.compile的调用,我们可以使用getAnImmediateUse()而不是getAUse()。更好的一种方式是使用getACall(),这样就可以避免getReturn后面跟着getAnImmediateUse()

    另外,API图不区分类实例化和函数调用,对它而言两者都只是调用API图节点的地方

    子类

    对于很多库来说,主要的使用方式是扩展一个或多个库,我们想要在API图中跟踪这一点,可以使用getASubclass()方法获取与该节点的所有直接子类对应的API图节点。要查找所有子类,只需要重复使用*+应用在方法上,例如getASubclass*

    flask.views.View中有一个预定义的子类MethodView,要查找所有的子类View,我们需要显示包含MethodView子类

    import python
    import semmle.python.ApiGraphs
    
    API::Node viewClass() {
      result =
        API::moduleImport("flask").getMember("views").getMember(["View", "MethodView"]).getASubclass*()
    }
    
    select viewClass().getAUse()
    

    内置函数和类

    我们可以使用API::builtin方法访问内置函数和类,将内置函数的名称作为参数提供

    例如,查找对内置函数open的所有调用

    import python
    import semmle.python.ApiGraphs
    
    select API::builtin("open").getACall()
    

    END

    建了一个微信的安全交流群,欢迎添加我微信备注进群,一起来聊天吹水哇,以及一个会发布安全相关内容的公众号,欢迎关注

    GIF GIF
  • 相关阅读:
    模拟
    广搜——最优方案
    动态规划——背包
    动态规划——树规
    动态规划——区间
    fill 的用法
    状态压缩dp
    超大背包问题
    lower_bound
    弹性碰撞 poj 3684
  • 原文地址:https://www.cnblogs.com/Cl0ud/p/15963825.html
Copyright © 2020-2023  润新知