WebSocket: Introduce new analyzer and log

This adds a new WebSocket analyzer that is enabled with the HTTP upgrade
mechanism introduced previously. It is a first implementation in BinPac with
manual chunking of frame payload. Configuration of the analyzer is sketched
via the new websocket_handshake() event and a configuration BiF called
WebSocket::__configure_analyzer(). In short, script land collects WebSocket
related HTTP headers and can forward these to the analyzer to change its
parsing behavior at websocket_handshake() time. For now, however, there's
no actual logic that would change behavior based on agreed upon extensions
exchanged via HTTP headers (e.g. frame compression). WebSocket::Configure()
simply attaches a PIA_TCP analyzer to the WebSocket analyzer for dynamic
protocol detection (or a custom analyzer if set). The added pcaps show this
in action for tunneled ssh, http and https using wstunnel. One test pcap is
Broker's WebSocket traffic from our own test suite, the other is the
Jupyter websocket traffic from the ticket/discussion.

This commit further adds a basic websocket.log that aggregates the WebSocket
specific headers (Sec-WebSocket-*) headers into a single log.

Closes #3424
This commit is contained in:
Arne Welzel 2024-01-13 16:56:52 +01:00
parent 8ebd054abc
commit efc2681152
55 changed files with 1256 additions and 6 deletions

View file

@ -458,6 +458,41 @@ export {
const upgrade_analyzers: table[string] of Analyzer::Tag &redef;
}
module WebSocket;
export {
## The WebSocket analyzer consumes and forwards
## frame payload in chunks to keep memory usage
## bounded. There should not be a reason to change
## this value except for debugging and
## testing reasons.
const payload_chunk_size = 8192 &redef;
## Whether to enable DPD on WebSocket frame payload by default.
const use_dpd_default = T &redef;
## Record type that is passed to :zeek:see:`WebSocket::__configure_analyzer`.
##
## This allows to configure the WebSocket analyzer given parameters
## collected from HTTP headers.
type AnalyzerConfig: record {
## The analyzer to attach for analysis of the WebSocket
## frame payload. See *use_dpd* below for the behavior
## when unset.
analyzer: Analyzer::Tag &optional;
## If *analyzer* is unset, determines whether to attach a
## PIA_TCP analyzer for dynamic protocol detection with
## WebSocket payload.
use_dpd: bool &default=use_dpd_default;
## The subprotocol as selected by the server, if any.
subprotocol: string &optional;
## The WebSocket extensions as selected by the server, if any.
server_extensions: vector of string &optional;
};
}
module GLOBAL;
## A type alias for a vector of encapsulating "connections", i.e. for when

View file

@ -78,6 +78,7 @@
@load base/protocols/ssh
@load base/protocols/ssl
@load base/protocols/syslog
@load base/protocols/websocket
@load base/protocols/tunnels
@load base/protocols/xmpp

View file

@ -0,0 +1,2 @@
@load ./consts.zeek
@load ./main.zeek

View file

@ -0,0 +1,21 @@
##! WebSocket constants.
module WebSocket;
export {
const OPCODE_CONTINUATION = 0x00;
const OPCODE_TEXT = 0x01;
const OPCODE_BINARY = 0x02;
const OPCODE_CLOSE = 0x08;
const OPCODE_PING = 0x09;
const OPCODE_PONG = 0x0a;
const opcodes: table[count] of string = {
[OPCODE_CONTINUATION] = "continuation",
[OPCODE_TEXT] = "text",
[OPCODE_BINARY] = "binary",
[OPCODE_CLOSE] = "close",
[OPCODE_PING] = "ping",
[OPCODE_PONG] = "pong",
} &default=function(opcode: count): string { return fmt("unknown-%x", opcode); } &redef;
}

View file

@ -0,0 +1,176 @@
##! Implements base functionality for WebSocket analysis.
##!
##! Upon a websocket_handshake(), logs all gathered information into websocket.log
##! and then configures the WebSocket analyzer with the headers collected using
##! http events.
@load base/protocols/http
module WebSocket;
# Register the WebSocket analyzer as HTTP upgrade analyzer.
redef HTTP::upgrade_analyzers += {
["websocket"] = Analyzer::ANALYZER_WEBSOCKET,
};
export {
redef enum Log::ID += { LOG };
## The record type for the WebSocket log.
type Info: record {
## Timestamp
ts: time &log;
## Unique ID for the connection.
uid: string &log;
## The connection's 4-tuple of endpoint addresses/ports.
id: conn_id &log;
## Same as in the HTTP log.
host: string &log &optional;
## Same as in the HTTP log.
uri: string &log &optional;
## Same as in the HTTP log.
user_agent: string &log &optional;
## The WebSocket subprotocol as selected by the server.
subprotocol: string &log &optional;
## The protocols requested by the client, if any.
client_protocols: vector of string &log &optional;
## The extensions selected by the the server, if any.
server_extensions: vector of string &log &optional;
## The extensions requested by the client, if any.
client_extensions: vector of string &log &optional;
};
## Event that can be handled to access the WebSocket record as it is
## sent on to the logging framework.
global log_websocket: event(rec: Info);
## Log policy hook.
global log_policy: Log::PolicyHook;
## Hook to allow interception of WebSocket analyzer configuration.
##
## c: The connection
##
## aid: The analyzer ID for the WebSocket analyzer.
##
## config: The configuration record, also containing information
## about the subprotocol and extensions.
global configure_analyzer: hook(c: connection, aid: count, config: AnalyzerConfig);
}
redef record connection += {
websocket: Info &optional;
};
function set_websocket(c: connection)
{
c$websocket = Info(
$ts=network_time(),
$uid=c$uid,
$id=c$id,
);
}
event http_header(c: connection, is_orig: bool, name: string, value: string)
{
if ( ! starts_with(name, "SEC-WEBSOCKET-") )
return;
if ( ! c?$websocket )
set_websocket(c);
local ws = c$websocket;
if ( is_orig )
{
if ( name == "SEC-WEBSOCKET-PROTOCOL" )
{
if ( ! ws?$client_protocols )
ws$client_protocols = vector();
ws$client_protocols += split_string(value, / *, */);
}
else if ( name == "SEC-WEBSOCKET-EXTENSIONS" )
{
if ( ! ws?$client_extensions )
ws$client_extensions = vector();
ws$client_extensions += split_string(value, / *, */);
}
}
else
{
if ( name == "SEC-WEBSOCKET-PROTOCOL" )
{
ws$subprotocol = value;
}
else if ( name == "SEC-WEBSOCKET-EXTENSIONS" )
{
if ( ! ws?$server_extensions )
ws$server_extensions = vector();
ws$server_extensions += split_string(value, / *, */);
}
}
}
event http_request(c: connection, method: string, original_URI: string,
unescaped_URI: string, version: string)
{
# If we see a http_request and have websocket state, wipe it as
# we should've seen a websocket_handshake even on success and
# likely no more http events.
if ( ! c?$websocket )
delete c$websocket;
}
event websocket_handshake(c: connection, aid: count) &priority=5
{
if ( ! c?$websocket )
{
# This means we never saw a Sec-WebSocket-* header, weird.
Reporter::conn_weird("websocket_handshake_unexpected", c, "", "WebSocket");
set_websocket(c);
}
local ws = c$websocket;
# Replicate some information from the HTTP.log
if ( c?$http )
{
if ( c$http?$host )
ws$host = c$http$host;
if ( c$http?$uri )
ws$uri = c$http$uri;
if ( c$http?$user_agent )
ws$user_agent = c$http$user_agent;
}
}
event websocket_handshake(c: connection, aid: count) &priority=-5
{
local ws = c$websocket;
local config = AnalyzerConfig();
if ( ws?$subprotocol )
config$subprotocol = ws$subprotocol;
if ( ws?$server_extensions )
config$server_extensions = ws$server_extensions;
# Give other scripts a chance to modify the analyzer configuration.
hook WebSocket::configure_analyzer(c, aid, config);
WebSocket::__configure_analyzer(c, aid, config);
ws$ts = network_time();
Log::write(LOG, ws);
}
event zeek_init()
{
Log::create_stream(LOG, [$columns=Info, $ev=log_websocket, $path="websocket", $policy=log_policy]);
}

View file

@ -42,5 +42,6 @@ add_subdirectory(ssh)
add_subdirectory(ssl)
add_subdirectory(syslog)
add_subdirectory(tcp)
add_subdirectory(websocket)
add_subdirectory(xmpp)
add_subdirectory(zip)

View file

@ -0,0 +1,15 @@
zeek_add_plugin(
Zeek
WebSocket
SOURCES
WebSocket.cc
Plugin.cc
BIFS
consts.bif
events.bif
functions.bif
types.bif
PAC
websocket.pac
websocket-analyzer.pac
websocket-protocol.pac)

View file

@ -0,0 +1,24 @@
// See the file "COPYING" in the main distribution directory for copyright.
#include "zeek/plugin/Plugin.h"
#include "zeek/analyzer/Component.h"
#include "analyzer/protocol/websocket/WebSocket.h"
namespace zeek::plugin::detail::Zeek_WebSocket {
class Plugin : public zeek::plugin::Plugin {
public:
zeek::plugin::Configuration Configure() override {
AddComponent(
new zeek::analyzer::Component("WebSocket", zeek::analyzer::websocket::WebSocket_Analyzer::Instantiate));
zeek::plugin::Configuration config;
config.name = "Zeek::WebSocket";
config.description = "WebSocket analyzer";
return config;
}
} plugin;
} // namespace zeek::plugin::detail::Zeek_WebSocket

View file

