指纹编写

ExpDepos 指纹库使用 YAML 语言编写,我们提供了两种方式来编写指纹。第一种是直接使用 YAML 语法在 ExpDepos/modules/fingerprints 下创建指纹库文件。第二种是在模块开发时候使用 Python 字典数据结构编写指纹,编写好的指纹将自动转换成 YAML 格式存放。

备注

要编写指纹请 点击此处 下载对应指纹模板,推荐在模块开发过程中为其编写对应指纹。

在模块中编写

要在模块中编写指纹,需要继承模块基类的 _fingers 函数,在该函数中返回一个指纹信息字典,如下代码所示:

def _fingers(self):
    """
    当前模块指纹定义

    :return: dict
    """
    fingerprint = {
        "name": self.AppName,                           # 漏洞应用名作为指纹名称
        "author": self.Author,                          # 作者
        "version": "1.0",                               # 版本号
        "type": FINGERPRINT.FP_TYPE.WEBAPP,             # 指纹类型 详情请参考指纹类型表
        "logic": "or",                                  # 匹配逻辑 默认为 or
        "description": "指纹描述信息",                    # 描述信息
        "website": "https://www.tongda2000.com/",
        "filters": {                                    # 过滤属性,用于从操作系统平台、中间件、和脚本语言3个维度进行过滤
            "platform": ['windows', 'Unix'],
            "middleware": ['apache', 'nginx'],
            "language": ['PHP']
        },
        "matches": [{"url": "/tongda.ico?r={randstr()}", "hash": -759108386, "certainty": 100, "status": 200},
                    {"search": "headers", "keyword": "X-Powered-By: PHP/7.2.24-0ubuntu0.18.04.8"},
                    {"search": "headers[set-cookie]", "regex": "(aa)", "offset": 1, "version": "2.2",
                     "aim": "version"},
                    {"name": "matchName", "keyword": "test <||> referer"},
                    {"status": 200}],
        "sets": {                                       # 主动式匹配的一些HTTP Request设置
            "headers": {"testHeader": "testHeader{randstr(10)}"},
            "cookies": {"cname": "cValue{randstr(5,true)}"},
            "params": {"test": "bbbb"},
            "data": ""
        }
    }
    return fingerprint

指纹合并

在模块中编写指纹时候为避免重复,可与指纹库中现有指纹进行绑定或者合并。如果需要将当前 exploit 模块与现有指纹绑定,在 _fingers() 函数中只需返回现有指纹的文件名(不含 .yaml)即可。若在绑定现有指纹的同时需要对原指纹进行更新,则在 _fingers() 函数中返回一个由文件名及指纹信息组成的 Tuple 类型数据即可,如下所示:

def _fingers(self) -> [dict, str, tuple]:
    already_exists_fp = "trs-ids"
    fingerprint = {
        "matches": [{"search": "headers", "keyword": "trsidsssosessionid"}],
    }
    return already_exists_fp, fingerprint

以上代码将模块与 trs-ids.yaml 指纹进行绑定,并将原指纹的 matches 与提供的 matches 进行合并。

小技巧

在需要更新原指纹的时候只需提供需要更新的键值即可,若提供的键值为指纹基本属性,则替换原指纹键值,若提供键值为 matchessetsfilters 则与原值进行合并。

使用向导编写

使用内置的指纹添加向导模块 addfps 可以以向导的方式添加指纹到指纹库中,运行指纹添加向导请使用以下命令:

python3 cli.py -M addfps

向导会依次要求输入指纹基本信息,针对有默认值的选项可直接回车选择。如果输入的指纹信息在指纹库中有相似的指纹,则会提示用户选择是否编辑已存在的指纹还是继续添加新的指纹。基本信息填写完成之后会进入 Shell 模式,在该模式下可以使用命令进一步完成指纹属性,命令列表如下所示:

  • add 添加 matchesfilterssets 指纹属性

  • edit 编辑 matchesfilterssets 指纹属性

  • set 设置指纹基本属性

  • show 显示当前指纹信息

  • save 保存指纹到文件

  • exit 退出shell模式

