Suricata-流关键字

tech2022-08-23  125

Thank Zhihao Tao for your hard work. The document spent countless nights and weekends, using his hard work to make it convenient for everyone. If you have any questions, please send a email to zhihao.tao@outlook.com


文章目录

1. `flowbits`1.1 `flowbits`安装1.2 `flowbits`匹配1.2.1 `flowbits: set, name`1.2.2 `flowbits: isset, name`1.2.3 `flowbits: toggle, name`1.2.4 `flowbits: unset, name`1.2.5 `flowbits: isnotset, name`1.2.6 `flowbits: noalert`

1. flowbits

flowbits由两部分组成:

第一部分描述将要执行的动作,第二部分是flowbits的名称。

有多个数据包属于一个流。Suricata将这些流保存在内存中。flowbits可以确保在两个不同的数据包匹配时才将生成警报。仅当两个数据包匹配时才会生成警报。

因此,当第二个数据包匹配时,Suricata必须知道第一个数据包是否也匹配。如果数据包匹配,则flowbits会标记流,因此当Suricata“知道”第二个数据包也匹配时,它将生成警报。

示例: 当你看第一条规则时,你会注意到如果它匹配,如果不是在规则末尾的flowbits:noalert,它就会生成一个警报。该规则的目的是检查userlogin上的匹配项,并在流中进行标记。因此,无需生成警报。

如果没有第一条规则,第二条规则将无效。如果第一个规则匹配,flowbits将设置流中存在的特定条件。现在,使用第二条规则,可以检查前一个数据包是否满足第一个条件。如果此时第二条规则匹配,将生成警报。可以在规则中多次使用流位,并组合不同的功能。

void DetectFlowbitsRegister (void) { sigmatch_table[DETECT_FLOWBITS].name = "flowbits"; sigmatch_table[DETECT_FLOWBITS].desc = "operate on flow flag"; sigmatch_table[DETECT_FLOWBITS].url = DOC_URL DOC_VERSION "/rules/flow-keywords.html#flowbits"; sigmatch_table[DETECT_FLOWBITS].Match = DetectFlowbitMatch; sigmatch_table[DETECT_FLOWBITS].Setup = DetectFlowbitSetup; sigmatch_table[DETECT_FLOWBITS].Free = DetectFlowbitFree; sigmatch_table[DETECT_FLOWBITS].RegisterTests = NULL; /* this is compatible to ip-only signatures */ sigmatch_table[DETECT_FLOWBITS].flags |= SIGMATCH_IPONLY_COMPAT; DetectSetupParseRegexes(PARSE_REGEX, &parse_regex, &parse_regex_study); }

1.1 flowbits安装

解析flowbits具有的6种不同的动作: noalertissetisnotsetsetunsettoggle int DetectFlowbitSetup (DetectEngineCtx *de_ctx, Signature *s, const char *rawstr) { DetectFlowbitsData *cd = NULL; SigMatch *sm = NULL; uint8_t fb_cmd = 0; char fb_cmd_str[16] = "", fb_name[256] = ""; if (!DetectFlowbitParse(rawstr, fb_cmd_str, sizeof(fb_cmd_str), fb_name, sizeof(fb_name))) { return -1; } if (strcmp(fb_cmd_str,"noalert") == 0) { fb_cmd = DETECT_FLOWBITS_CMD_NOALERT; } else if (strcmp(fb_cmd_str,"isset") == 0) { fb_cmd = DETECT_FLOWBITS_CMD_ISSET; } else if (strcmp(fb_cmd_str,"isnotset") == 0) { fb_cmd = DETECT_FLOWBITS_CMD_ISNOTSET; } else if (strcmp(fb_cmd_str,"set") == 0) { fb_cmd = DETECT_FLOWBITS_CMD_SET; } else if (strcmp(fb_cmd_str,"unset") == 0) { fb_cmd = DETECT_FLOWBITS_CMD_UNSET; } else if (strcmp(fb_cmd_str,"toggle") == 0) { fb_cmd = DETECT_FLOWBITS_CMD_TOGGLE; } else { SCLogError(SC_ERR_UNKNOWN_VALUE, "ERROR: flowbits action \"%s\" is not supported.", fb_cmd_str); goto error; } 对noalert设置SIG_FLAG_NOALERT选项。 switch (fb_cmd) { case DETECT_FLOWBITS_CMD_NOALERT: if (strlen(fb_name) != 0) goto error; s->flags |= SIG_FLAG_NOALERT; return 0; case DETECT_FLOWBITS_CMD_ISNOTSET: case DETECT_FLOWBITS_CMD_ISSET: case DETECT_FLOWBITS_CMD_SET: case DETECT_FLOWBITS_CMD_UNSET: case DETECT_FLOWBITS_CMD_TOGGLE: default: if (strlen(fb_name) == 0) goto error; break; } 分配flowbits id,并加入到签名的匹配条件中。 isset和isnotset加入DETECT_SM_LIST_MATCH组。set、unset及toggle加入DETECT_SM_LIST_POSTMATCH组。 ... cd = SCMalloc(sizeof(DetectFlowbitsData)); if (unlikely(cd == NULL)) goto error; cd->idx = VarNameStoreSetupAdd(fb_name, VAR_TYPE_FLOW_BIT); de_ctx->max_fb_id = MAX(cd->idx, de_ctx->max_fb_id); cd->cmd = fb_cmd; SCLogDebug("idx %" PRIu32 ", cmd %s, name %s", cd->idx, fb_cmd_str, strlen(fb_name) ? fb_name : "(none)"); /* Okay so far so good, lets get this into a SigMatch * and put it in the Signature. */ sm = SigMatchAlloc(); if (sm == NULL) goto error; sm->type = DETECT_FLOWBITS; sm->ctx = (SigMatchCtx *)cd; switch (fb_cmd) { /* case DETECT_FLOWBITS_CMD_NOALERT can't happen here */ case DETECT_FLOWBITS_CMD_ISNOTSET: case DETECT_FLOWBITS_CMD_ISSET: /* checks, so packet list */ SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_MATCH); break; case DETECT_FLOWBITS_CMD_SET: case DETECT_FLOWBITS_CMD_UNSET: case DETECT_FLOWBITS_CMD_TOGGLE: /* modifiers, only run when entire sig has matched */ SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_POSTMATCH); break; // suppress coverity warning as scan-build-7 warns w/o this. // coverity[deadcode : FALSE] default: goto error; } return 0; error: if (cd != NULL) SCFree(cd); if (sm != NULL) SCFree(sm); return -1; }