@ -0,0 +1,101 @@
// See the file in the main distribution directory for copyright.
#include "zeek/analyzer/protocol/websocket/WebSocket.h"
#include <string_view>
#include "zeek/analyzer/Manager.h"
#include "zeek/analyzer/protocol/pia/PIA.h"
#include "zeek/analyzer/protocol/websocket/events.bif.h"
namespace zeek::analyzer::websocket {
WebSocket_Analyzer::WebSocket_Analyzer(Connection* conn) : analyzer::tcp::TCP_ApplicationAnalyzer("WebSocket", conn) {
// TODO: Consider approaches dispatching to optionally use a
// Spicy analyzer here instead of the BinPac interpreter.
//
// E.g. we could instantiate a SPICY_WEBSOCKET analyzer and pass it the necessary
// information and call DeliverStream() directly on it.
interp = std::make_unique<binpac::WebSocket::WebSocket_Conn>(this);
}
void WebSocket_Analyzer::Init() {
tcp::TCP_ApplicationAnalyzer::Init();
// This event calls back via Configure()
zeek::BifEvent::enqueue_websocket_handshake(this, Conn(), GetID());
}
bool WebSocket_Analyzer::Configure(zeek::RecordValPtr config) {
// TODO: Check extensions and modify parsing if needed, e.g. WebSocket frame
// compression extension: https://www.rfc-editor.org/rfc/rfc7692.html
//
// interp->SetExtensions(...)
//
// TODO: The Sec-WebSocket-Protocol header might provide some information
// that we could leverage to instantiate a more specific analyzer.
//
// For now, we just attach a PIA analyzer as child analyzer.
static const auto& config_type = id::find_type<zeek::RecordType>("WebSocket::AnalyzerConfig");
static int analyzer_idx = config_type->FieldOffset("analyzer");
static int use_dpd_idx = config_type->FieldOffset("use_dpd");
if ( config->HasField(analyzer_idx) ) {
const auto& analyzer_tag_val = config->GetField(analyzer_idx);
auto analyzer_tag = analyzer_mgr->GetComponentTag(analyzer_tag_val.get());
if ( analyzer_tag == zeek::Tag() ) {
reporter->InternalWarning("no component tag for enum '%s'",
analyzer_tag_val->GetType<EnumType>()->Lookup(analyzer_tag_val->AsEnum()));
return false;
}
DBG_LOG(DBG_ANALYZER, "%s Configure() using analyzer %s", fmt_analyzer(this).c_str(),
analyzer_tag_val->GetType<EnumType>()->Lookup(analyzer_tag_val->AsEnum()));
auto* analyzer = analyzer_mgr->InstantiateAnalyzer(analyzer_tag, Conn());
if ( ! analyzer )
return false;
return AddChildAnalyzer(analyzer);
}
else if ( config->GetField(use_dpd_idx)->AsBool() ) {
DBG_LOG(DBG_ANALYZER, "%s Configure() enables DPD via PIA_TCP", fmt_analyzer(this).c_str());
auto* pia = new analyzer::pia::PIA_TCP(Conn());
if ( AddChildAnalyzer(pia) ) {
pia->FirstPacket(true, nullptr);
pia->FirstPacket(false, nullptr);
return true;
}
return false;
}
// Neither analyzer nor dpd was enabled, success.
return true;
}
void WebSocket_Analyzer::DeliverStream(int len, const u_char* data, bool orig) {
analyzer::tcp::TCP_ApplicationAnalyzer::DeliverStream(len, data, orig);
if ( had_gap ) {
DBG_LOG(DBG_ANALYZER, "Skipping data after gap len=%d orig=%d", len, orig);
return;
}
try {
interp->NewData(orig, data, data + len);
} catch ( const binpac::Exception& e ) {
AnalyzerViolation(e.c_msg(), reinterpret_cast<const char*>(data), len);
}
}
void WebSocket_Analyzer::Undelivered(uint64_t seq, int len, bool orig) {
analyzer::tcp::TCP_ApplicationAnalyzer::Undelivered(seq, len, orig);
interp->NewGap(orig, len);
had_gap = true;
}
} // namespace zeek::analyzer::websocket

View file

@ -0,0 +1,38 @@
// See the file "COPYING" in the main distribution directory for copyright.
#pragma once
#include <memory>
#include "zeek/analyzer/protocol/tcp/TCP.h"
#include "zeek/analyzer/protocol/websocket/websocket_pac.h"
namespace zeek::analyzer::websocket {
/**
* A WebSocket analyzer to be used directly on top of HTTP.
*/
class WebSocket_Analyzer : public analyzer::tcp::TCP_ApplicationAnalyzer {
public:
WebSocket_Analyzer(zeek::Connection* conn);
~WebSocket_Analyzer() = default;
/**
* Allows script land to configure the WebSocket analyzer before analysis.
*
* @param config Zeek value of type WebSocket::AnalyzerConfig
*/
bool Configure(zeek::RecordValPtr config);
void Init() override;
void DeliverStream(int len, const u_char* data, bool orig) override;
void Undelivered(uint64_t seq, int len, bool orig) override;
static zeek::analyzer::Analyzer* Instantiate(Connection* conn) { return new WebSocket_Analyzer(conn); }
private:
std::unique_ptr<binpac::WebSocket::WebSocket_Conn> interp;
bool had_gap = false;
};
} // namespace zeek::analyzer::websocket

View file

@ -0,0 +1 @@
const WebSocket::payload_chunk_size: count;

View file

@ -0,0 +1,71 @@
## Generated when a WebSocket handshake completed.
##
## This is a bit artificial. It can be used to configure the WebSocket
## analyzer if the HTTP headers contained protocol and extension headers.
##
## c: The WebSocket connection.
##
## aid: The analyzer identifier of the WebSocket analyzer.
##
## .. zeek:see:: WebSocket::__configure_analyzer
##
## .. zeek:see:: WebSocket::configure_analyzer
##
event websocket_handshake%(c: connection, aid: count%);
## Generated for every WebSocket frame.
##
## c: The WebSocket connection.
##
## is_orig: True if the frame is from the originator, else false.
##
## fin: True if the fin bit is set, else false.
##
## rsv: The value of the RSV1, RSV2 and RSV3 bits.
##
## opcode: The frame's opcode.
##
## payload_len: The frame's payload length.
##
event websocket_frame%(c: connection, is_orig: bool, fin: bool, rsv: count, opcode: count, payload_len: count%);
## Generated for every chunk of WebSocket frame payload data.
##
## Do not use it to extract data from a WebSocket connection unless for testing
## or experimentation. Consider implementing a proper analyzer instead.
##
## c: The WebSocket connection.
##
## is_orig: True if the frame is from the originator, else false.
##
## data: One data chunk of frame payload. The length of is at most
## :zeek:see:`WebSocket::payload_chunk_size` bytes. A frame with
## a longer payload will result in multiple events events.
##
## .. zeek:see:: WebSocket::payload_chunk_size
event websocket_frame_data%(c: connection, is_orig: bool, data: string%);
## Generated for every completed WebSocket message.
##
## c: The WebSocket connection.
##
## is_orig: True if the frame is from the originator, else false.
##
## opcode: The first frame's opcode.
event websocket_message%(c: connection, is_orig: bool, opcode: count%);
## Generated for WebSocket Close frames.
##
## c: The WebSocket connection.
##
## is_orig: True if the frame is from the originator, else false.
##
## status: If the CloseFrame had no payload, this is 0, otherwise the value
## of the first two bytes in the frame's payload.
##
## reason: Remaining payload after *status*. This is capped at
## 2 bytes less than :zeek:see:`WebSocket::payload_chunk_size`.
##
## .. zeek:see:: WebSocket::payload_chunk_size
event websocket_close%(c: connection, is_orig: bool, status: count, reason: string%);

View file

@ -0,0 +1,46 @@
%%{
#include "zeek/analyzer/protocol/websocket/WebSocket.h"
%%}
module WebSocket;
## Configure the WebSocket analyzer.
##
## Called during :zeek:see:`websocket_handshake` to configure
## the WebSocket analyzer given the selected protocol and extension
## as chosen by the server.
##
## c: The WebSocket connection.
#
## aid: The identifier for the WebSocket analyzer as provided to :zeek:see:`websocket_handshake`.
##
## server_protocol: The protocol as found in the server's Sec-WebSocket-Protocol HTTP header, or empty.
##
## server_extensions: The extension as selected by the server via the Sec-WebSocket-Extensions HTTP Header.
##
## .. zeek:see:: websocket_handshake
function __configure_analyzer%(c: connection, aid: count, config: WebSocket::AnalyzerConfig%): bool
%{
auto* analyzer = c->FindAnalyzer(aid);
auto* ws_analyzer = dynamic_cast<analyzer::websocket::WebSocket_Analyzer*>(analyzer);
if ( ! ws_analyzer )
{
reporter->Warning("WebSocket analyzer to configure not found");
return zeek::val_mgr->False();
}
static const auto& config_type = zeek::id::find_type<zeek::RecordType>("WebSocket::AnalyzerConfig");
if ( config->GetType() != config_type )
{
reporter->Warning("config has wrong type %s, expected %s",
config->GetType()->GetName().c_str(),
config_type->GetName().c_str());
return zeek::val_mgr->False();
}
if ( ! ws_analyzer->Configure({zeek::NewRef{}, config->AsRecordVal()}) )
return zeek::val_mgr->False();
return zeek::val_mgr->True();
%}

View file

@ -0,0 +1,4 @@
module WebSocket;
# A configuration record used for the WebSocket analyzer.
type AnalyzerConfig: record;

View file

@ -0,0 +1,126 @@
# See the file "COPYING" in the main distribution directory for copyright.
#
# The WebSocket analyzer.
#
refine flow WebSocket_Flow += {
function process_message(msg: WebSocket_Message): bool
%{
connection()->zeek_analyzer()->AnalyzerConfirmation();
if ( websocket_message )
{
zeek::BifEvent::enqueue_websocket_message(connection()->zeek_analyzer(),
connection()->zeek_analyzer()->Conn(),
is_orig(),
${msg.opcode});
}
return true;
%}
function process_header(hdr: WebSocket_FrameHeader): bool
%{
if ( websocket_frame )
{
zeek::BifEvent::enqueue_websocket_frame(connection()->zeek_analyzer(),
connection()->zeek_analyzer()->Conn(),
is_orig(),
${hdr.b.fin},
${hdr.b.reserved},
${hdr.b.opcode},
${hdr.payload_len});
}
return true;
%}
function process_payload_unmask(chunk: WebSocket_FramePayloadUnmask): bool
%{
auto& data = ${chunk.data};
// In-place unmasking if frame payload is masked.
if ( has_mask_ )
{
auto *d = data.data();
for ( int i = 0; i < data.length(); i++ )
d[i] = d[i] ^ mask_[mask_idx_++ % mask_.size()];
}
return true;
%}
function process_payload_close(close: WebSocket_FramePayloadClose): bool
%{
if ( websocket_close )
{
const auto& reason = ${close.reason};
auto reason_val = zeek::make_intrusive<zeek::StringVal>(reason.length(),
reinterpret_cast<const char*>(reason.data()));
zeek::BifEvent::enqueue_websocket_close(connection()->zeek_analyzer(),
connection()->zeek_analyzer()->Conn(),
is_orig(),
${close.status},
reason_val);
}
return true;
%}
function process_empty_close(hdr: WebSocket_FrameHeader): bool
%{
if ( websocket_close )
{
zeek::BifEvent::enqueue_websocket_close(connection()->zeek_analyzer(),
connection()->zeek_analyzer()->Conn(),
is_orig(),
0, /* use placeholder status */
zeek::val_mgr->EmptyString());
}
return true;
%}
function process_payload_chunk(chunk: WebSocket_FramePayloadChunk): bool
%{
auto& data = ${chunk.unmask.data};
if ( websocket_frame_data )
{
auto data_val = zeek::make_intrusive<zeek::StringVal>(data.length(), reinterpret_cast<const char*>(data.data()));
zeek::BifEvent::enqueue_websocket_frame_data(connection()->zeek_analyzer(),
connection()->zeek_analyzer()->Conn(),
is_orig(),
data_val);
}
// Forward text and binary data to downstream analyzers.
if ( ${chunk.hdr.b.opcode} == OPCODE_TEXT|| ${chunk.hdr.b.opcode} == OPCODE_BINARY)
connection()->zeek_analyzer()->ForwardStream(data.length(),
data.data(),
is_orig());
return true;
%}
};
refine typeattr WebSocket_Message += &let {
proc_message = $context.flow.process_message(this);
};
refine typeattr WebSocket_FrameHeader += &let {
proc_header = $context.flow.process_header(this);
};
refine typeattr WebSocket_FramePayloadUnmask += &let {
proc_payload_unmask = $context.flow.process_payload_unmask(this);
};
refine typeattr WebSocket_FramePayloadClose += &let {
proc_payload_close = $context.flow.process_payload_close(this);
};
refine typeattr WebSocket_FramePayloadChunk += &let {
proc_payload_chunk = $context.flow.process_payload_chunk(this);
};

View file

@ -0,0 +1,149 @@
# See the file "COPYING" in the main distribution directory for copyright.
#
# The WebSocket protocol.
#
# https://datatracker.ietf.org/doc/html/rfc6455
enum Opcodes {
OPCODE_CONTINUATION = 0x00,
OPCODE_TEXT = 0x01,
OPCODE_BINARY = 0x02,
OPCODE_CLOSE = 0x08,
OPCODE_PING = 0x09,
OPCODE_PONG = 0x0a,
}
type WebSocket_FrameHeaderFixed(first_frame: bool) = record {
# First frame in message cannot be continuation, following
# frames are only expected to be continuations.
b: uint16 &enforce((first_frame && opcode != 0) || (!first_frame && opcode == 0));
} &let {
fin: bool = (b & 0x8000) ? true : false;
reserved: uint8 = ((b & 0x7000) >> 12);
opcode: uint8 = (b & 0x0f00) >> 8;
has_mask: bool = (b & 0x0080) ? true : false;
payload_len1: uint8 = (b & 0x007f);
rest_header_len: uint64 = (has_mask ? 4 : 0) + (payload_len1 < 126 ? 0 : (payload_len1 == 126 ? 2 : 8));
} &length=2;
type WebSocket_FrameHeader(b: WebSocket_FrameHeaderFixed) = record {
maybe_more_len: case b.payload_len1 of {
126 -> payload_len2: uint16;
127 -> payload_len8: uint64;
default -> short_len: empty;
};
maybe_mask: case b.has_mask of {
true -> mask: bytestring &length=4;
false -> no_mask: empty;
};
} &let {
payload_len: uint64 = b.payload_len1 < 126 ? b.payload_len1 : (b.payload_len1 == 126 ? payload_len2 : payload_len8);
new_frame_payload = $context.flow.new_frame_payload(this);
} &length=b.rest_header_len;
type WebSocket_FramePayloadClose(hdr: WebSocket_FrameHeader) = record {
status: uint16;
reason: bytestring &restofdata;
} &byteorder=bigendian;
type WebSocket_FramePayloadUnmask(hdr: WebSocket_FrameHeader) = record {
data: bytestring &restofdata;
};
type WebSocket_FramePayloadChunk(len: uint64, hdr: WebSocket_FrameHeader) = record {
unmask: WebSocket_FramePayloadUnmask(hdr);
} &let {
consumed_payload = $context.flow.consumed_chunk(len);
close_payload: WebSocket_FramePayloadClose(hdr) withinput unmask.data &length=len &if(hdr.b.opcode == OPCODE_CLOSE);
} &length=len;
type WebSocket_Frame(first_frame: bool, msg: WebSocket_Message) = record {
b: WebSocket_FrameHeaderFixed(first_frame);
hdr: WebSocket_FrameHeader(b);
# This is implementing frame payload chunking so that we do not
# attempt to buffer huge frames and forward data to downstream
# analyzers in chunks.
#
# I tried &chunked and it didn't do anything very useful.
chunks: WebSocket_FramePayloadChunk($context.flow.next_chunk_len(), hdr)[]
&until($context.flow.remaining_frame_payload_len() == 0)
&transient;
} &let {
# If we find a close frame without payload, raise the event here
# as the close won't have been parsed via chunks.
empty_close = $context.flow.process_empty_close(hdr) &if(b.opcode == OPCODE_CLOSE) && hdr.payload_len == 0;
};
type WebSocket_Message = record {
first_frame: WebSocket_Frame(true, this);
optional_more_frames: case first_frame.hdr.b.fin of {
true -> no_more_frames: empty;
false -> more_frames: WebSocket_Frame(false, this)[] &until($element.hdr.b.fin) &transient;
};
} &let {
opcode = first_frame.hdr.b.opcode;
} &byteorder=bigendian;
flow WebSocket_Flow(is_orig: bool) {
flowunit = WebSocket_Message withcontext(connection, this);
%member{
bool has_mask_;
uint64_t mask_idx_;
uint64_t frame_payload_len_;
std::array<uint8_t, 4> mask_;
%}
%init{
has_mask_ = false;
mask_idx_ = 0;
frame_payload_len_ = 0;
%}
function new_frame_payload(hdr: WebSocket_FrameHeader): uint64
%{
if ( frame_payload_len_ > 0 )
connection()->zeek_analyzer()->Weird("websocket_frame_not_consumed");
frame_payload_len_ = ${hdr.payload_len};
has_mask_ = ${hdr.b.has_mask};
mask_idx_ = 0;
if ( has_mask_ ) {
assert(${hdr.mask}.length() == static_cast<int>(mask_.size()));
memcpy(mask_.data(), ${hdr.mask}.data(), mask_.size());
}
return frame_payload_len_;
%}
function remaining_frame_payload_len(): uint64
%{
return frame_payload_len_;
%}
function consumed_chunk(len: uint64): uint64
%{
if ( len > frame_payload_len_ ) {
connection()->zeek_analyzer()->Weird("websocket_frame_consuming_too_much");
len = frame_payload_len_;
}
frame_payload_len_ -= len;
return len;
%}
function next_chunk_len(): uint64
%{
uint64_t len = frame_payload_len_;
// It would be somewhat nicer if we could just consume
// anything still left to consume from the current packet,
// but couldn't figure out if that information can be pulled
// flow buffer.
if ( len > zeek::BifConst::WebSocket::payload_chunk_size )
len = zeek::BifConst::WebSocket::payload_chunk_size;
return len;
%}
};

View file

@ -0,0 +1,24 @@
# See the file "COPYING" in the main distribution directory for copyright.
%include binpac.pac
%include zeek.pac
%extern{
#include <array>
#include "zeek/analyzer/protocol/websocket/consts.bif.h"
#include "zeek/analyzer/protocol/websocket/events.bif.h"
%}
analyzer WebSocket withcontext {
connection: WebSocket_Conn;
flow: WebSocket_Flow;
};
connection WebSocket_Conn(zeek_analyzer: ZeekAnalyzer) {
upflow = WebSocket_Flow(true);
downflow = WebSocket_Flow(false);
};
%include websocket-protocol.pac
%include websocket-analyzer.pac

View file

@ -244,6 +244,10 @@ scripts/base/init-frameworks-and-bifs.zeek
build/scripts/base/bif/plugins/Zeek_TCP.events.bif.zeek
build/scripts/base/bif/plugins/Zeek_TCP.types.bif.zeek
build/scripts/base/bif/plugins/Zeek_TCP.functions.bif.zeek
build/scripts/base/bif/plugins/Zeek_WebSocket.consts.bif.zeek
build/scripts/base/bif/plugins/Zeek_WebSocket.events.bif.zeek
build/scripts/base/bif/plugins/Zeek_WebSocket.functions.bif.zeek
build/scripts/base/bif/plugins/Zeek_WebSocket.types.bif.zeek
build/scripts/base/bif/plugins/Zeek_XMPP.events.bif.zeek
build/scripts/base/bif/plugins/Zeek_ARP.events.bif.zeek
build/scripts/base/bif/plugins/Zeek_UDP.events.bif.zeek

View file

@ -244,6 +244,10 @@ scripts/base/init-frameworks-and-bifs.zeek
build/scripts/base/bif/plugins/Zeek_TCP.events.bif.zeek
build/scripts/base/bif/plugins/Zeek_TCP.types.bif.zeek
build/scripts/base/bif/plugins/Zeek_TCP.functions.bif.zeek
build/scripts/base/bif/plugins/Zeek_WebSocket.consts.bif.zeek
build/scripts/base/bif/plugins/Zeek_WebSocket.events.bif.zeek
build/scripts/base/bif/plugins/Zeek_WebSocket.functions.bif.zeek
build/scripts/base/bif/plugins/Zeek_WebSocket.types.bif.zeek
build/scripts/base/bif/plugins/Zeek_XMPP.events.bif.zeek
build/scripts/base/bif/plugins/Zeek_ARP.events.bif.zeek
build/scripts/base/bif/plugins/Zeek_UDP.events.bif.zeek
@ -465,6 +469,9 @@ scripts/base/init-default.zeek
scripts/base/protocols/syslog/spicy-events.zeek
scripts/base/protocols/syslog/consts.zeek
scripts/base/protocols/syslog/main.zeek
scripts/base/protocols/websocket/__load__.zeek
scripts/base/protocols/websocket/consts.zeek
scripts/base/protocols/websocket/main.zeek
scripts/base/protocols/tunnels/__load__.zeek
scripts/base/protocols/xmpp/__load__.zeek
scripts/base/protocols/xmpp/main.zeek

View file

@ -65,6 +65,7 @@ telemetry_histogram
traceroute
tunnel
unknown_protocols
websocket
weird
weird_stats
x509

View file

@ -884,4 +884,18 @@ connection {
}
* uid: string, log=F, optional=F
* vlan: int, log=F, optional=T
* websocket: record WebSocket::Info, log=F, optional=T
WebSocket::Info {
* client_extensions: vector of string, log=T, optional=T
* client_protocols: vector of string, log=T, optional=T
* host: string, log=T, optional=T
* id: record conn_id, log=T, optional=F
conn_id { ... }
* server_extensions: vector of string, log=T, optional=T
* subprotocol: string, log=T, optional=T
* ts: time, log=T, optional=F
* uid: string, log=T, optional=F
* uri: string, log=T, optional=T
* user_agent: string, log=T, optional=T
}
}