备注

  • 若编辑已有但指纹是从 exploit 模块注册,则编辑不会生效,从 exploit 模块注册的指纹需要在 exploit 模块中进行修改。

  • Shell 模式下可以使用 Table 键进行命令补全。

add添加属性

使用 add [matches、filters、sets] 命令进入添加 matchesfilterssets 指纹属性向导,依次输入指纹属性相关属性及值即可完成属性添加。

edit编辑属性

使用 edit [matches、filters、sets] [index] 命令进入编辑 matchesfilterssets 指纹属性向导,可选参数 index 为需要编辑到属性值索引。支持 intstr 类型值,当编辑指定匹配项(matches)的时候需要传入对应匹配项值的下标。当编辑过滤器属性(filters)或请求配置(sets)时候则需要传入需要编辑属性的键名, 例如 edit sets headers 将进入编辑指纹 sets 属性的 headers 向导。若不提供 index 索引值则会输出列表让用户选择需要编辑的项目。

set设置属性

使用 set [option] option_value 命令可设置指纹除 matchesfilterssets 外的其他基本信息。

show查看指纹

使用 show 命令可以查看当前指纹信息, 一遍在编写过程中查看指纹设置是否正确, 该信息将已字典形式打印。

save保存指纹

使用 save 命令将指纹信息注册并保存到指纹库,在保存过程中会询问是否将指纹绑定到指定到 exploit 模块,若需要绑定可以输入 exploit 模块名称或者别名进行绑定,否则可直接回车保存。

exit退出

使用 exit 命令退出指纹编写向导模块,在退出之前若指纹已修改但未保存,则会询问用户是否强制退出或先调用保存函数后再退出。

指纹属性

一个指纹由基本信息( nameauthor 等)、过滤属性( filters )、匹配项( matches )、设置( sets )组成,以下为全部属性释义:

  • name 指纹名称,在模块中可以使用漏洞应用作为指纹名称。

  • author 指纹作者信息(值可选列表或字符串类型)。

  • version 指纹版本信息。

  • type 指纹分类(值可选列表或字符串类型),详情参看 指纹分类 定义。

  • logic 指纹匹配项之间的匹配逻辑,可选 orand

  • description 指纹描述信息。

  • website 指纹应用官网。

  • filters 指纹过滤属性,用于从操作系统平台、中间件、和脚本语言3个维度进行过滤。

  • matches 指纹匹配项,每一个匹配项为指纹匹配属性字典组成。

  • sets 主动式匹配的一些HTTP请求设置,可设置 headerscookiesparamsdata

  • file_path 指定指纹文件保存路径(相对 ExpDepos/modules/fingerprints/ 目录下)

  • regByExp 指纹绑定到的 exploit 模块(在 exploit 模块中定义的指纹会自动设置该属性)

matches

matches 为多个匹配项组成的列表,每一个匹配项是由不同的匹配属性组成的匹配规则。以下为所有匹配属性释义:

  • name 匹配项名称,该属性为可选属性。

  • url 主动式匹配的标识,如果设置该属性则表示该匹配项需要主动请求该 url 进行指纹识别,没有该属性则为一个被动式匹配项。

  • search 被动式匹配的标识,该属性值标识了被动式匹配区域,默认为 text。可选区域有 headers (HTTP响应头)、text (HTTP响应体),headers 区域亦可设置具体属性,例如 headers[set-cookie]

  • keyword 关键词匹配,该属性标识该匹配项使用关键词进行匹配。

  • regex 正则匹配,该属性标识该匹配项使用正则表达式进行匹配,值为一个正则表达式。

  • offset 正则匹配结果索引值,该属性搭配 regex 使用,如果匹配成功则返回 match 对象 group 属性的对应索引值,否则将返回整个 match 对象。

  • hash mmh3 值匹配,该属性标识该匹配项匹配响应体的 mmh3 值。

  • md5 md5 值匹配,该属性标识该匹配项匹配响应体的 md5 值。

  • status HTTP状态码匹配,该属性标识该匹配项匹配HTTP状态码,针对主动式匹配项,默认会设置请求的URL状态码为 200

  • aim 变量设置,该属性用于设置匹配成功后存储值的变量名称,该名称在匹配结果字典中以键值存在。

  • certainty 匹配准确度百分比,该属性标识该匹配项匹配成功后指纹识别的准确度。

  • redirects 主动式匹配在请求URL时是否允许重定向(默认: False)。

多个匹配属性

针对每一个匹配项可以同时设置多个匹配属性,比如一个主动匹配项在请求特定URL的同时需要满足状态码为 200 ,或是一个被动模式匹配属性在满足 hash 值的同时需要满足 md5 值。设有多个匹配属性的匹配项只有在全部匹配属性均满足的条件下才算匹配成功。

"matches": [{"url": "/tongda.ico}", "hash": -759108386, "certainty": 100, "status": 200},
            {"hash": -759108386, "md5": 1205af91d6b1638c23de1132ae0c7e0b}
            ]

多个匹配值

针对 hashmd5 方式的匹配值还支持列表类型,可以对多个值进行匹配验证,只要值存在于列表中均为匹配成功。这对一个匹配项存在多个可能值的情况比较适用,如下所示:

"matches": [{"url": "/tongda.ico}", "hash": [-759108386, -75326295], "status": 200},]

keyword匹配逻辑

针对 keyword 关键词匹配属性可以使用 <||> 或是 <&&> 符号分割多个关键词,用于表达简单的关键词匹配逻辑,前者为逻辑 后者为逻辑 <||> 标识所分割的关键词只要有一个匹配成功则该匹配项即算匹配成功, <&&> 则需要所有关键词匹配成功才算匹配成功。

"matches": [{"name": "matchName", "keyword": "test <||> referer"}]

使用随机字符

要在主动式匹配的URL属性或是HTTP请求属性的任意位置使用随机字符可以使用 {randstr()} 标识,该标识将调用 randstr() 函数作为随机字符生成器。该函数可以接受 lengthnumber 参数,前者用于设置随机字符串长度,后者用于表示是否只用数字。

# 生成默认5位随机数字加大小写字母的随机字符
{"url": "/tongda.ico?r={randstr()}", "hash": -759108386, "certainty": 100, "status": 200}
# 生成10位纯数字随机字符
{"url": "/tongda.ico?r={randstr(10, true)}", "hash": -759108386, "certainty": 100, "status": 200}

randstr() 函数定义如下:

ExpDepos.libs.core.base.Fingerprint.randstr(length: int = 5, number: bool = False, letter: bool = False) str[源代码]

随机字符生成器

参数
  • length -- 生成长度

  • number -- 是否纯数字

@param letter

是否纯字母

返回

str

sets

sets 属性用于设置主动式匹配项HTTP请求属性,配置值为一个字典类型,可配置属性如下所示:

  • headers HTTP 请求头设置。

  • cookies HTTP 请求头的cookie值。

  • params HTTP GET 请求参数值。

  • data HTTP POST 请求参数值

"sets": {
            "headers": {"testHeader": "testHeader{randstr(10)}"},
            "cookies": {"cname": "cValue{randstr(5,true)}"},
            "params": {"test": "bbbb"},
            "data": ""
        }

filters

指纹过滤属性 filters 为在批量指纹识别中过滤不必要的指纹信息做条件支持,filtersplatform (系统平台)、 middleware (中间件) 和 language (脚本语言)3个维度进行过滤,以下为常用过滤值列表:

备注

指纹 type 属性亦可作为过滤属性使用,在需要过滤特定类型指纹时候只需在过滤字典中添加 type 键,其值为需要过滤的指纹类型或者类型列表即可。

ENUMS.PLATFORM = ['windows', 'unix']
ENUMS.MIDDLEWARE = ['iis', 'apache', 'nginx', 'tomcat', 'weblogic', 'jboss', 'jetty', 'webshere', 'glasshfish', 'bws', 'nodejs', 'embedthis-appweb']
ENUMS.SCRIPT_LANGUAGE = ['asp', 'csharp', 'php', 'js', 'python', 'java', 'cgi']