1.2 flowbits匹配

如果DETECT_SM_LIST_MATCH有匹配项,进行注册Match函数注册。 int DetectEnginePktInspectionSetup(Signature *s) { ... if (s->sm_arrays[DETECT_SM_LIST_MATCH]) { if (DetectEnginePktInspectionAppend(s, DetectEngineInspectRulePacketMatches, NULL) < 0) ... } 遍历DETECT_SM_LIST_MATCH中所有选项进行匹配。 static int DetectEngineInspectRulePacketMatches( DetectEngineThreadCtx *det_ctx, const DetectEnginePktInspectionEngine *engine, const Signature *s, Packet *p, uint8_t *_alert_flags) { ... if (sigmatch_table[smd->type].Match(det_ctx, p, s, smd->ctx) <= 0) { ... } 对不同类型的flowbits进行匹配。 int DetectFlowbitMatch (DetectEngineThreadCtx *det_ctx, Packet *p, const Signature *s, const SigMatchCtx *ctx) { const DetectFlowbitsData *fd = (const DetectFlowbitsData *)ctx; if (fd == NULL) return 0; switch (fd->cmd) { case DETECT_FLOWBITS_CMD_ISSET: return DetectFlowbitMatchIsset(p,fd); case DETECT_FLOWBITS_CMD_ISNOTSET: return DetectFlowbitMatchIsnotset(p,fd); case DETECT_FLOWBITS_CMD_SET: return DetectFlowbitMatchSet(p,fd); case DETECT_FLOWBITS_CMD_UNSET: return DetectFlowbitMatchUnset(p,fd); case DETECT_FLOWBITS_CMD_TOGGLE: return DetectFlowbitMatchToggle(p,fd); default: SCLogError(SC_ERR_UNKNOWN_VALUE, "unknown cmd %" PRIu32 "", fd->cmd); return 0; } return 0; }

1.2.1 flowbits: set, name

在流中设置条件/名称(如果存在)。

static int DetectFlowbitMatchSet (Packet *p, const DetectFlowbitsData *fd) { if (p->flow == NULL) return 0; FlowBitSet(p->flow,fd->idx); return 1; }

1.2.2 flowbits: isset, name

可在规则中使用,以确保在规则匹配且条件在流中设置时生成告警。

static int DetectFlowbitMatchIsset (Packet *p, const DetectFlowbitsData *fd) { if (p->flow == NULL) return 0; return FlowBitIsset(p->flow,fd->idx); }

1.2.3 flowbits: toggle, name

反转当前设置。因此,如果设置了条件,则将不设置条件,反之亦然。

void FlowBitToggle(Flow *f, uint32_t idx) { FlowBit *fb = FlowBitGet(f, idx); if (fb != NULL) { FlowBitRemove(f, idx); } else { FlowBitAdd(f, idx); } } static int DetectFlowbitMatchToggle (Packet *p, const DetectFlowbitsData *fd) { if (p->flow == NULL) return 0; FlowBitToggle(p->flow,fd->idx); return 1; }

1.2.4 flowbits: unset, name

可用于取消设置流中的条件。

static int DetectFlowbitMatchUnset (Packet *p, const DetectFlowbitsData *fd) { if (p->flow == NULL) return 0; FlowBitUnset(p->flow,fd->idx); return 1; }

1.2.5 flowbits: isnotset, name

可在规则中使用,以确保在规则匹配且条件未在流中设置时生成告警。

static int DetectFlowbitMatchIsnotset (Packet *p, const DetectFlowbitsData *fd) { if (p->flow == NULL) return 0; return FlowBitIsnotset(p->flow,fd->idx); }

1.2.6 flowbits: noalert

此规则将不会生成告警。

static inline void DetectRulePacketRules( ThreadVars * const tv, DetectEngineCtx * const de_ctx, DetectEngineThreadCtx * const det_ctx, Packet * const p, Flow * const pflow, const DetectRunScratchpad *scratch ) { ... if (!(sflags & SIG_FLAG_NOALERT)) { /* stateful sigs call PacketAlertAppend from DeStateDetectStartDetection */ if (!state_alert) PacketAlertAppend(det_ctx, s, p, 0, alert_flags); } else { /* apply actions even if not alerting */ DetectSignatureApplyActions(p, s, alert_flags); } ... }

未完待续。。。

最新回复(0)