View file

@ -463,6 +463,10 @@
0.000000 MetaHookPost LoadFile(0, ./Zeek_Teredo.functions.bif.zeek, <...>/Zeek_Teredo.functions.bif.zeek) -> -1
0.000000 MetaHookPost LoadFile(0, ./Zeek_UDP.events.bif.zeek, <...>/Zeek_UDP.events.bif.zeek) -> -1
0.000000 MetaHookPost LoadFile(0, ./Zeek_VXLAN.events.bif.zeek, <...>/Zeek_VXLAN.events.bif.zeek) -> -1
0.000000 MetaHookPost LoadFile(0, ./Zeek_WebSocket.consts.bif.zeek, <...>/Zeek_WebSocket.consts.bif.zeek) -> -1
0.000000 MetaHookPost LoadFile(0, ./Zeek_WebSocket.events.bif.zeek, <...>/Zeek_WebSocket.events.bif.zeek) -> -1
0.000000 MetaHookPost LoadFile(0, ./Zeek_WebSocket.functions.bif.zeek, <...>/Zeek_WebSocket.functions.bif.zeek) -> -1
0.000000 MetaHookPost LoadFile(0, ./Zeek_WebSocket.types.bif.zeek, <...>/Zeek_WebSocket.types.bif.zeek) -> -1
0.000000 MetaHookPost LoadFile(0, ./Zeek_X509.events.bif.zeek, <...>/Zeek_X509.events.bif.zeek) -> -1
0.000000 MetaHookPost LoadFile(0, ./Zeek_X509.functions.bif.zeek, <...>/Zeek_X509.functions.bif.zeek) -> -1
0.000000 MetaHookPost LoadFile(0, ./Zeek_X509.ocsp_events.bif.zeek, <...>/Zeek_X509.ocsp_events.bif.zeek) -> -1
@ -752,6 +756,10 @@
0.000000 MetaHookPost LoadFileExtended(0, ./Zeek_Teredo.functions.bif.zeek, <...>/Zeek_Teredo.functions.bif.zeek) -> (-1, <no content>)
0.000000 MetaHookPost LoadFileExtended(0, ./Zeek_UDP.events.bif.zeek, <...>/Zeek_UDP.events.bif.zeek) -> (-1, <no content>)
0.000000 MetaHookPost LoadFileExtended(0, ./Zeek_VXLAN.events.bif.zeek, <...>/Zeek_VXLAN.events.bif.zeek) -> (-1, <no content>)
0.000000 MetaHookPost LoadFileExtended(0, ./Zeek_WebSocket.consts.bif.zeek, <...>/Zeek_WebSocket.consts.bif.zeek) -> (-1, <no content>)
0.000000 MetaHookPost LoadFileExtended(0, ./Zeek_WebSocket.events.bif.zeek, <...>/Zeek_WebSocket.events.bif.zeek) -> (-1, <no content>)
0.000000 MetaHookPost LoadFileExtended(0, ./Zeek_WebSocket.functions.bif.zeek, <...>/Zeek_WebSocket.functions.bif.zeek) -> (-1, <no content>)
0.000000 MetaHookPost LoadFileExtended(0, ./Zeek_WebSocket.types.bif.zeek, <...>/Zeek_WebSocket.types.bif.zeek) -> (-1, <no content>)
0.000000 MetaHookPost LoadFileExtended(0, ./Zeek_X509.events.bif.zeek, <...>/Zeek_X509.events.bif.zeek) -> (-1, <no content>)
0.000000 MetaHookPost LoadFileExtended(0, ./Zeek_X509.functions.bif.zeek, <...>/Zeek_X509.functions.bif.zeek) -> (-1, <no content>)
0.000000 MetaHookPost LoadFileExtended(0, ./Zeek_X509.ocsp_events.bif.zeek, <...>/Zeek_X509.ocsp_events.bif.zeek) -> (-1, <no content>)
@ -1389,6 +1397,10 @@
0.000000 MetaHookPre LoadFile(0, ./Zeek_Teredo.functions.bif.zeek, <...>/Zeek_Teredo.functions.bif.zeek)
0.000000 MetaHookPre LoadFile(0, ./Zeek_UDP.events.bif.zeek, <...>/Zeek_UDP.events.bif.zeek)
0.000000 MetaHookPre LoadFile(0, ./Zeek_VXLAN.events.bif.zeek, <...>/Zeek_VXLAN.events.bif.zeek)
0.000000 MetaHookPre LoadFile(0, ./Zeek_WebSocket.consts.bif.zeek, <...>/Zeek_WebSocket.consts.bif.zeek)
0.000000 MetaHookPre LoadFile(0, ./Zeek_WebSocket.events.bif.zeek, <...>/Zeek_WebSocket.events.bif.zeek)
0.000000 MetaHookPre LoadFile(0, ./Zeek_WebSocket.functions.bif.zeek, <...>/Zeek_WebSocket.functions.bif.zeek)
0.000000 MetaHookPre LoadFile(0, ./Zeek_WebSocket.types.bif.zeek, <...>/Zeek_WebSocket.types.bif.zeek)
0.000000 MetaHookPre LoadFile(0, ./Zeek_X509.events.bif.zeek, <...>/Zeek_X509.events.bif.zeek)
0.000000 MetaHookPre LoadFile(0, ./Zeek_X509.functions.bif.zeek, <...>/Zeek_X509.functions.bif.zeek)
0.000000 MetaHookPre LoadFile(0, ./Zeek_X509.ocsp_events.bif.zeek, <...>/Zeek_X509.ocsp_events.bif.zeek)
@ -1678,6 +1690,10 @@
0.000000 MetaHookPre LoadFileExtended(0, ./Zeek_Teredo.functions.bif.zeek, <...>/Zeek_Teredo.functions.bif.zeek)
0.000000 MetaHookPre LoadFileExtended(0, ./Zeek_UDP.events.bif.zeek, <...>/Zeek_UDP.events.bif.zeek)
0.000000 MetaHookPre LoadFileExtended(0, ./Zeek_VXLAN.events.bif.zeek, <...>/Zeek_VXLAN.events.bif.zeek)
0.000000 MetaHookPre LoadFileExtended(0, ./Zeek_WebSocket.consts.bif.zeek, <...>/Zeek_WebSocket.consts.bif.zeek)
0.000000 MetaHookPre LoadFileExtended(0, ./Zeek_WebSocket.events.bif.zeek, <...>/Zeek_WebSocket.events.bif.zeek)
0.000000 MetaHookPre LoadFileExtended(0, ./Zeek_WebSocket.functions.bif.zeek, <...>/Zeek_WebSocket.functions.bif.zeek)
0.000000 MetaHookPre LoadFileExtended(0, ./Zeek_WebSocket.types.bif.zeek, <...>/Zeek_WebSocket.types.bif.zeek)
0.000000 MetaHookPre LoadFileExtended(0, ./Zeek_X509.events.bif.zeek, <...>/Zeek_X509.events.bif.zeek)
0.000000 MetaHookPre LoadFileExtended(0, ./Zeek_X509.functions.bif.zeek, <...>/Zeek_X509.functions.bif.zeek)
0.000000 MetaHookPre LoadFileExtended(0, ./Zeek_X509.ocsp_events.bif.zeek, <...>/Zeek_X509.ocsp_events.bif.zeek)
@ -2314,6 +2330,10 @@
0.000000 | HookLoadFile ./Zeek_Teredo.functions.bif.zeek <...>/Zeek_Teredo.functions.bif.zeek
0.000000 | HookLoadFile ./Zeek_UDP.events.bif.zeek <...>/Zeek_UDP.events.bif.zeek
0.000000 | HookLoadFile ./Zeek_VXLAN.events.bif.zeek <...>/Zeek_VXLAN.events.bif.zeek
0.000000 | HookLoadFile ./Zeek_WebSocket.consts.bif.zeek <...>/Zeek_WebSocket.consts.bif.zeek
0.000000 | HookLoadFile ./Zeek_WebSocket.events.bif.zeek <...>/Zeek_WebSocket.events.bif.zeek
0.000000 | HookLoadFile ./Zeek_WebSocket.functions.bif.zeek <...>/Zeek_WebSocket.functions.bif.zeek
0.000000 | HookLoadFile ./Zeek_WebSocket.types.bif.zeek <...>/Zeek_WebSocket.types.bif.zeek
0.000000 | HookLoadFile ./Zeek_X509.events.bif.zeek <...>/Zeek_X509.events.bif.zeek
0.000000 | HookLoadFile ./Zeek_X509.functions.bif.zeek <...>/Zeek_X509.functions.bif.zeek
0.000000 | HookLoadFile ./Zeek_X509.ocsp_events.bif.zeek <...>/Zeek_X509.ocsp_events.bif.zeek
@ -2603,6 +2623,10 @@
0.000000 | HookLoadFileExtended ./Zeek_Teredo.functions.bif.zeek <...>/Zeek_Teredo.functions.bif.zeek
0.000000 | HookLoadFileExtended ./Zeek_UDP.events.bif.zeek <...>/Zeek_UDP.events.bif.zeek
0.000000 | HookLoadFileExtended ./Zeek_VXLAN.events.bif.zeek <...>/Zeek_VXLAN.events.bif.zeek
0.000000 | HookLoadFileExtended ./Zeek_WebSocket.consts.bif.zeek <...>/Zeek_WebSocket.consts.bif.zeek
0.000000 | HookLoadFileExtended ./Zeek_WebSocket.events.bif.zeek <...>/Zeek_WebSocket.events.bif.zeek
0.000000 | HookLoadFileExtended ./Zeek_WebSocket.functions.bif.zeek <...>/Zeek_WebSocket.functions.bif.zeek
0.000000 | HookLoadFileExtended ./Zeek_WebSocket.types.bif.zeek <...>/Zeek_WebSocket.types.bif.zeek
0.000000 | HookLoadFileExtended ./Zeek_X509.events.bif.zeek <...>/Zeek_X509.events.bif.zeek
0.000000 | HookLoadFileExtended ./Zeek_X509.functions.bif.zeek <...>/Zeek_X509.functions.bif.zeek
0.000000 | HookLoadFileExtended ./Zeek_X509.ocsp_events.bif.zeek <...>/Zeek_X509.ocsp_events.bif.zeek

View file

