mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 06:38:20 +00:00
Merge remote-tracking branch 'origin/topic/jsiwek/gh-779-udp-state-sig'
* origin/topic/jsiwek/gh-779-udp-state-sig: GH-779: Add "udp-state" signature condition Rename RuleConditionTCPState::TCPState enum values Rename signature parser tokens to not be TCP-specific
This commit is contained in:
commit
b73cc816e9
11 changed files with 141 additions and 28 deletions
13
CHANGES
13
CHANGES
|
@ -1,4 +1,17 @@
|
|||
|
||||
3.3.0-dev.381 | 2020-10-12 11:15:29 -0700
|
||||
|
||||
* GH-779: Add "udp-state" signature condition (Jon Siwek, Corelight)
|
||||
|
||||
It accepts "originator" or "responder" states as a way to enforce that
|
||||
the signature only matches packets in the associated direction.
|
||||
The "established" state is rejected as an error since it doesn't
|
||||
have a useful meaning like it does for the "tcp-state" condition.
|
||||
|
||||
* Rename RuleConditionTCPState::TCPState enum values (Jon Siwek, Corelight)
|
||||
|
||||
* Rename "tcp-state" signature parser tokens to not be TCP-specific (Jon Siwek, Corelight)
|
||||
|
||||
3.3.0-dev.377 | 2020-10-08 12:07:42 -0700
|
||||
|
||||
* GH-1200: ignore a maybe-uninitialized warning (Jon Siwek, Corelight)
|
||||
|
|
3
NEWS
3
NEWS
|
@ -34,6 +34,9 @@ New Functionality
|
|||
See https://docs.zeek.org/en/master/frameworks/logging.html#filter-log-records
|
||||
for more details.
|
||||
|
||||
- Added a ``udp-state`` signature condition to enforce matching against
|
||||
either "originator" or "responder" flow direction of UDP packets.
|
||||
|
||||
Changed Functionality
|
||||
---------------------
|
||||
|
||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
3.3.0-dev.377
|
||||
3.3.0-dev.381
|
||||
|
|
2
doc
2
doc
|
@ -1 +1 @@
|
|||
Subproject commit 2960bd2ee131e1c565da3e02983bbe4b719bc607
|
||||
Subproject commit fd3e22bf5efc42a572e83346031aec4493b3c803
|
|
@ -32,16 +32,16 @@ bool RuleConditionTCPState::DoMatch(Rule* rule, RuleEndpointState* state,
|
|||
|
||||
auto* ta = static_cast<analyzer::tcp::TCP_Analyzer*>(root);
|
||||
|
||||
if ( tcpstates & STATE_STATELESS )
|
||||
if ( tcpstates & RULE_STATE_STATELESS )
|
||||
return true;
|
||||
|
||||
if ( (tcpstates & STATE_ORIG) && ! state->IsOrig() )
|
||||
if ( (tcpstates & RULE_STATE_ORIG) && ! state->IsOrig() )
|
||||
return false;
|
||||
|
||||
if ( (tcpstates & STATE_RESP) && state->IsOrig() )
|
||||
if ( (tcpstates & RULE_STATE_RESP) && state->IsOrig() )
|
||||
return false;
|
||||
|
||||
if ( (tcpstates & STATE_ESTABLISHED ) &&
|
||||
if ( (tcpstates & RULE_STATE_ESTABLISHED ) &&
|
||||
! (is_established(ta->Orig()) &&
|
||||
is_established(ta->Resp())))
|
||||
return false;
|
||||
|
@ -54,6 +54,31 @@ void RuleConditionTCPState::PrintDebug()
|
|||
fprintf(stderr, " RuleConditionTCPState: 0x%x\n", tcpstates);
|
||||
}
|
||||
|
||||
bool RuleConditionUDPState::DoMatch(Rule* rule, RuleEndpointState* state,
|
||||
const u_char* data, int len)
|
||||
{
|
||||
analyzer::Analyzer* root = state->GetAnalyzer()->Conn()->GetRootAnalyzer();
|
||||
|
||||
if ( ! root || ! root->IsAnalyzer("UDP") )
|
||||
return false;
|
||||
|
||||
if ( states & RULE_STATE_STATELESS )
|
||||
return true;
|
||||
|
||||
if ( (states & RULE_STATE_ORIG) && ! state->IsOrig() )
|
||||
return false;
|
||||
|
||||
if ( (states & RULE_STATE_RESP) && state->IsOrig() )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void RuleConditionUDPState::PrintDebug()
|
||||
{
|
||||
fprintf(stderr, " RuleConditionUDPState: 0x%x\n", states);
|
||||
}
|
||||
|
||||
void RuleConditionIPOptions::PrintDebug()
|
||||
{
|
||||
fprintf(stderr, " RuleConditionIPOptions: 0x%x\n", options);
|
||||
|
|
|
@ -22,16 +22,16 @@ public:
|
|||
virtual void PrintDebug() = 0;
|
||||
};
|
||||
|
||||
enum RuleStateKind {
|
||||
RULE_STATE_ESTABLISHED = 1,
|
||||
RULE_STATE_ORIG = 2,
|
||||
RULE_STATE_RESP = 4,
|
||||
RULE_STATE_STATELESS = 8
|
||||
};
|
||||
|
||||
// Implements the "tcp-state" keyword.
|
||||
class RuleConditionTCPState : public RuleCondition {
|
||||
public:
|
||||
enum TCPState {
|
||||
STATE_ESTABLISHED = 1,
|
||||
STATE_ORIG = 2,
|
||||
STATE_RESP = 4,
|
||||
STATE_STATELESS = 8
|
||||
};
|
||||
|
||||
explicit RuleConditionTCPState(int arg_tcpstates)
|
||||
{ tcpstates = arg_tcpstates; }
|
||||
|
||||
|
@ -46,6 +46,20 @@ private:
|
|||
int tcpstates;
|
||||
};
|
||||
|
||||
// Implements the "udp-state" keyword.
|
||||
class RuleConditionUDPState : public RuleCondition {
|
||||
public:
|
||||
explicit RuleConditionUDPState(int arg_states)
|
||||
{ states = arg_states; }
|
||||
|
||||
bool DoMatch(Rule* rule, RuleEndpointState* state, const u_char* data,
|
||||
int len) override;
|
||||
|
||||
void PrintDebug() override;
|
||||
|
||||
private:
|
||||
int states;
|
||||
};
|
||||
|
||||
// Implements "ip-options".
|
||||
class RuleConditionIPOptions : public RuleCondition {
|
||||
|
|
|
@ -58,15 +58,16 @@ static uint8_t ip4_mask_to_len(uint32_t mask)
|
|||
%token TOK_SRC_IP
|
||||
%token TOK_SRC_PORT
|
||||
%token TOK_TCP_STATE
|
||||
%token TOK_UDP_STATE
|
||||
%token TOK_STRING
|
||||
%token TOK_TCP_STATE_SYM
|
||||
%token TOK_STATE_SYM
|
||||
%token TOK_ACTIVE
|
||||
%token TOK_BOOL
|
||||
%token TOK_POLICY_SYMBOL
|
||||
|
||||
%type <str> TOK_STRING TOK_IDENT TOK_POLICY_SYMBOL TOK_PATTERN pattern string
|
||||
%type <val> TOK_INT TOK_TCP_STATE_SYM TOK_IP_OPTION_SYM TOK_COMP
|
||||
%type <val> integer ipoption_list tcpstate_list opt_strength
|
||||
%type <val> TOK_INT TOK_STATE_SYM TOK_IP_OPTION_SYM TOK_COMP
|
||||
%type <val> integer ipoption_list state_list opt_strength
|
||||
%type <rule> rule
|
||||
%type <bl> TOK_BOOL opt_negate
|
||||
%type <hdr_test> hdr_expr
|
||||
|
@ -246,11 +247,19 @@ rule_attr:
|
|||
(zeek::detail::RuleHdrTest::Comp) $2, $3));
|
||||
}
|
||||
|
||||
| TOK_TCP_STATE tcpstate_list
|
||||
| TOK_TCP_STATE state_list
|
||||
{
|
||||
current_rule->AddCondition(new zeek::detail::RuleConditionTCPState($2));
|
||||
}
|
||||
|
||||
| TOK_UDP_STATE state_list
|
||||
{
|
||||
if ( $2 & zeek::detail::RULE_STATE_ESTABLISHED )
|
||||
rules_error("'established' is not a valid 'udp-state'");
|
||||
|
||||
current_rule->AddCondition(new zeek::detail::RuleConditionUDPState($2));
|
||||
}
|
||||
|
||||
| TOK_ACTIVE TOK_BOOL
|
||||
{ current_rule->SetActiveStatus($2); }
|
||||
;
|
||||
|
@ -382,10 +391,10 @@ ipoption_list:
|
|||
{ $$ = $1; }
|
||||
;
|
||||
|
||||
tcpstate_list:
|
||||
tcpstate_list ',' TOK_TCP_STATE_SYM
|
||||
state_list:
|
||||
state_list ',' TOK_STATE_SYM
|
||||
{ $$ = $1 | $3; }
|
||||
| TOK_TCP_STATE_SYM
|
||||
| TOK_STATE_SYM
|
||||
{ $$ = $1; }
|
||||
;
|
||||
|
||||
|
|
|
@ -75,23 +75,23 @@ true { rules_lval.val = true; return TOK_BOOL; }
|
|||
false { rules_lval.val = false; return TOK_BOOL; }
|
||||
|
||||
established {
|
||||
rules_lval.val = zeek::detail::RuleConditionTCPState::STATE_ESTABLISHED;
|
||||
return TOK_TCP_STATE_SYM;
|
||||
rules_lval.val = zeek::detail::RULE_STATE_ESTABLISHED;
|
||||
return TOK_STATE_SYM;
|
||||
}
|
||||
|
||||
originator {
|
||||
rules_lval.val = zeek::detail::RuleConditionTCPState::STATE_ORIG;
|
||||
return TOK_TCP_STATE_SYM;
|
||||
rules_lval.val = zeek::detail::RULE_STATE_ORIG;
|
||||
return TOK_STATE_SYM;
|
||||
}
|
||||
|
||||
responder {
|
||||
rules_lval.val = zeek::detail::RuleConditionTCPState::STATE_RESP;
|
||||
return TOK_TCP_STATE_SYM;
|
||||
rules_lval.val = zeek::detail::RULE_STATE_RESP;
|
||||
return TOK_STATE_SYM;
|
||||
}
|
||||
|
||||
stateless {
|
||||
rules_lval.val = zeek::detail::RuleConditionTCPState::STATE_STATELESS;
|
||||
return TOK_TCP_STATE_SYM;
|
||||
rules_lval.val = zeek::detail::RULE_STATE_STATELESS;
|
||||
return TOK_STATE_SYM;
|
||||
}
|
||||
|
||||
lsrr {
|
||||
|
@ -132,6 +132,7 @@ same-ip return TOK_SAME_IP;
|
|||
src-ip return TOK_SRC_IP;
|
||||
src-port return TOK_SRC_PORT;
|
||||
tcp-state return TOK_TCP_STATE;
|
||||
udp-state return TOK_UDP_STATE;
|
||||
active return TOK_ACTIVE;
|
||||
|
||||
file-magic { rules_lval.val = zeek::detail::Rule::FILE_MAGIC; return TOK_PATTERN_TYPE; }
|
||||
|
|
10
testing/btest/Baseline/signatures.udp-state/out
Normal file
10
testing/btest/Baseline/signatures.udp-state/out
Normal file
|
@ -0,0 +1,10 @@
|
|||
signature_match [orig_h=192.168.17.58, orig_p=58755/udp, resp_h=8.8.8.8, resp_p=53/udp] - my_sig_udp_orig
|
||||
0000 35 5e 01 00 00 01 00 00 00 00 00 00 06 67 6f 6f 5^...... .....goo
|
||||
0010 67 6c 65 03 63 6f 6d 00 01 01 00 01 gle.com. ....
|
||||
|
||||
signature_match [orig_h=192.168.17.58, orig_p=58755/udp, resp_h=8.8.8.8, resp_p=53/udp] - my_sig_udp_resp
|
||||
0000 35 5e 81 80 00 01 00 01 00 00 00 00 06 67 6f 6f 5^...... .....goo
|
||||
0010 67 6c 65 03 63 6f 6d 00 01 01 00 01 c0 0c 01 01 gle.com. ........
|
||||
0020 00 01 00 00 54 49 00 13 00 05 69 73 73 75 65 73 ....TI.. ..issues
|
||||
0030 79 6d 61 6e 74 65 63 2e 63 6f 6d ymantec. com
|
||||
|
2
testing/btest/Baseline/signatures.udp-state/reject
Normal file
2
testing/btest/Baseline/signatures.udp-state/reject
Normal file
|
@ -0,0 +1,2 @@
|
|||
error: Error in signature (udp-established.sig:5): 'established' is not a valid 'udp-state'
|
||||
|
36
testing/btest/signatures/udp-state.zeek
Normal file
36
testing/btest/signatures/udp-state.zeek
Normal file
|
@ -0,0 +1,36 @@
|
|||
# @TEST-EXEC: zeek -b -s udp-states.sig -r $TRACES/dns-caa.pcap %INPUT >out
|
||||
# @TEST-EXEC-FAIL: zeek -b -s udp-established.sig -r $TRACES/dns-caa.pcap %INPUT >reject 2>&1
|
||||
# @TEST-EXEC: btest-diff out
|
||||
# @TEST-EXEC: btest-diff reject
|
||||
|
||||
@TEST-START-FILE udp-states.sig
|
||||
signature my_sig_udp_orig {
|
||||
ip-proto == udp
|
||||
payload /.+/
|
||||
udp-state originator
|
||||
event "my_sig_udp_orig"
|
||||
}
|
||||
|
||||
signature my_sig_udp_resp {
|
||||
ip-proto == udp
|
||||
payload /.+/
|
||||
udp-state responder
|
||||
event "my_sig_udp_resp"
|
||||
}
|
||||
@TEST-END-FILE
|
||||
|
||||
@TEST-START-FILE udp-established.sig
|
||||
signature my_sig_udp_est {
|
||||
ip-proto == udp
|
||||
payload /.+/
|
||||
udp-state established
|
||||
event "my_sig_udp_est"
|
||||
}
|
||||
@TEST-END-FILE
|
||||
|
||||
event signature_match(state: signature_state, msg: string, data: string)
|
||||
{
|
||||
print fmt("signature_match %s - %s", state$conn$id, msg);
|
||||
local s = split_string(hexdump(data), /\n/);
|
||||
for ( i in s ) print s[i];
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue