From 4210e62e57cdee172b44066378574b65a4631d56 Mon Sep 17 00:00:00 2001 From: Evan Typanski Date: Thu, 19 Sep 2024 13:55:55 -0400 Subject: [PATCH] spicy-redis: Begin Spicy Redis analyzer --- scripts/base/protocols/redis/__load__.zeek | 1 + scripts/base/protocols/redis/main.zeek | 97 ++++++++++++++++ src/analyzer/protocol/redis/CMakeLists.txt | 6 + src/analyzer/protocol/redis/resp.evt | 8 ++ src/analyzer/protocol/redis/resp.spicy | 107 ++++++++++++++++++ src/analyzer/protocol/redis/zeek_resp.spicy | 72 ++++++++++++ .../conn.log.filtered | 2 + .../output | 2 + .../output | 25 ++++ .../scripts.base.protocols.redis.trace/output | 15 +++ .../resp.log | 24 ++++ testing/btest/Traces/redis/loop-redis.trace | Bin 0 -> 52946 bytes .../base/protocols/redis/availability.zeek | 3 + .../base/protocols/redis/standalone.spicy | 11 ++ .../scripts/base/protocols/redis/trace.zeek | 10 ++ 15 files changed, 383 insertions(+) create mode 100644 scripts/base/protocols/redis/__load__.zeek create mode 100644 scripts/base/protocols/redis/main.zeek create mode 100644 src/analyzer/protocol/redis/CMakeLists.txt create mode 100644 src/analyzer/protocol/redis/resp.evt create mode 100644 src/analyzer/protocol/redis/resp.spicy create mode 100644 src/analyzer/protocol/redis/zeek_resp.spicy create mode 100644 testing/btest/Baseline/scripts.base.protocols.redis.run-pcap/conn.log.filtered create mode 100644 testing/btest/Baseline/scripts.base.protocols.redis.run-pcap/output create mode 100644 testing/btest/Baseline/scripts.base.protocols.redis.standalone/output create mode 100644 testing/btest/Baseline/scripts.base.protocols.redis.trace/output create mode 100644 testing/btest/Baseline/scripts.base.protocols.redis.trace/resp.log create mode 100644 testing/btest/Traces/redis/loop-redis.trace create mode 100644 testing/btest/scripts/base/protocols/redis/availability.zeek create mode 100644 testing/btest/scripts/base/protocols/redis/standalone.spicy create mode 100644 testing/btest/scripts/base/protocols/redis/trace.zeek diff --git a/scripts/base/protocols/redis/__load__.zeek b/scripts/base/protocols/redis/__load__.zeek new file mode 100644 index 0000000000..a10fe855df --- /dev/null +++ b/scripts/base/protocols/redis/__load__.zeek @@ -0,0 +1 @@ +@load ./main diff --git a/scripts/base/protocols/redis/main.zeek b/scripts/base/protocols/redis/main.zeek new file mode 100644 index 0000000000..f71044b373 --- /dev/null +++ b/scripts/base/protocols/redis/main.zeek @@ -0,0 +1,97 @@ +@load base/protocols/conn/removal-hooks + +module RESP; + +export { + ## Log stream identifier. + redef enum Log::ID += { LOG }; + + ## The ports to register RESP for. + const ports = { + 6379/tcp, + } &redef; + + type RESPData: record { + simple_string: string &optional &log; + simple_error: string &optional &log; + i: int &optional &log; + bulk_string: string &optional &log; + #array: + is_null: bool &log; + boolean: bool &optional &log; + double_: double &optional &log; + big_num: string &optional &log; + bulk_error: string &optional &log; + verbatim_string: string &optional &log; + }; + + ## Record type containing the column fields of the RESP log. + type Info: record { + ## Timestamp for when the activity happened. + ts: time &log; + ## Unique ID for the connection. + uid: string &log; + ## The connection's 4-tuple of endpoint addresses/ports. + id: conn_id &log; + resp_data: RESPData &log; + }; + + ## A default logging policy hook for the stream. + global log_policy: Log::PolicyHook; + + ## Default hook into RESP logging. + global log_resp: event(rec: Info); +} + +redef record connection += { + redis_resp: Info &optional; +}; + +redef likely_server_ports += { ports }; + +# TODO: If you're going to send file data into the file analysis framework, you +# need to provide a file handle function. This is a simple example that's +# sufficient if the protocol only transfers a single, complete file at a time. +# +# function get_file_handle(c: connection, is_orig: bool): string +# { +# return cat(Analyzer::ANALYZER_SPICY_RESP, c$start_time, c$id, is_orig); +# } + +event zeek_init() &priority=5 + { + Log::create_stream(RESP::LOG, [$columns=Info, $ev=log_resp, $path="resp", $policy=log_policy]); + + Analyzer::register_for_ports(Analyzer::ANALYZER_SPICY_RESP, ports); + + # TODO: To activate the file handle function above, uncomment this. + # Files::register_protocol(Analyzer::ANALYZER_SPICY_RESP, [$get_file_handle=RESP::get_file_handle ]); + } + +# Initialize logging state. +hook set_session(c: connection) + { + if ( c?$redis_resp ) + return; + + c$redis_resp = Info($ts=network_time(), $uid=c$uid, $id=c$id); + } + +function emit_log(c: connection) + { + if ( ! c?$redis_resp ) + return; + + Log::write(RESP::LOG, c$redis_resp); + delete c$redis_resp; + } + +# Example event defined in resp.evt. +event RESP::data(c: connection, payload: RESPData) + { + hook set_session(c); + + local info = c$redis_resp; + info$resp_data = payload; + emit_log(c); + } diff --git a/src/analyzer/protocol/redis/CMakeLists.txt b/src/analyzer/protocol/redis/CMakeLists.txt new file mode 100644 index 0000000000..e2fb1ab53c --- /dev/null +++ b/src/analyzer/protocol/redis/CMakeLists.txt @@ -0,0 +1,6 @@ +spicy_add_analyzer( + NAME RESP + PACKAGE_NAME spicy-resp + SOURCES resp.spicy resp.evt zeek_resp.spicy + SCRIPTS __load__.zeek main.zeek +) diff --git a/src/analyzer/protocol/redis/resp.evt b/src/analyzer/protocol/redis/resp.evt new file mode 100644 index 0000000000..25cd1ebdd1 --- /dev/null +++ b/src/analyzer/protocol/redis/resp.evt @@ -0,0 +1,8 @@ +protocol analyzer spicy::RESP over TCP: + parse with RESP::Messages, + port 6379/tcp; + +import RESP; +import Zeek_RESP; + +on RESP::Data -> event RESP::data($conn, Zeek_RESP::create_data(self)); diff --git a/src/analyzer/protocol/redis/resp.spicy b/src/analyzer/protocol/redis/resp.spicy new file mode 100644 index 0000000000..f661a8e0bb --- /dev/null +++ b/src/analyzer/protocol/redis/resp.spicy @@ -0,0 +1,107 @@ +module RESP; + +public type Messages = unit { + : Data[]; +}; + +public type Data = unit { + ty: uint8 &convert=DataType($$); + switch ( self.ty ) { + DataType::SIMPLE_STRING -> simple_string: SimpleString(False); + DataType::SIMPLE_ERROR -> simple_error: SimpleString(True); + DataType::INTEGER -> integer: Integer; + DataType::BULK_STRING -> bulk_string: BulkString(False); + DataType::ARRAY -> array: Array; + DataType::NULL -> null: Null_; + DataType::BOOLEAN -> boolean: Boolean; + DataType::DOUBLE -> double: Double; + DataType::BIG_NUM -> big_num: BigNum; + DataType::BULK_ERROR -> bulk_error: BulkString(True); + # This can be a different type, but the docs also say: + # "Some client libraries may ignore the difference between this type and the string type" + # It just includes the encoding first in the content + DataType::VERBATIM_STRING -> verbatim_string: BulkString(False); + DataType::MAP -> map_: Map; + DataType::SET -> set_: Set; + # "Push events are encoded similarly to arrays, differing only in their + # first byte" - TODO: can probably make it more obvious, though + DataType::PUSH -> push: Array; + }; +}; + +type DataType = enum { + SIMPLE_STRING = '+', + SIMPLE_ERROR = '-', + INTEGER = ':', + BULK_STRING = '$', + ARRAY = '*', + NULL = '_', + BOOLEAN = '#', + DOUBLE = ',', + BIG_NUM = '(', + BULK_ERROR = '!', + VERBATIM_STRING = '=', + MAP = '%', + SET = '~', + PUSH = '>' +}; + +type SimpleString = unit(is_error: bool) { + content: bytes &until=b"\x0d\x0a"; +}; + +type Integer = unit { + int: bytes &convert=$$.to_int(10) &until=b"\x0d\x0a"; +}; + +type BulkString = unit(is_error: bool) { + length: bytes &convert=$$.to_int(10) &until=b"\x0d\x0a"; + # NullBulkString is a BulkString with content unset + content: bytes &size=uint64( self.length ) if ( self.length >= 0 ); + + # Consume last CLRF + : bytes &until=b"\x0d\x0a"; +}; + +type Array = unit { + num_elements: bytes &convert=$$.to_int(10) &until=b"\x0d\x0a"; + # Null array is an array with elements unset. This is different from an empty array + elements: Data[uint64(self.num_elements)] if ( self.num_elements >= 0 ); +}; + +type Null_ = unit { + # Still must consume CLRF + : bytes &until=b"\x0d\x0a"; +}; + +type Boolean = unit { + val: uint8 &convert=$$ == 't'; + : bytes &until=b"\x0d\x0a"; +}; + +type Double = unit { + val: bytes &convert=$$.to_real() &until=b"\x0d\x0a"; +}; + +type BigNum = unit { + # Big num can be very big so put it in a UTF-8 decoded string + val: bytes &convert=$$.decode() &until=b"\x0d\x0a"; +}; + +type Map = unit { + var key_val_pairs: vector>; + num_elements: bytes &convert=$$.to_uint(10) &until=b"\x0d\x0a"; + # TODO: How can I make this into a map? Alternatively, how can I do this better? + raw_data: Data[self.num_elements*2] { + while ( local i = 0; i < self.num_elements ) { + self.key_val_pairs.push_back(($$[i], $$[i+1])); + i += 2; + } + } +}; + +type Set = unit { + num_elements: bytes &convert=$$.to_uint(10) &until=b"\x0d\x0a"; + # TODO: This should be a set but doesn't go in the backed C++ set + elements: Data[self.num_elements]; +}; diff --git a/src/analyzer/protocol/redis/zeek_resp.spicy b/src/analyzer/protocol/redis/zeek_resp.spicy new file mode 100644 index 0000000000..89a163daa9 --- /dev/null +++ b/src/analyzer/protocol/redis/zeek_resp.spicy @@ -0,0 +1,72 @@ +# Set up protocol confirmation/rejection for analyzers, as well as any further +# Zeek-specific analysis. + +module Zeek_RESP; + +import RESP; +import zeek; + +# Any error bubbling up to the top unit will trigger a protocol rejection. +on RESP::Data::%done { + zeek::confirm_protocol(); +} + +on RESP::Data::%error { + zeek::reject_protocol("error while parsing RESP data"); +} + +type ZeekData = tuple< + optional, + optional, + optional, + optional, + #optional>, # TODO: This segfaults because recursive type :( + bool, + optional, + optional, + optional, + optional, + optional, +>; + +public function create_data(data: RESP::Data): ZeekData { + local simple_string: optional; + local simple_error: optional; + local i: optional; + local bulk_string: optional; + #local array: optional>; + local null: bool; + local boolean: optional; + local double: optional; + local big_num: optional; + local bulk_error: optional; + local verbatim_string: optional; + if (data?.simple_string) + simple_string = data.simple_string.content; + if (data?.simple_error) + simple_error = data.simple_error.content; + if (data?.integer) + i = data.integer.int; + if (data?.bulk_string) + bulk_string = data.bulk_string.content; + #if (data?.array) { + # for ( data in data.array.elements ) { + # array.push_back(data); + # } + #} + if (data?.null) + null = True; + else + null = False; + if (data?.boolean) + boolean = data.boolean.val; + if (data?.double) + double = data.double.val; + if (data?.big_num) + big_num = data.big_num.val; + if (data?.bulk_error) + bulk_error = data.bulk_error.content; + if (data?.verbatim_string) + verbatim_string = data.verbatim_string.content; + return (simple_string, simple_error, i, bulk_string, null, boolean, double, big_num, bulk_error, verbatim_string); +} diff --git a/testing/btest/Baseline/scripts.base.protocols.redis.run-pcap/conn.log.filtered b/testing/btest/Baseline/scripts.base.protocols.redis.run-pcap/conn.log.filtered new file mode 100644 index 0000000000..1e6917b8c7 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.redis.run-pcap/conn.log.filtered @@ -0,0 +1,2 @@ +ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes tunnel_parents +XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 10.1.9.63 63526 54.175.222.246 80 tcp http 0.755677 207 489 SF 0 ShADTadFf 7 790 4 705 - diff --git a/testing/btest/Baseline/scripts.base.protocols.redis.run-pcap/output b/testing/btest/Baseline/scripts.base.protocols.redis.run-pcap/output new file mode 100644 index 0000000000..781c9fcbd9 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.redis.run-pcap/output @@ -0,0 +1,2 @@ +Hello world! +Goodbye world! diff --git a/testing/btest/Baseline/scripts.base.protocols.redis.standalone/output b/testing/btest/Baseline/scripts.base.protocols.redis.standalone/output new file mode 100644 index 0000000000..6a6e880e2d --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.redis.standalone/output @@ -0,0 +1,25 @@ +### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. +RESP::Data { + ty: SIMPLE_STRING + simple_string: RESP::SimpleString { + content: OK + } +} +RESP::Data { + ty: INTEGER + integer: RESP::Integer { + int_: 1000 + } +} +RESP::Data { + ty: INTEGER + integer: RESP::Integer { + int_: -1000 + } +} +RESP::Data { + ty: INTEGER + integer: RESP::Integer { + int_: 1000 + } +} diff --git a/testing/btest/Baseline/scripts.base.protocols.redis.trace/output b/testing/btest/Baseline/scripts.base.protocols.redis.trace/output new file mode 100644 index 0000000000..a3c0b852bb --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.redis.trace/output @@ -0,0 +1,15 @@ +### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. +Testing RESP: [simple_string=, simple_error=, i=, bulk_string=SET, is_null=F, boolean=, double_=, big_num=, bulk_error=, verbatim_string=] +Testing RESP: [simple_string=, simple_error=, i=, bulk_string=hi:2, is_null=F, boolean=, double_=, big_num=, bulk_error=, verbatim_string=] +Testing RESP: [simple_string=, simple_error=, i=, bulk_string=2, is_null=F, boolean=, double_=, big_num=, bulk_error=, verbatim_string=] +Testing RESP: [simple_string=, simple_error=, i=, bulk_string=, is_null=F, boolean=, double_=, big_num=, bulk_error=, verbatim_string=] +Testing RESP: [simple_string=OK, simple_error=, i=, bulk_string=, is_null=F, boolean=, double_=, big_num=, bulk_error=, verbatim_string=] +Testing RESP: [simple_string=, simple_error=, i=, bulk_string=SET, is_null=F, boolean=, double_=, big_num=, bulk_error=, verbatim_string=] +Testing RESP: [simple_string=, simple_error=, i=, bulk_string=hi:3, is_null=F, boolean=, double_=, big_num=, bulk_error=, verbatim_string=] +Testing RESP: [simple_string=, simple_error=, i=, bulk_string=sup, is_null=F, boolean=, double_=, big_num=, bulk_error=, verbatim_string=] +Testing RESP: [simple_string=, simple_error=, i=, bulk_string=, is_null=F, boolean=, double_=, big_num=, bulk_error=, verbatim_string=] +Testing RESP: [simple_string=OK, simple_error=, i=, bulk_string=, is_null=F, boolean=, double_=, big_num=, bulk_error=, verbatim_string=] +Testing RESP: [simple_string=, simple_error=, i=, bulk_string=GET, is_null=F, boolean=, double_=, big_num=, bulk_error=, verbatim_string=] +Testing RESP: [simple_string=, simple_error=, i=, bulk_string=hi:3, is_null=F, boolean=, double_=, big_num=, bulk_error=, verbatim_string=] +Testing RESP: [simple_string=, simple_error=, i=, bulk_string=, is_null=F, boolean=, double_=, big_num=, bulk_error=, verbatim_string=] +Testing RESP: [simple_string=, simple_error=, i=, bulk_string=sup, is_null=F, boolean=, double_=, big_num=, bulk_error=, verbatim_string=] diff --git a/testing/btest/Baseline/scripts.base.protocols.redis.trace/resp.log b/testing/btest/Baseline/scripts.base.protocols.redis.trace/resp.log new file mode 100644 index 0000000000..85c62c2387 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.redis.trace/resp.log @@ -0,0 +1,24 @@ +### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path resp +#open XXXX-XX-XX-XX-XX-XX +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p resp_data.simple_string resp_data.simple_error resp_data.i resp_data.bulk_string resp_data.is_null resp_data.boolean resp_data.double_ resp_data.big_num resp_data.bulk_error resp_data.verbatim_string +#types time string addr port addr port string string int string bool bool double string string string +XXXXXXXXXX.XXXXXX C4J4Th3PJpwUYZZ6gc 127.0.0.1 58972 127.0.0.1 6379 - - - SET F - - - - - +XXXXXXXXXX.XXXXXX C4J4Th3PJpwUYZZ6gc 127.0.0.1 58972 127.0.0.1 6379 - - - hi:2 F - - - - - +XXXXXXXXXX.XXXXXX C4J4Th3PJpwUYZZ6gc 127.0.0.1 58972 127.0.0.1 6379 - - - 2 F - - - - - +XXXXXXXXXX.XXXXXX C4J4Th3PJpwUYZZ6gc 127.0.0.1 58972 127.0.0.1 6379 - - - - F - - - - - +XXXXXXXXXX.XXXXXX C4J4Th3PJpwUYZZ6gc 127.0.0.1 58972 127.0.0.1 6379 OK - - - F - - - - - +XXXXXXXXXX.XXXXXX C4J4Th3PJpwUYZZ6gc 127.0.0.1 58972 127.0.0.1 6379 - - - SET F - - - - - +XXXXXXXXXX.XXXXXX C4J4Th3PJpwUYZZ6gc 127.0.0.1 58972 127.0.0.1 6379 - - - hi:3 F - - - - - +XXXXXXXXXX.XXXXXX C4J4Th3PJpwUYZZ6gc 127.0.0.1 58972 127.0.0.1 6379 - - - sup F - - - - - +XXXXXXXXXX.XXXXXX C4J4Th3PJpwUYZZ6gc 127.0.0.1 58972 127.0.0.1 6379 - - - - F - - - - - +XXXXXXXXXX.XXXXXX C4J4Th3PJpwUYZZ6gc 127.0.0.1 58972 127.0.0.1 6379 OK - - - F - - - - - +XXXXXXXXXX.XXXXXX C4J4Th3PJpwUYZZ6gc 127.0.0.1 58972 127.0.0.1 6379 - - - GET F - - - - - +XXXXXXXXXX.XXXXXX C4J4Th3PJpwUYZZ6gc 127.0.0.1 58972 127.0.0.1 6379 - - - hi:3 F - - - - - +XXXXXXXXXX.XXXXXX C4J4Th3PJpwUYZZ6gc 127.0.0.1 58972 127.0.0.1 6379 - - - - F - - - - - +XXXXXXXXXX.XXXXXX C4J4Th3PJpwUYZZ6gc 127.0.0.1 58972 127.0.0.1 6379 - - - sup F - - - - - +#close XXXX-XX-XX-XX-XX-XX diff --git a/testing/btest/Traces/redis/loop-redis.trace b/testing/btest/Traces/redis/loop-redis.trace new file mode 100644 index 0000000000000000000000000000000000000000..4ce10fdf5577fd295fbf1f4db66e2e2bf6946c97 GIT binary patch literal 52946 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 2>&1 +# @TEST-EXEC: printf ":1000\x0d\x0a" | spicy-dump -p RESP::Data resp.hlto >>output 2>&1 +# @TEST-EXEC: printf ":-1000\x0d\x0a" | spicy-dump -p RESP::Data resp.hlto >>output 2>&1 +# @TEST-EXEC: printf ":+1000\x0d\x0a" | spicy-dump -p RESP::Data resp.hlto >>output 2>&1 +# @TEST-EXEC: TEST_DIFF_CANONIFIER= btest-diff output diff --git a/testing/btest/scripts/base/protocols/redis/trace.zeek b/testing/btest/scripts/base/protocols/redis/trace.zeek new file mode 100644 index 0000000000..bc20102b6c --- /dev/null +++ b/testing/btest/scripts/base/protocols/redis/trace.zeek @@ -0,0 +1,10 @@ +# @TEST-DOC: Test Zeek parsing a trace file through the RESP analyzer. +# +# @TEST-EXEC: zeek -Cr $TRACES/redis/loop-redis.trace base/protocols/redis %INPUT >output +# @TEST-EXEC: btest-diff output +# @TEST-EXEC: btest-diff resp.log + +event RESP::data(c: connection, payload: RESP::RESPData) + { + print fmt("Testing RESP: %s", payload); + }