@ -7,10 +7,10 @@
#open XXXX-XX-XX-XX-XX-XX
#fields ts fuid uid id.orig_h id.orig_p id.resp_h id.resp_p source depth analyzers mime_type filename duration local_orig is_orig seen_bytes total_bytes missing_bytes overflow_bytes timedout parent_fuid md5 sha1 sha256
#types time string string addr port addr port string count set[string] string string interval bool bool count count count count bool string string string string
XXXXXXXXXX.XXXXXX FgN3AE3of2TRIqaeQe CHhAvVGS1DHFjwGM9 192.168.4.149 60623 74.125.239.129 443 SSL 0 SHA256,X509,SHA1,MD5 application/x-x509-user-cert - 0.000000 F F 1859 - 0 0 F - 7af07aca6d5c6e8e87fe4bb34786edc0 548b9e03bc183d1cd39f93a37985cb3950f8f06f 6bacfa4536150ed996f2b0c05ab6e345a257225f449aeb9d2018ccd88f4ede43
XXXXXXXXXX.XXXXXX Fv2Agc4z5boBOacQi6 CHhAvVGS1DHFjwGM9 192.168.4.149 60623 74.125.239.129 443 SSL 0 SHA256,X509,SHA1,MD5 application/x-x509-ca-cert - 0.000000 F F 1032 - 0 0 F - 9e4ac96474245129d9766700412a1f89 d83c1a7f4d0446bb2081b81a1670f8183451ca24 a047a37fa2d2e118a4f5095fe074d6cfe0e352425a7632bf8659c03919a6c81d
XXXXXXXXXX.XXXXXX Ftmyeg2qgI2V38Dt3g CHhAvVGS1DHFjwGM9 192.168.4.149 60623 74.125.239.129 443 SSL 0 SHA256,X509,SHA1,MD5 application/x-x509-ca-cert - 0.000000 F F 897 - 0 0 F - 2e7db2a31d0e3da4b25f49b9542a2e1a 7359755c6df9a0abc3060bce369564c8ec4542a3 3c35cc963eb004451323d3275d05b353235053490d9cd83729a2faf5e7ca1cc0
XXXXXXXXXX.XXXXXX FUFNf84cduA0IJCp07 ClEkJM2Vm5giqnMf4h 192.168.4.149 60624 74.125.239.129 443 SSL 0 SHA256,X509,SHA1,MD5 application/x-x509-user-cert - 0.000000 F F 1859 - 0 0 F - 7af07aca6d5c6e8e87fe4bb34786edc0 548b9e03bc183d1cd39f93a37985cb3950f8f06f 6bacfa4536150ed996f2b0c05ab6e345a257225f449aeb9d2018ccd88f4ede43
XXXXXXXXXX.XXXXXX F1H4bd2OKGbLPEdHm4 ClEkJM2Vm5giqnMf4h 192.168.4.149 60624 74.125.239.129 443 SSL 0 SHA256,X509,SHA1,MD5 application/x-x509-ca-cert - 0.000000 F F 1032 - 0 0 F - 9e4ac96474245129d9766700412a1f89 d83c1a7f4d0446bb2081b81a1670f8183451ca24 a047a37fa2d2e118a4f5095fe074d6cfe0e352425a7632bf8659c03919a6c81d
XXXXXXXXXX.XXXXXX Fgsbci2jxFXYMOHOhi ClEkJM2Vm5giqnMf4h 192.168.4.149 60624 74.125.239.129 443 SSL 0 SHA256,X509,SHA1,MD5 application/x-x509-ca-cert - 0.000000 F F 897 - 0 0 F - 2e7db2a31d0e3da4b25f49b9542a2e1a 7359755c6df9a0abc3060bce369564c8ec4542a3 3c35cc963eb004451323d3275d05b353235053490d9cd83729a2faf5e7ca1cc0
XXXXXXXXXX.XXXXXX FgN3AE3of2TRIqaeQe CHhAvVGS1DHFjwGM9 192.168.4.149 60623 74.125.239.129 443 SSL 0 X509,SHA256,SHA1,MD5 application/x-x509-user-cert - 0.000000 F F 1859 - 0 0 F - 7af07aca6d5c6e8e87fe4bb34786edc0 548b9e03bc183d1cd39f93a37985cb3950f8f06f 6bacfa4536150ed996f2b0c05ab6e345a257225f449aeb9d2018ccd88f4ede43
XXXXXXXXXX.XXXXXX Fv2Agc4z5boBOacQi6 CHhAvVGS1DHFjwGM9 192.168.4.149 60623 74.125.239.129 443 SSL 0 X509,SHA256,SHA1,MD5 application/x-x509-ca-cert - 0.000000 F F 1032 - 0 0 F - 9e4ac96474245129d9766700412a1f89 d83c1a7f4d0446bb2081b81a1670f8183451ca24 a047a37fa2d2e118a4f5095fe074d6cfe0e352425a7632bf8659c03919a6c81d
XXXXXXXXXX.XXXXXX Ftmyeg2qgI2V38Dt3g CHhAvVGS1DHFjwGM9 192.168.4.149 60623 74.125.239.129 443 SSL 0 X509,SHA256,SHA1,MD5 application/x-x509-ca-cert - 0.000000 F F 897 - 0 0 F - 2e7db2a31d0e3da4b25f49b9542a2e1a 7359755c6df9a0abc3060bce369564c8ec4542a3 3c35cc963eb004451323d3275d05b353235053490d9cd83729a2faf5e7ca1cc0
XXXXXXXXXX.XXXXXX FUFNf84cduA0IJCp07 ClEkJM2Vm5giqnMf4h 192.168.4.149 60624 74.125.239.129 443 SSL 0 X509,SHA256,SHA1,MD5 application/x-x509-user-cert - 0.000000 F F 1859 - 0 0 F - 7af07aca6d5c6e8e87fe4bb34786edc0 548b9e03bc183d1cd39f93a37985cb3950f8f06f 6bacfa4536150ed996f2b0c05ab6e345a257225f449aeb9d2018ccd88f4ede43
XXXXXXXXXX.XXXXXX F1H4bd2OKGbLPEdHm4 ClEkJM2Vm5giqnMf4h 192.168.4.149 60624 74.125.239.129 443 SSL 0 X509,SHA256,SHA1,MD5 application/x-x509-ca-cert - 0.000000 F F 1032 - 0 0 F - 9e4ac96474245129d9766700412a1f89 d83c1a7f4d0446bb2081b81a1670f8183451ca24 a047a37fa2d2e118a4f5095fe074d6cfe0e352425a7632bf8659c03919a6c81d
XXXXXXXXXX.XXXXXX Fgsbci2jxFXYMOHOhi ClEkJM2Vm5giqnMf4h 192.168.4.149 60624 74.125.239.129 443 SSL 0 X509,SHA256,SHA1,MD5 application/x-x509-ca-cert - 0.000000 F F 897 - 0 0 F - 2e7db2a31d0e3da4b25f49b9542a2e1a 7359755c6df9a0abc3060bce369564c8ec4542a3 3c35cc963eb004451323d3275d05b353235053490d9cd83729a2faf5e7ca1cc0
#close XXXX-XX-XX-XX-XX-XX

View file

@ -0,0 +1,3 @@
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
ts uid history service
XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 ShADadfF websocket,http

View file

@ -0,0 +1,11 @@
### 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 websocket
#open XXXX-XX-XX-XX-XX-XX
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p host uri user_agent subprotocol client_protocols server_extensions client_extensions
#types time string addr port addr port string string string string vector[string] vector[string] vector[string]
XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 127.0.0.1 38776 127.0.0.1 27599 localhost:27599 /v1/messages/json Python/3.10 websockets/12.0 - - - permessage-deflate; client_max_window_bits
#close XXXX-XX-XX-XX-XX-XX

View file

