发布于2025年12月5日12月5日 # V2版本\r \r ## POC 格式\r \r 基本的POC 如下:\r \r ```yaml\r name: poc-yaml-example-com\r # 脚本部分\r Transport: http\r 规则:\r r1:\r 请求:\r method: GET\r 路径: \'/\'\r 表达式: |\r response.status==200 response.body.bcontains(b'示例域')\r 表达式:\r r1()\r #信息部分\r 详情:\r 作者: 姓名(链接)\r links: \r - http://example.com\r ````\r \r 整个POC大致可以分为3部分:\r \r - 名称:脚本名称,字符串类型\r - 脚本部分:主要逻辑控制部分,控制脚本的运行过程\r - 信息部分:主要用于声明脚本的一些信息,包括输出内容\r \r 接下来介绍各部分的格式和内容。 \r \r ### 脚本部分\r \r 该部分包含4部分,分别是:\r \r -运输\r - 全局变量定义(设置)\r - 规则描述(规则)\r - 正则表达式(表达式)\r \r ####运输\r \r 该字段用于指定发送数据包的协议。 `传输:字符串`\r \r 形状如:\r \r ```yaml\r Transport: http\r ````\r \r Transport 的当前值可以是以下三个之一:\r \r 1.tcp\r 2.udp\r 3.http\r \r 与v1版本相比,v2版本做出的一个重要变化是它允许发送多种数据包,不再局限于http请求,我们增加了对tcp和udp的支持。 \r \r 目前,不允许在一个脚本中发送不同传输的请求,因为通常我们的输入是稳定的协议,例如:\r \r 1.端口存活检测的结果通常会告诉你是tcp还是udp alive\r 2. 或者从显式的http请求或网站开始\r \r 如果后续有其他协议的需求,可以扩展该字段的值。 \r \r #### 全局变量定义(设置)\r \r 该字段用于定义全局变量。比如随机数、反连接平台等`set: map[string]interface{}`\r \r 形状如:\r \r ```yaml\r 设置:\r a: 1\r ````\r \r #### 全局变量有效负载\r \r 该字段用于定义多个payload,以达到发送不同payload的效果。字段结构如下\r \r 变量名/函数名|类型|描述\r ---- | ---- | ----\r `继续` | `布尔` |打完后是否继续\r `有效负载` | `地图[字符串]集` |与`set` 相同的结构和语法\r \r 形状如:\r \r ```yaml\r 有效负载:\r continue: 假\r 有效负载:\r ping:\r cmd: r\'ping test.com\'\r 卷曲:\r cmd: r\'curl test.com\'\r ````\r \r **注**:\r \r 1. 仅支持`payload`列表。目前,不考虑对文件或复杂排列和组合的支持。每个`payload`中的`key`必须严格一致\r 2. 循环payload,然后在set后面添加当前payload,形成一个新的set来执行\r \r ```yaml\r 设置:\r a: 1\r 有效负载:\r - b: a\r - b: b\r ````\r \r 实际运行结果相当于运行两次\r \r 第一遍:\r \r ```yaml\r 设置:\r a: 1\r b: a\r ````\r \r 第二次:\r \r ```yaml\r 设置:\r a: 1\r b: b\r ````\r \r #### 规则描述(规则)\r \r 该字段定义了一些命名规则。 `rules: 地图[字符串]规则`\r 形状如:\r \r ```yaml\r 规则:\r r1:\r #这里是一个http请求的例子\r 请求:\r method: GET\r 路径: \'/\'\r 表达式: |\r response.status==200 response.body.bcontains(b'示例域')\r # 与V1 版本相比新增内容\r 输出:\r 搜索: |\r r'(?P1.1.1)'.bsubmatch(response.raw)'\r version: 搜索['版本']\r ````\r \r 规则的结构可以分为3部分:\r \r - request: 构造请求相关参数\r - 表达式:确定此规则的结果\r - 输出:声明一些变量供后续使用\r \r ##### 请求\r \r 该字段应与上面提到的“transport”相对应。对应不同的传输,有不同的请求参数设置。 \r \r ###### TCP\r \r 结构如下:\r \r ```yaml\r cache: true\r content: \'请求\'\r read_timeout: \'10\'\r 连接_id: xxx\r ````\r \r - `cache: bool` 是否使用缓存请求。如果此选项为true,则如果其他脚本在探测中向同一目标发送了相同的请求,则将使用先前缓存的响应,而不是发送新的数据包\r - `content: string` 请求内容\r - `read_timeout: string` 发送请求后读取超时时间(**注意** 它实际上是一个`int`,但是为了启用变量渲染,设置为`string`)\r - `connection_id: string`连接id,相同的连接id重复使用连接(**注意**不允许为0;当`cache`为true时,可能无法发送请求,所以如果有特殊需求,请记住`cache: false`)\r \r ###### udp\r \r 结构如下:\r \r ```yaml\r cache: true\r content: \'请求\'\r read_timeout: \'10\'\r 连接_id: xxx\r ````\r \r - `cache: bool` 是否使用缓存请求。如果此选项为true,则如果其他脚本在探测中向同一目标发送了相同的请求,则将使用先前缓存的响应,而不是发送新的数据包\r - `content: string` 请求内容\r - `read_timeout: string` 发送请求后读取超时时间(**注意** 它实际上是一个`int`,但是为了启用变量渲染,设置为`string`)\r - `connection_id: string`连接id,相同的连接id重复使用连接(**注意**不允许为0;当`cache`为true时,可能无法发送请求,所以如果有特殊需求,请记住`cache: false`)\r \r ###### http\r \r 结构如下:\r \r ```yaml\r cache: true\r method: GET\r 路径: /\r headers:\r 内容类型: 应用程序/xml\r body: aaaa\r follow_redirects: true\r ````\r \r - `cache: bool` 是否使用缓存请求。如果此选项为true,则如果其他脚本在探测中向同一目标发送了相同的请求,则将使用先前缓存的响应,而不是发送新的数据包\r - `method: string` 请求方法\r - `path: string` 请求的完整Path,包括querystring等(具体参见:【HTTP PATH的使用】(guide/skill/path))\r 1. 如果路径以`/`开头,则取dir路径并连接\r 2. 如果路径以`^`开头,uri将直接取路径\r - `headers: map[string]string` 请求HTTP 标头,Rule 中指定的值将被覆盖到原始数据包的HTTP 标头\r - `body: string` 请求正文\r - `follow_redirects: bool` 是否允许follow 300跳转\r \r ##### 表达式\r \r 该字段定义了该规则最终执行的结果。 `表达式: 字符串`\r \r 形状如:\r \r ```yaml\r 表达式: |\r response.status==200 response.body.bcontains(b'示例域')\r ````\r \r 表达式的具体书写方式请参见[表达式书写](#表达式书写)\r \r ##### 输出\r \r 该字段定义了该规则运行后的一些变量。该字段中定义的变量将被添加到全局变量中,类似于`set`。 `output: []字符串`\r \r 形状如:\r \r ```yaml\r 输出:\r 搜索: |\r r'(?P1.1.1)'.bsubmatch(response.raw)'\r version: 搜索['版本']\r ````\r \r #### 表达式\r \r 该字段定义了整个脚本最终执行的结果。 `表达式: 字符串`\r \r 形状如:\r \r ```yaml\r 表达式: |\r r1() || r2()\r ````\r \r 表达式具体如何书写请参见[表达式书写](#表达式书写),尤其要注意脚本表达式书写部分\r \r ### 信息部分(详细)\r \r 该字段用于定义一些脚本相关的信息。所有内容都是可选的。 \r \r ```yaml\r 详情:\r 作者: 姓名(链接)\r links: \r - http://example.com\r # 指纹信息\r 指纹:\r 信息:\r - id: \'长汀指纹数据库id\'\r name: \'SSH\'\r version: {{版本}}\r type: \'system_bin\'\r 信心: 70\r 主机信息:\r 主机名: \'测试\'\r # 漏洞信息\r 漏洞:\r id: \'长汀漏洞库id\'\r match: \'证明漏洞存在的信息\'\r #其他字段\r cve: \'CVE-2020-1234\'\r # 其他未定义字段\r 摘要: \'测试\'\r ````\r \r 目前主要定义了几个部分:\r \r **注意**:支持变量渲染,形式为`{{variable}}`,其中变量是set或rule输出中定义的变量\r \r - `author: string` 作者\r - `links: []string` 相关链接\r - `fingerprint` 指纹信息\r - `infos: []Info` 指纹信息\r - `id: string` 长汀指纹库ID\r - `name: string` 名称\r - `version: string` 版本号\r - `type: string` 指纹类型,可选值如下:`operating_system`、`hardware`、`system_bin`、`web_application`、`dependency`\r - `confidence: int` 值范围(1-100)\r - `host_info` 主机信息\r - `hostname: string` 主机名\r - `vulnerability`漏洞信息\r - `id: string` 长汀漏洞库ID\r - `match: string` 证明漏洞存在的一些信息\r - 额外字段\r - 额外字段\r \r ## 表达式书写\r \r 正如spring使用SpEL表达式,struts2使用OGNL表达式,xray使用编译语言Golang一样,所以为了动态执行一些规则,我们使用通用表达式语言(CEL)表达式。 \r \r 有关CEL表达项目的更多信息,请参考该项目。如果您只是编写一些简单的规则,请阅读此文档。 \r \r 让我们从上面示例中的表达式开始:\r \r ````\r response.status==200 response.body.bcontains(b'示例域')\r ````\r \r CEL 表达式很容易理解,并且与Python 表达式非常相似。上述表达式的含义是:**返回的包状态等于200,body包含内容“示例域”**。 \r \r 表达式上下文还包含一些常用的函数。例如上面的`bcontains`用于匹配bytes是否包含。同样,如果要匹配包含字符串,可以使用`contains`,如:\r \r ````\r response.content_type.contains(\'json\')\r ````\r \r 值得注意的是,与python类似,CEL中的字符串可以有转义符和前缀,如:(详细参见:[头痛转义](guide/skill/escape))\r \r - `'\\r\ '' 表示换行符\r - `r'\\r\ '' 并不表示换行,仅表示这4 个字符。编写正则表达式时有意义。 \r - `b'test'` 是字节流(bytes),在golang中是`[]byte`\r \r 用一些简单的例子来解释我们可能使用的大多数表达式:\r \r - `response.body.bcontains(b'test')`\r - 返回的包体包含test,因为body是bytes类型变量,所以我们需要使用bcontains方法,其参数也是bytes\r - `response.body.bcontains(bytes(r1+'某个值'+r2))`\r - r1和r2是randomLowercase的变量,其中body的内容是动态确定的\r - `response.content_type.contains('application/octet-stream') response.body.bcontains(b'\\x00\\x01\\x02')`\r - 返回包的content-type包含application/octet-stream,body包含二进制字符串0x000102\r - `response.content_type.contains('zip') r'^PK\\x03\\x04'.bmatches(response.body)`\r - 该规则用于判断返回的内容是否为zip文件。它必须满足以下条件:content-type包含关键字\'zip\',并且body匹配正则r'^PK\\x03\\x04'(这是zip文件头)。因为startsWith方法只支持字符串判断,所以这里不使用。 \r - `response.status=300 response.status 400`\r - 返回包的状态码在300~400之间\r - `(response.status=500 response.status !=502) || r' - 返回的包状态码大于等于500且不等于502,或者Body包含表单\r - `response.headers['location']==\'https://www.example.com\'`\r - 标头中的“位置”等于指定值。如果`Location` 不存在,则表达式返回false\r -response.headers 中的“docker-distribution-api-version”response.headers['docker-distribution-api-version'].contains('registry/2.0')`\r - 标头包含“docker-distribution-api-version”,值包含指定的字符串。如果不勾选“in”,后续的包含将导致错误。 \r - `response.body.bcontains(bytes(response.url.path))`\r - 正文中包含url 的路径\r \r 表达式表达式必须返回bool 类型的结果。 \r \r 对于规则结构中的表达式,此结果用作整个规则调用的值\r \r 对于脚本级表达式,该结果作为最终脚本是否匹配成功的值。通常脚本级表达式是规则结果的组合。例如,一个脚本包含4 个规则“r1”、“r2”、“r3”、“r4”。作为脚本级表达式,其全局变量将定义4 个函数“r1”、“r2”、“r3”、“r4”。调用这4个函数就可以得到其对应规则的结果。 \r \r ```yaml\r 表达式: r1() r2() r3() r4()\r ````\r \r **注意**:\r \r 与V1版本相比,规则的运行方式发生了较大变化。假设我们有4 个规则`r1`, `r2`, `r3`, `r4`\r \r 最初,V1版本添加了“rules: []Rule”来定义规则及其执行顺序。逻辑是顺序执行规则,当`r1`,`r2`,`r3`,`r4`都为true时,脚本执行成功\r \r ```yaml\r 规则: \r r1:\r r2:\r r3:\r r4:\r ````\r \r 然后添加`group: map[string][]Rule`来扩展规则的执行方法。支持当r1和r2同时为true或者r3和r4同时为true时,脚本执行成功\r \r ```yaml\r 组:\r g1: [r1, r2]\r g2: [r3, r4]\r ````\r \r 在V2版本下,我们使用表达式来组织规则的执行逻辑。 \r \r 对于方法1,对应的形式为:\r \r ```yaml\r 规则: \r r1:\r r2:\r r3:\r r4:\r 表达式: r1() r2() r3() r4()\r ````\r \r 对于方法2,对应的形式为:\r \r ```yaml\r 规则: \r r1:\r r2:\r r3:\r r4:\r 表达式: (r1() r2()) || (r3() r4())\r ````\r \r 我们甚至可以支持:\r \r ```yaml\r 规则: \r r1:\r r2:\r r3:\r r4:\r 表达式: (r1() || r2() || r3()) r4()\r ````\r \r 这里有几点需要说明一下:\r \r 1.规则的执行顺序按照逻辑表达式
创建帐户或登录后发表意见