Merge remote-tracking branch 'origin/topic/awelzel/websocket-continuation-opcode-fix'

* origin/topic/awelzel/websocket-continuation-opcode-fix:
  websocket: Fix opcode for continuation frames
This commit is contained in:
Arne Welzel 2024-01-25 12:21:24 +01:00
commit ba510f018c
8 changed files with 47 additions and 3 deletions

View file

@ -1,3 +1,12 @@
6.2.0-dev.468 | 2024-01-25 12:21:24 +0100
* websocket: Fix opcode for continuation frames (Arne Welzel, Corelight)
A continuation frame has the same type as the first frame, but that
information wasn't used nor kept, resulting payload of continuation
frames not being forwarded. The pcap was created with a fake Python
server and a bit of message crafting.
6.2.0-dev.465 | 2024-01-24 15:25:16 -0800
* Prepare Broker manager for broker::variant (Dominik Charousset)

View file

@ -1 +1 @@
6.2.0-dev.465
6.2.0-dev.468

View file

@ -89,7 +89,7 @@ refine flow WebSocket_Flow += {
}
// Forward text and binary data to downstream analyzers.
if ( ${chunk.hdr.opcode} == OPCODE_TEXT|| ${chunk.hdr.opcode} == OPCODE_BINARY)
if ( effective_opcode_ == OPCODE_TEXT || effective_opcode_ == OPCODE_BINARY)
connection()->zeek_analyzer()->ForwardStream(data.length(),
data.data(),
is_orig());

View file

@ -87,12 +87,14 @@ flow WebSocket_Flow(is_orig: bool) {
uint64_t masking_key_idx_;
uint64_t frame_payload_len_;
std::array<uint8_t, 4> masking_key_;
uint8_t effective_opcode_;
%}
%init{
has_mask_ = false;
masking_key_idx_ = 0;
frame_payload_len_ = 0;
effective_opcode_ = OPCODE_CONTINUATION;
%}
function new_frame_payload(hdr: WebSocket_FrameHeader): uint64
@ -100,6 +102,11 @@ flow WebSocket_Flow(is_orig: bool) {
if ( frame_payload_len_ > 0 )
connection()->zeek_analyzer()->Weird("websocket_frame_not_consumed");
// Update the effective_opcode for all frames
// following this one in the message.
if ( ${hdr.first_frame} )
effective_opcode_ = ${hdr.opcode};
frame_payload_len_ = ${hdr.payload_len};
has_mask_ = ${hdr.has_mask};
masking_key_idx_ = 0;

View file

@ -0,0 +1,5 @@
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
websocket_established
http_header, T, HOST, localhost
http_header, F, SERVER, dont ask
http_header, F, CONTENT-LENGTH, 0

View file

@ -0,0 +1,23 @@
# @TEST-DOC: Test a HTTP request tunneled within WebSocket where the HTTP reply is fragmented. This wasn't handled properly in the first iteration.
#
# @TEST-EXEC: zeek -b -r $TRACES/websocket/fragmented-http-reply.pcap %INPUT >out
# @TEST-EXEC: btest-diff out
@load base/protocols/websocket
# Only print http_headers after the websocket_established() event
# to reduce the noise. There' a HTTP request within the WebSocket
# tunnel.
global ws = F;
event websocket_established(c: connection, aid: count)
{
ws = T;
print "websocket_established";
}
event http_header(c: connection, is_orig: bool, original_name: string, name: string, val: string)
{
if ( ws )
print "http_header", is_orig, name, val;
}

View file

@ -1 +1 @@
3577ad0657c0cd61222d329a840e881dacf93f07
43766922ec10cb7cf41d6b15156a8b5984808a44