@ -0,0 +1,91 @@
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
jupyter-websocket.pcap
websocket_handshake, CHhAvVGS1DHFjwGM9, 7, [ts=XXXXXXXXXX.XXXXXX, uid=CHhAvVGS1DHFjwGM9, id=[orig_h=127.0.0.1, orig_p=40492/tcp, resp_h=127.0.0.1, resp_p=51185/tcp], host=192.168.122.182, uri=/user/christian/api/kernels/f8645ecd-0a76-4bb1-9e6e-cb464276bc69/channels?session_id=deeecee7-efc2-42a1-a7c1-e1c0569436e3, user_agent=Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/118.0, subprotocol=v1.kernel.websocket.jupyter.org, client_protocols=[v1.kernel.websocket.jupyter.org], server_extensions=<uninitialized>, client_extensions=[permessage-deflate]]
websocket_frame, CHhAvVGS1DHFjwGM9, T, fin, T, rsv, 0, opcode, binary, payload_len, 262
websocket_frame_data, CHhAvVGS1DHFjwGM9, T, len, 262, data, \x06\x00\x00\x00\x00\x00\x00\x008\x00\x00\x00\x00\x00\x00\x00=\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x02\x01\x00\x00\x00\x00\x00\x00\x04\x01\x00\x00\x00\x00\x00\x00\x06\x01\x00\x00\x00\x00\x00\x00shell{"date":"2023-09-29T23:25:05.568Z","msg_id":"5af8fd02-14a1-
websocket_message, CHhAvVGS1DHFjwGM9, T, opcode, binary
websocket_frame, CHhAvVGS1DHFjwGM9, F, fin, T, rsv, 0, opcode, binary, payload_len, 539
websocket_frame_data, CHhAvVGS1DHFjwGM9, F, len, 539, data, \x06\x00\x00\x00\x00\x00\x00\x008\x00\x00\x00\x00\x00\x00\x00=\x00\x00\x00\x00\x00\x00\x00\x14\x01\x00\x00\x00\x00\x00\x00\xfe\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x1b\x02\x00\x00\x00\x00\x00\x00iopub{"msg_id": "5accb611-84744090d18c920147a97eb5_25702_7", "ms
websocket_message, CHhAvVGS1DHFjwGM9, F, opcode, binary
websocket_frame, CHhAvVGS1DHFjwGM9, F, fin, T, rsv, 0, opcode, binary, payload_len, 527
websocket_frame_data, CHhAvVGS1DHFjwGM9, F, len, 527, data, \x06\x00\x00\x00\x00\x00\x00\x008\x00\x00\x00\x00\x00\x00\x00=\x00\x00\x00\x00\x00\x00\x00\x14\x01\x00\x00\x00\x00\x00\x00\xf2\x01\x00\x00\x00\x00\x00\x00\xf4\x01\x00\x00\x00\x00\x00\x00\x0f\x02\x00\x00\x00\x00\x00\x00iopub{"msg_id": "5accb611-84744090d18c920147a97eb5_25702_9", "ms
websocket_message, CHhAvVGS1DHFjwGM9, F, opcode, binary
websocket_frame, CHhAvVGS1DHFjwGM9, F, fin, T, rsv, 0, opcode, binary, payload_len, 1647
websocket_frame_data, CHhAvVGS1DHFjwGM9, F, len, 1647, data, \x06\x00\x00\x00\x00\x00\x00\x008\x00\x00\x00\x00\x00\x00\x00=\x00\x00\x00\x00\x00\x00\x00 \x01\x00\x00\x00\x00\x00\x00\xf1\x01\x00\x00\x00\x00\x00\x00\xf3\x01\x00\x00\x00\x00\x00\x00o\x06\x00\x00\x00\x00\x00\x00shell{"msg_id": "5accb611-84744090d18c920147a97eb5_25702_14", "m
websocket_message, CHhAvVGS1DHFjwGM9, F, opcode, binary
websocket_frame, CHhAvVGS1DHFjwGM9, F, fin, T, rsv, 0, opcode, binary, payload_len, 540
websocket_frame_data, CHhAvVGS1DHFjwGM9, F, len, 540, data, \x06\x00\x00\x00\x00\x00\x00\x008\x00\x00\x00\x00\x00\x00\x00=\x00\x00\x00\x00\x00\x00\x00\x15\x01\x00\x00\x00\x00\x00\x00\xff\x01\x00\x00\x00\x00\x00\x00\x01\x02\x00\x00\x00\x00\x00\x00\x1c\x02\x00\x00\x00\x00\x00\x00iopub{"msg_id": "5accb611-84744090d18c920147a97eb5_25702_10", "m
websocket_message, CHhAvVGS1DHFjwGM9, F, opcode, binary
websocket_frame, CHhAvVGS1DHFjwGM9, F, fin, T, rsv, 0, opcode, binary, payload_len, 540
websocket_frame_data, CHhAvVGS1DHFjwGM9, F, len, 540, data, \x06\x00\x00\x00\x00\x00\x00\x008\x00\x00\x00\x00\x00\x00\x00=\x00\x00\x00\x00\x00\x00\x00\x15\x01\x00\x00\x00\x00\x00\x00\xff\x01\x00\x00\x00\x00\x00\x00\x01\x02\x00\x00\x00\x00\x00\x00\x1c\x02\x00\x00\x00\x00\x00\x00iopub{"msg_id": "5accb611-84744090d18c920147a97eb5_25702_12", "m
websocket_message, CHhAvVGS1DHFjwGM9, F, opcode, binary
websocket_frame, CHhAvVGS1DHFjwGM9, F, fin, T, rsv, 0, opcode, binary, payload_len, 515
websocket_frame_data, CHhAvVGS1DHFjwGM9, F, len, 515, data, \x06\x00\x00\x00\x00\x00\x00\x008\x00\x00\x00\x00\x00\x00\x00=\x00\x00\x00\x00\x00\x00\x00\x15\x01\x00\x00\x00\x00\x00\x00\xe6\x01\x00\x00\x00\x00\x00\x00\xe8\x01\x00\x00\x00\x00\x00\x00\x03\x02\x00\x00\x00\x00\x00\x00iopub{"msg_id": "5accb611-84744090d18c920147a97eb5_25702_13", "m
websocket_message, CHhAvVGS1DHFjwGM9, F, opcode, binary
websocket_frame, CHhAvVGS1DHFjwGM9, F, fin, T, rsv, 0, opcode, binary, payload_len, 515
websocket_frame_data, CHhAvVGS1DHFjwGM9, F, len, 515, data, \x06\x00\x00\x00\x00\x00\x00\x008\x00\x00\x00\x00\x00\x00\x00=\x00\x00\x00\x00\x00\x00\x00\x15\x01\x00\x00\x00\x00\x00\x00\xe6\x01\x00\x00\x00\x00\x00\x00\xe8\x01\x00\x00\x00\x00\x00\x00\x03\x02\x00\x00\x00\x00\x00\x00iopub{"msg_id": "5accb611-84744090d18c920147a97eb5_25702_15", "m
websocket_message, CHhAvVGS1DHFjwGM9, F, opcode, binary
websocket_frame, CHhAvVGS1DHFjwGM9, F, fin, T, rsv, 0, opcode, binary, payload_len, 540
websocket_frame_data, CHhAvVGS1DHFjwGM9, F, len, 540, data, \x06\x00\x00\x00\x00\x00\x00\x008\x00\x00\x00\x00\x00\x00\x00=\x00\x00\x00\x00\x00\x00\x00\x15\x01\x00\x00\x00\x00\x00\x00\xff\x01\x00\x00\x00\x00\x00\x00\x01\x02\x00\x00\x00\x00\x00\x00\x1c\x02\x00\x00\x00\x00\x00\x00iopub{"msg_id": "5accb611-84744090d18c920147a97eb5_25702_16", "m
websocket_message, CHhAvVGS1DHFjwGM9, F, opcode, binary
websocket_frame, CHhAvVGS1DHFjwGM9, F, fin, T, rsv, 0, opcode, binary, payload_len, 540
websocket_frame_data, CHhAvVGS1DHFjwGM9, F, len, 540, data, \x06\x00\x00\x00\x00\x00\x00\x008\x00\x00\x00\x00\x00\x00\x00=\x00\x00\x00\x00\x00\x00\x00\x15\x01\x00\x00\x00\x00\x00\x00\xff\x01\x00\x00\x00\x00\x00\x00\x01\x02\x00\x00\x00\x00\x00\x00\x1c\x02\x00\x00\x00\x00\x00\x00iopub{"msg_id": "5accb611-84744090d18c920147a97eb5_25702_18", "m
websocket_message, CHhAvVGS1DHFjwGM9, F, opcode, binary
websocket_frame, CHhAvVGS1DHFjwGM9, F, fin, T, rsv, 0, opcode, binary, payload_len, 540
websocket_frame_data, CHhAvVGS1DHFjwGM9, F, len, 540, data, \x06\x00\x00\x00\x00\x00\x00\x008\x00\x00\x00\x00\x00\x00\x00=\x00\x00\x00\x00\x00\x00\x00\x15\x01\x00\x00\x00\x00\x00\x00\xff\x01\x00\x00\x00\x00\x00\x00\x01\x02\x00\x00\x00\x00\x00\x00\x1c\x02\x00\x00\x00\x00\x00\x00iopub{"msg_id": "5accb611-84744090d18c920147a97eb5_25702_20", "m
websocket_message, CHhAvVGS1DHFjwGM9, F, opcode, binary
websocket_frame, CHhAvVGS1DHFjwGM9, F, fin, T, rsv, 0, opcode, binary, payload_len, 540
websocket_frame_data, CHhAvVGS1DHFjwGM9, F, len, 540, data, \x06\x00\x00\x00\x00\x00\x00\x008\x00\x00\x00\x00\x00\x00\x00=\x00\x00\x00\x00\x00\x00\x00\x15\x01\x00\x00\x00\x00\x00\x00\xff\x01\x00\x00\x00\x00\x00\x00\x01\x02\x00\x00\x00\x00\x00\x00\x1c\x02\x00\x00\x00\x00\x00\x00iopub{"msg_id": "5accb611-84744090d18c920147a97eb5_25702_21", "m
websocket_message, CHhAvVGS1DHFjwGM9, F, opcode, binary
websocket_frame, CHhAvVGS1DHFjwGM9, T, fin, T, rsv, 0, opcode, close, payload_len, 0
websocket_close, CHhAvVGS1DHFjwGM9, T, status, 0, reason,
websocket_message, CHhAvVGS1DHFjwGM9, T, opcode, close
websocket_frame, CHhAvVGS1DHFjwGM9, F, fin, T, rsv, 0, opcode, close, payload_len, 0
websocket_close, CHhAvVGS1DHFjwGM9, F, status, 0, reason,
websocket_message, CHhAvVGS1DHFjwGM9, F, opcode, close
wstunnel-http.pcap
websocket_handshake, CHhAvVGS1DHFjwGM9, 7, [ts=XXXXXXXXXX.XXXXXX, uid=CHhAvVGS1DHFjwGM9, id=[orig_h=127.0.0.1, orig_p=51102/tcp, resp_h=127.0.0.1, resp_p=8888/tcp], host=localhost:8888, uri=/v1/events, user_agent=<uninitialized>, subprotocol=v1, client_protocols=[v1, authorization.bearer.eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6IjAxOGNmZWFiLWY5OWQtNzBmNy05NmFmLTBlOGJhNjk2YTFmNiIsInAiOiJUY3AiLCJyIjoiemVlay5vcmciLCJycCI6ODB9.FsquetBp_jsIDzBslWyyTPlS2hcMprVuWmbT2r57N0A], server_extensions=<uninitialized>, client_extensions=<uninitialized>]
websocket_frame, CHhAvVGS1DHFjwGM9, T, fin, T, rsv, 0, opcode, binary, payload_len, 72
websocket_frame_data, CHhAvVGS1DHFjwGM9, T, len, 72, data, GET / HTTP/1.1\x0d\x0aHost: zeek.org\x0d\x0aUser-Agent: curl/7.81.0\x0d\x0aAccept: */*\x0d\x0a\x0d\x0a
websocket_message, CHhAvVGS1DHFjwGM9, T, opcode, binary
websocket_frame, CHhAvVGS1DHFjwGM9, F, fin, T, rsv, 0, opcode, binary, payload_len, 409
websocket_frame_data, CHhAvVGS1DHFjwGM9, F, len, 409, data, HTTP/1.1 301 Moved Permanently\x0d\x0aServer: nginx\x0d\x0aDate: Fri, 12 Jan 2024 17:15:32 GMT\x0d\x0aContent-Type: text/html\x0d\x0aContent-Len
websocket_message, CHhAvVGS1DHFjwGM9, F, opcode, binary
websocket_frame, CHhAvVGS1DHFjwGM9, T, fin, T, rsv, 0, opcode, close, payload_len, 2
websocket_close, CHhAvVGS1DHFjwGM9, T, status, 1000, reason,
websocket_frame_data, CHhAvVGS1DHFjwGM9, T, len, 2, data, \x03\xe8
websocket_message, CHhAvVGS1DHFjwGM9, T, opcode, close
websocket_frame, CHhAvVGS1DHFjwGM9, F, fin, T, rsv, 0, opcode, close, payload_len, 2
websocket_close, CHhAvVGS1DHFjwGM9, F, status, 1000, reason,
websocket_frame_data, CHhAvVGS1DHFjwGM9, F, len, 2, data, \x03\xe8
websocket_message, CHhAvVGS1DHFjwGM9, F, opcode, close
broker-websocket.pcap
websocket_handshake, CHhAvVGS1DHFjwGM9, 7, [ts=XXXXXXXXXX.XXXXXX, uid=CHhAvVGS1DHFjwGM9, id=[orig_h=127.0.0.1, orig_p=38776/tcp, resp_h=127.0.0.1, resp_p=27599/tcp], host=localhost:27599, uri=/v1/messages/json, user_agent=Python/3.10 websockets/12.0, subprotocol=<uninitialized>, client_protocols=<uninitialized>, server_extensions=<uninitialized>, client_extensions=[permessage-deflate; client_max_window_bits]]
websocket_frame, CHhAvVGS1DHFjwGM9, T, fin, T, rsv, 0, opcode, text, payload_len, 24
websocket_frame_data, CHhAvVGS1DHFjwGM9, T, len, 24, data, ["/zeek/event/my_topic"]
websocket_message, CHhAvVGS1DHFjwGM9, T, opcode, text
websocket_frame, CHhAvVGS1DHFjwGM9, F, fin, T, rsv, 0, opcode, text, payload_len, 91
websocket_frame_data, CHhAvVGS1DHFjwGM9, F, len, 91, data, {"type": "ack", "endpoint": "cfc03c41-7983-5fe2-b22e-6894100e6305", "version": "2.8.0-dev"}
websocket_message, CHhAvVGS1DHFjwGM9, F, opcode, text
websocket_frame, CHhAvVGS1DHFjwGM9, F, fin, T, rsv, 0, opcode, text, payload_len, 533
websocket_frame_data, CHhAvVGS1DHFjwGM9, F, len, 533, data, {"type": "data-message", "topic": "/zeek/event/my_topic", "@data-type": "vector", "data": [{"@data-type": "count", "data
websocket_message, CHhAvVGS1DHFjwGM9, F, opcode, text
websocket_frame, CHhAvVGS1DHFjwGM9, T, fin, T, rsv, 0, opcode, text, payload_len, 361
websocket_frame_data, CHhAvVGS1DHFjwGM9, T, len, 361, data, {"type": "data-message", "topic": "/zeek/event/my_topic", "@data-type": "vector", "data": [{"@data-type": "count", "data
websocket_message, CHhAvVGS1DHFjwGM9, T, opcode, text
websocket_frame, CHhAvVGS1DHFjwGM9, F, fin, T, rsv, 0, opcode, text, payload_len, 533
websocket_frame_data, CHhAvVGS1DHFjwGM9, F, len, 533, data, {"type": "data-message", "topic": "/zeek/event/my_topic", "@data-type": "vector", "data": [{"@data-type": "count", "data
websocket_message, CHhAvVGS1DHFjwGM9, F, opcode, text
websocket_frame, CHhAvVGS1DHFjwGM9, T, fin, T, rsv, 0, opcode, text, payload_len, 361
websocket_frame_data, CHhAvVGS1DHFjwGM9, T, len, 361, data, {"type": "data-message", "topic": "/zeek/event/my_topic", "@data-type": "vector", "data": [{"@data-type": "count", "data
websocket_message, CHhAvVGS1DHFjwGM9, T, opcode, text
websocket_frame, CHhAvVGS1DHFjwGM9, F, fin, T, rsv, 0, opcode, text, payload_len, 533
websocket_frame_data, CHhAvVGS1DHFjwGM9, F, len, 533, data, {"type": "data-message", "topic": "/zeek/event/my_topic", "@data-type": "vector", "data": [{"@data-type": "count", "data
websocket_message, CHhAvVGS1DHFjwGM9, F, opcode, text
websocket_frame, CHhAvVGS1DHFjwGM9, T, fin, T, rsv, 0, opcode, text, payload_len, 361
websocket_frame_data, CHhAvVGS1DHFjwGM9, T, len, 361, data, {"type": "data-message", "topic": "/zeek/event/my_topic", "@data-type": "vector", "data": [{"@data-type": "count", "data
websocket_message, CHhAvVGS1DHFjwGM9, T, opcode, text
websocket_frame, CHhAvVGS1DHFjwGM9, T, fin, T, rsv, 0, opcode, close, payload_len, 2
websocket_close, CHhAvVGS1DHFjwGM9, T, status, 1000, reason,
websocket_frame_data, CHhAvVGS1DHFjwGM9, T, len, 2, data, \x03\xe8
websocket_message, CHhAvVGS1DHFjwGM9, T, opcode, close

View file

@ -0,0 +1,3 @@
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
ts uid history service
XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 ShADadfF websocket,http

View file

@ -0,0 +1,11 @@
### 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 websocket
#open XXXX-XX-XX-XX-XX-XX
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p host uri user_agent subprotocol client_protocols server_extensions client_extensions
#types time string addr port addr port string string string string vector[string] vector[string] vector[string]
XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 127.0.0.1 40492 127.0.0.1 51185 192.168.122.182 /user/christian/api/kernels/f8645ecd-0a76-4bb1-9e6e-cb464276bc69/channels?session_id=deeecee7-efc2-42a1-a7c1-e1c0569436e3 Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/118.0 v1.kernel.websocket.jupyter.org v1.kernel.websocket.jupyter.org - permessage-deflate
#close XXXX-XX-XX-XX-XX-XX

View file

@ -0,0 +1,3 @@
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
ts uid history service
XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 ShADadFR websocket,http

View file

@ -0,0 +1,4 @@
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
ts uid host uri status_code user_agent
XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 localhost:8888 /v1/events 301 -
XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 zeek.org / - curl/7.81.0

View file

@ -0,0 +1,11 @@
### 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 websocket
#open XXXX-XX-XX-XX-XX-XX
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p host uri user_agent subprotocol client_protocols server_extensions client_extensions
#types time string addr port addr port string string string string vector[string] vector[string] vector[string]
XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 127.0.0.1 51102 127.0.0.1 8888 localhost:8888 /v1/events - v1 v1,authorization.bearer.eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6IjAxOGNmZWFiLWY5OWQtNzBmNy05NmFmLTBlOGJhNjk2YTFmNiIsInAiOiJUY3AiLCJyIjoiemVlay5vcmciLCJycCI6ODB9.FsquetBp_jsIDzBslWyyTPlS2hcMprVuWmbT2r57N0A - -
#close XXXX-XX-XX-XX-XX-XX

View file

@ -0,0 +1,3 @@
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
ts uid history service
XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 ShADadFR websocket,ssl,http

View file

@ -0,0 +1,3 @@
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
ts uid version server_name ssl_history
XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 TLSv13 zeek.org CsiI

View file

@ -0,0 +1,11 @@
### 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 websocket
#open XXXX-XX-XX-XX-XX-XX
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p host uri user_agent subprotocol client_protocols server_extensions client_extensions
#types time string addr port addr port string string string string vector[string] vector[string] vector[string]
XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 127.0.0.1 39992 127.0.0.1 8888 localhost:8888 /v1/events - v1 v1,authorization.bearer.eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6IjAxOGQwNTY1LTlmZTItNzFkZS1iNjRlLTU5MzhmZTI0ZmIyZCIsInAiOiJUY3AiLCJyIjoiMTkyLjAuNzguMTUwIiwicnAiOjQ0M30.xyDNRR4kK4fQSGfEyGzuUINn0xBVltxrFVBieMlqwEI - -
#close XXXX-XX-XX-XX-XX-XX

View file

@ -0,0 +1,4 @@
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
ts uid history service
XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 ShADadR websocket,http
XXXXXXXXXX.XXXXXX ClEkJM2Vm5giqnMf4h ShADadR websocket,http

View file

@ -0,0 +1,12 @@
### 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 websocket
#open XXXX-XX-XX-XX-XX-XX
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p host uri user_agent subprotocol client_protocols server_extensions client_extensions
#types time string addr port addr port string string string string vector[string] vector[string] vector[string]
XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 127.0.0.1 42906 127.0.0.1 8888 localhost:8888 /v1/events - v1 v1,authorization.bearer.eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6IjAxOGQwNTVkLTQ5OTgtNzI5Zi04Yjg2LTMwZTBiZWEyZGE4ZiIsInAiOiJUY3AiLCJyIjoiMTk1LjIwMS4xNDguMjA5IiwicnAiOjIyfQ.jjTNJL12tQbAuhTB9p_geFXRkEHkxcvOS6zf76qDklQ - -
XXXXXXXXXX.XXXXXX ClEkJM2Vm5giqnMf4h 127.0.0.1 46796 127.0.0.1 8888 localhost:8888 /v1/events - v1 v1,authorization.bearer.eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6IjAxOGQwNTVkLTc4MWYtNzNiYi1hZDkwLTEzNjA5NzRjY2JmMyIsInAiOiJUY3AiLCJyIjoiMTk1LjIwMS4xNDguMjA5IiwicnAiOjIyfQ.2HQ4uC23p_OYIXnQWeSZCqdA3jc_lVVH7-T5xZDPrz4 - -
#close XXXX-XX-XX-XX-XX-XX

View file

@ -0,0 +1,4 @@
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
ts uid history service
XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 ShADadR websocket,ssh,http
XXXXXXXXXX.XXXXXX ClEkJM2Vm5giqnMf4h ShADadR websocket,ssh,http

View file

@ -0,0 +1,4 @@
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
ts uid client server auth_success auth_attempts kex_alg host_key_alg
XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.6 SSH-2.0-OpenSSH_8.2p1 Ubuntu-4ubuntu0.5 F 4 curve25519-sha256 ssh-ed25519
XXXXXXXXXX.XXXXXX ClEkJM2Vm5giqnMf4h SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.6 SSH-2.0-OpenSSH_8.2p1 Ubuntu-4ubuntu0.5 T 5 curve25519-sha256 ssh-ed25519

View file

@ -0,0 +1,12 @@
### 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 websocket
#open XXXX-XX-XX-XX-XX-XX
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p host uri user_agent subprotocol client_protocols server_extensions client_extensions
#types time string addr port addr port string string string string vector[string] vector[string] vector[string]
XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 127.0.0.1 42906 127.0.0.1 8888 localhost:8888 /v1/events - v1 v1,authorization.bearer.eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6IjAxOGQwNTVkLTQ5OTgtNzI5Zi04Yjg2LTMwZTBiZWEyZGE4ZiIsInAiOiJUY3AiLCJyIjoiMTk1LjIwMS4xNDguMjA5IiwicnAiOjIyfQ.jjTNJL12tQbAuhTB9p_geFXRkEHkxcvOS6zf76qDklQ - -
XXXXXXXXXX.XXXXXX ClEkJM2Vm5giqnMf4h 127.0.0.1 46796 127.0.0.1 8888 localhost:8888 /v1/events - v1 v1,authorization.bearer.eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6IjAxOGQwNTVkLTc4MWYtNzNiYi1hZDkwLTEzNjA5NzRjY2JmMyIsInAiOiJUY3AiLCJyIjoiMTk1LjIwMS4xNDguMjA5IiwicnAiOjIyfQ.2HQ4uC23p_OYIXnQWeSZCqdA3jc_lVVH7-T5xZDPrz4 - -
#close XXXX-XX-XX-XX-XX-XX

View file

@ -0,0 +1,4 @@
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
ts uid history service
XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 ShADadR websocket,ssh,http
XXXXXXXXXX.XXXXXX ClEkJM2Vm5giqnMf4h ShADadR websocket,ssh,http

View file

@ -0,0 +1,4 @@
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
ts uid client server auth_success auth_attempts kex_alg host_key_alg
XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.6 SSH-2.0-OpenSSH_8.2p1 Ubuntu-4ubuntu0.5 F 4 curve25519-sha256 ssh-ed25519
XXXXXXXXXX.XXXXXX ClEkJM2Vm5giqnMf4h SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.6 SSH-2.0-OpenSSH_8.2p1 Ubuntu-4ubuntu0.5 T 5 curve25519-sha256 ssh-ed25519

View file

@ -0,0 +1,12 @@
### 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 websocket
#open XXXX-XX-XX-XX-XX-XX
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p host uri user_agent subprotocol client_protocols server_extensions client_extensions
#types time string addr port addr port string string string string vector[string] vector[string] vector[string]
XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 127.0.0.1 42906 127.0.0.1 8888 localhost:8888 /v1/events - v1 v1,authorization.bearer.eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6IjAxOGQwNTVkLTQ5OTgtNzI5Zi04Yjg2LTMwZTBiZWEyZGE4ZiIsInAiOiJUY3AiLCJyIjoiMTk1LjIwMS4xNDguMjA5IiwicnAiOjIyfQ.jjTNJL12tQbAuhTB9p_geFXRkEHkxcvOS6zf76qDklQ - -
XXXXXXXXXX.XXXXXX ClEkJM2Vm5giqnMf4h 127.0.0.1 46796 127.0.0.1 8888 localhost:8888 /v1/events - v1 v1,authorization.bearer.eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6IjAxOGQwNTVkLTc4MWYtNzNiYi1hZDkwLTEzNjA5NzRjY2JmMyIsInAiOiJUY3AiLCJyIjoiMTk1LjIwMS4xNDguMjA5IiwicnAiOjIyfQ.2HQ4uC23p_OYIXnQWeSZCqdA3jc_lVVH7-T5xZDPrz4 - -
#close XXXX-XX-XX-XX-XX-XX

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,13 @@
# @TEST-DOC: Test Broker WebSocket traffic.
#
# @TEST-EXEC: zeek -b -r $TRACES/websocket/broker-websocket.pcap %INPUT
#
# @TEST-EXEC: zeek-cut -m ts uid history service < conn.log > conn.log.cut
# @TEST-EXEC: btest-diff conn.log.cut
# @TEST-EXEC: btest-diff websocket.log
# @TEST-EXEC: test ! -f analyzer.log
# @TEST-EXEC: test ! -f weird.log
@load base/protocols/conn
@load base/protocols/websocket

View file

@ -0,0 +1,38 @@
# @TEST-DOC: Test WebSocket events.
#
# @TEST-EXEC: echo "jupyter-websocket.pcap" >>out
# @TEST-EXEC: zeek -b -r $TRACES/websocket/jupyter-websocket.pcap %INPUT >>out
# @TEST-EXEC: echo "wstunnel-http.pcap" >>out
# @TEST-EXEC: zeek -b -r $TRACES/websocket/wstunnel-http.pcap %INPUT >>out
# @TEST-EXEC: echo "broker-websocket.pcap" >>out
# @TEST-EXEC: zeek -b -r $TRACES//websocket/broker-websocket.pcap %INPUT >>out
# @TEST-EXEC: btest-diff out
# @TEST-EXEC: test ! -f analyzer.log
# @TEST-EXEC: test ! -f weird.log
@load base/protocols/websocket
event websocket_handshake(c: connection, aid: count)
{
print "websocket_handshake", c$uid, aid, c$websocket;
}
event websocket_message(c: connection, is_orig: bool, opcode: count)
{
print "websocket_message", c$uid, is_orig, "opcode", WebSocket::opcodes[opcode];
}
event websocket_frame(c: connection, is_orig: bool, fin: bool, rsv: count, opcode: count, payload_len: count)
{
print "websocket_frame", c$uid, is_orig, "fin", fin, "rsv", rsv, "opcode", WebSocket::opcodes[opcode], "payload_len", payload_len;
}
event websocket_frame_data(c: connection, is_orig: bool, data: string)
{
print "websocket_frame_data", c$uid, is_orig, "len", |data|, "data", data[:120];
}
event websocket_close(c: connection, is_orig: bool, status: count, reason: string)
{
print "websocket_close", c$uid, is_orig, "status", status, "reason", reason;
}

View file

@ -0,0 +1,13 @@
# @TEST-DOC: Testing Jupyter WebSocket traffic.
#
# @TEST-EXEC: zeek -b -r $TRACES/websocket/jupyter-websocket.pcap %INPUT
#
# @TEST-EXEC: zeek-cut -m ts uid history service < conn.log > conn.log.cut
#
# @TEST-EXEC: btest-diff conn.log.cut
# @TEST-EXEC: btest-diff websocket.log
# @TEST-EXEC: test ! -f analyzer.log
# @TEST-EXEC: test ! -f weird.log
@load base/protocols/conn
@load base/protocols/websocket

View file

@ -0,0 +1,16 @@
# @TEST-DOC: Test HTTP connection tunneled within WebSocket using wstunnel. Seems something in the HTTP scripts gets confused :-/
#
# @TEST-EXEC: zeek -b -r $TRACES/websocket/wstunnel-http.pcap %INPUT
#
# @TEST-EXEC: zeek-cut -m ts uid history service < conn.log > conn.log.cut
# @TEST-EXEC: zeek-cut -m ts uid host uri status_code user_agent < http.log > http.log.cut
# @TEST-EXEC: btest-diff conn.log.cut
# @TEST-EXEC: btest-diff http.log.cut
# @TEST-EXEC: btest-diff websocket.log
# @TEST-EXEC: test ! -f analyzer.log
# @TEST-EXEC: test ! -f weird.log
@load base/protocols/conn
@load base/protocols/ssh
@load base/protocols/websocket

View file

@ -0,0 +1,16 @@
# @TEST-DOC: Test SSH connection tunneled within WebSocket using wstunnel.
#
# @TEST-EXEC: zeek -b -r $TRACES/websocket/wstunnel-https.pcap %INPUT
#
# @TEST-EXEC: zeek-cut -m ts uid history service < conn.log > conn.log.cut
# @TEST-EXEC: zeek-cut -m ts uid version server_name ssl_history < ssl.log > ssl.log.cut
# @TEST-EXEC: btest-diff conn.log.cut
# @TEST-EXEC: btest-diff ssl.log.cut
# @TEST-EXEC: btest-diff websocket.log
# @TEST-EXEC: test ! -f analyzer.log
# @TEST-EXEC: test ! -f weird.log
@load base/protocols/conn
@load base/protocols/ssl
@load base/protocols/websocket

View file

@ -0,0 +1,21 @@
# @TEST-DOC: Test SSH connection tunneled within WebSocket using wstunnel, attaches HTTP analyzer instead of SSH.
#
# @TEST-EXEC: zeek -b -r $TRACES/websocket/wstunnel-ssh.pcap %INPUT
#
# @TEST-EXEC: zeek-cut -m ts uid history service < conn.log > conn.log.cut
# @TEST-EXEC: btest-diff conn.log.cut
# @TEST-EXEC: btest-diff websocket.log
# @TEST-EXEC: test ! -f ssh.log
# @TEST-EXEC: test ! -f analyzer.log
@load base/protocols/conn
@load base/protocols/http
@load base/protocols/ssh
@load base/protocols/websocket
hook WebSocket::configure_analyzer(c: connection, aid: count, config: WebSocket::AnalyzerConfig)
{
print "WebSocket::configure_analyzer", c$uid, aid;
config$analyzer = Analyzer::ANALYZER_HTTP; # this is obviously wrong :-)
}

View file

@ -0,0 +1,22 @@
# @TEST-DOC: Test SSH connection tunneled within WebSocket using wstunnel, configure SSH analyzer via hook explicitly.
#
# @TEST-EXEC: zeek -b -r $TRACES/websocket/wstunnel-ssh.pcap %INPUT
#
# @TEST-EXEC: zeek-cut -m ts uid history service < conn.log > conn.log.cut
# @TEST-EXEC: zeek-cut -m ts uid client server auth_success auth_attempts kex_alg host_key_alg < ssh.log > ssh.log.cut
# @TEST-EXEC: btest-diff conn.log.cut
# @TEST-EXEC: btest-diff ssh.log.cut
# @TEST-EXEC: btest-diff websocket.log
# @TEST-EXEC: test ! -f analyzer.log
# @TEST-EXEC: test ! -f weird.log
@load base/protocols/conn
@load base/protocols/ssh
@load base/protocols/websocket
hook WebSocket::configure_analyzer(c: connection, aid: count, config: WebSocket::AnalyzerConfig)
{
print "WebSocket::configure_analyzer", c$uid, aid;
config$analyzer = Analyzer::ANALYZER_SSH;
}

View file

@ -0,0 +1,16 @@
# @TEST-DOC: Test SSH connection tunneled within WebSocket using wstunnel.
#
# @TEST-EXEC: zeek -b -r $TRACES/websocket/wstunnel-ssh.pcap %INPUT
#
# @TEST-EXEC: zeek-cut -m ts uid history service < conn.log > conn.log.cut
# @TEST-EXEC: zeek-cut -m ts uid client server auth_success auth_attempts kex_alg host_key_alg < ssh.log > ssh.log.cut
# @TEST-EXEC: btest-diff conn.log.cut
# @TEST-EXEC: btest-diff ssh.log.cut
# @TEST-EXEC: btest-diff websocket.log
# @TEST-EXEC: test ! -f analyzer.log
# @TEST-EXEC: test ! -f weird.log
@load base/protocols/conn
@load base/protocols/ssh
@load base/protocols/websocket