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
flowbits
由兩部分組成:
- 第一部分描述將要執(zhí)行的動作案疲,
- 第二部分是flowbits的名稱虾宇。
有多個數(shù)據(jù)包屬于一個流盅抚。Suricata
將這些流保存在內(nèi)存中产镐。flowbits
可以確保在兩個不同的數(shù)據(jù)包匹配時才將生成警報。僅當(dāng)兩個數(shù)據(jù)包匹配時才會生成警報挠乳。
因此寝蹈,當(dāng)?shù)诙€數(shù)據(jù)包匹配時榆骚,Suricata
必須知道第一個數(shù)據(jù)包是否也匹配。如果數(shù)據(jù)包匹配浪读,則flowbits
會標(biāo)記流昔榴,因此當(dāng)Suricata“知道”第二個數(shù)據(jù)包也匹配時,它將生成警報碘橘。
示例:
當(dāng)你看第一條規(guī)則時互订,你會注意到如果它匹配,如果不是在規(guī)則末尾的flowbits:noalert
痘拆,它就會生成一個警報仰禽。該規(guī)則的目的是檢查userlogin
上的匹配項,并在流中進行標(biāo)記纺蛆。因此吐葵,無需生成警報。
如果沒有第一條規(guī)則桥氏,第二條規(guī)則將無效温峭。如果第一個規(guī)則匹配,flowbits
將設(shè)置流中存在的特定條件∽种В現(xiàn)在凤藏,使用第二條規(guī)則,可以檢查前一個數(shù)據(jù)包是否滿足第一個條件堕伪。如果此時第二條規(guī)則匹配揖庄,將生成警報∏反疲可以在規(guī)則中多次使用流位蹄梢,并組合不同的功能。
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種不同的動作:noalert
isset
isnotset
set
unset
toggle
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
設(shè)置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函數(shù)注冊凹蜂。
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
在流中設(shè)置條件/名稱
(如果存在)玛痊。
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
可在規(guī)則中使用汰瘫,以確保在規(guī)則匹配且條件在流中設(shè)置時生成告警。
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
反轉(zhuǎn)當(dāng)前設(shè)置擂煞。因此混弥,如果設(shè)置了條件,則將不設(shè)置條件对省,反之亦然蝗拿。
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
可用于取消設(shè)置流中的條件。
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
可在規(guī)則中使用蒿涎,以確保在規(guī)則匹配且條件未在流中設(shè)置時生成告警哀托。
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
此規(guī)則將不會生成告警。
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);
}
...
}
未完待續(xù)劳秋。仓手。。