mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 14:48:21 +00:00
Updates for the SOCKS analyzer.
- Now supports SOCKSv5 in the analyzer and the DPD sigs. - Reworked the core events. - Tests. - A SOCKS log!
This commit is contained in:
parent
c30c0d5ff2
commit
896f252a31
16 changed files with 411 additions and 47 deletions
|
@ -162,33 +162,48 @@ signature dpd_teredo {
|
||||||
enable "teredo"
|
enable "teredo"
|
||||||
}
|
}
|
||||||
|
|
||||||
signature dpd_socks_client {
|
signature dpd_socks4_client {
|
||||||
ip-proto == tcp
|
ip-proto == tcp
|
||||||
# '32' is a rather arbitrary max length for the user name.
|
# '32' is a rather arbitrary max length for the user name.
|
||||||
payload /^\x04[\x01\x02].{0,32}\x00/
|
payload /^\x04[\x01\x02].{0,32}\x00/
|
||||||
tcp-state originator
|
tcp-state originator
|
||||||
}
|
}
|
||||||
|
|
||||||
signature dpd_socks_server {
|
signature dpd_socks4_server {
|
||||||
ip-proto == tcp
|
ip-proto == tcp
|
||||||
requires-reverse-signature dpd_socks_client
|
requires-reverse-signature dpd_socks4_client
|
||||||
payload /^\x00[\x5a\x5b\x5c\x5d]/
|
payload /^\x00[\x5a\x5b\x5c\x5d]/
|
||||||
tcp-state responder
|
tcp-state responder
|
||||||
enable "socks"
|
enable "socks"
|
||||||
}
|
}
|
||||||
|
|
||||||
signature dpd_socks_reverse_client {
|
signature dpd_socks4_reverse_client {
|
||||||
ip-proto == tcp
|
ip-proto == tcp
|
||||||
# '32' is a rather arbitrary max length for the user name.
|
# '32' is a rather arbitrary max length for the user name.
|
||||||
payload /^\x04[\x01\x02].{0,32}\x00/
|
payload /^\x04[\x01\x02].{0,32}\x00/
|
||||||
tcp-state responder
|
tcp-state responder
|
||||||
}
|
}
|
||||||
|
|
||||||
signature dpd_socks_reverse_server {
|
signature dpd_socks4_reverse_server {
|
||||||
ip-proto == tcp
|
ip-proto == tcp
|
||||||
requires-reverse-signature dpd_socks_client
|
requires-reverse-signature dpd_socks4_reverse_client
|
||||||
payload /^\x00[\x5a\x5b\x5c\x5d]/
|
payload /^\x00[\x5a\x5b\x5c\x5d]/
|
||||||
tcp-state originator
|
tcp-state originator
|
||||||
enable "socks"
|
enable "socks"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
signature dpd_socks5_client {
|
||||||
|
ip-proto == tcp
|
||||||
|
payload /^\x05/
|
||||||
|
tcp-state originator
|
||||||
|
}
|
||||||
|
|
||||||
|
signature dpd_socks5_server {
|
||||||
|
ip-proto == tcp
|
||||||
|
requires-reverse-signature dpd_socks5_client
|
||||||
|
payload /^\x05/
|
||||||
|
tcp-state responder
|
||||||
|
enable "socks"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
|
@load ./consts
|
||||||
@load ./main
|
@load ./main
|
41
scripts/base/protocols/socks/consts.bro
Normal file
41
scripts/base/protocols/socks/consts.bro
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
module SOCKS;
|
||||||
|
|
||||||
|
export {
|
||||||
|
type RequestType: enum {
|
||||||
|
CONNECTION = 1,
|
||||||
|
PORT = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
const v5_authentication_methods: table[count] of string = {
|
||||||
|
[0] = "No Authentication Required",
|
||||||
|
[1] = "GSSAPI",
|
||||||
|
[2] = "Username/Password",
|
||||||
|
[3] = "Challenge-Handshake Authentication Protocol",
|
||||||
|
[4] = "Unassigned",
|
||||||
|
[5] = "Challenge-Response Authentication Method",
|
||||||
|
[6] = "Secure Sockets Layer",
|
||||||
|
[7] = "NDS Authentication",
|
||||||
|
[8] = "Multi-Authentication Framework",
|
||||||
|
[255] = "No Acceptable Methods",
|
||||||
|
} &default=function(i: count):string { return fmt("unknown-%d", i); };
|
||||||
|
|
||||||
|
const v4_status: table[count] of string = {
|
||||||
|
[0x5a] = "succeeded",
|
||||||
|
[0x5b] = "general SOCKS server failure",
|
||||||
|
[0x5c] = "request failed because client is not running identd",
|
||||||
|
[0x5d] = "request failed because client's identd could not confirm the user ID string in the request",
|
||||||
|
} &default=function(i: count):string { return fmt("unknown-%d", i); };
|
||||||
|
|
||||||
|
const v5_status: table[count] of string = {
|
||||||
|
[0] = "succeeded",
|
||||||
|
[1] = "general SOCKS server failure",
|
||||||
|
[2] = "connection not allowed by ruleset",
|
||||||
|
[3] = "Network unreachable",
|
||||||
|
[4] = "Host unreachable",
|
||||||
|
[5] = "Connection refused",
|
||||||
|
[6] = "TTL expired",
|
||||||
|
[7] = "Command not supported",
|
||||||
|
[8] = "Address type not supported",
|
||||||
|
} &default=function(i: count):string { return fmt("unknown-%d", i); };
|
||||||
|
|
||||||
|
}
|
|
@ -1,15 +1,98 @@
|
||||||
@load base/frameworks/tunnels
|
@load base/frameworks/tunnels
|
||||||
|
@load ./consts
|
||||||
|
|
||||||
module SOCKS;
|
module SOCKS;
|
||||||
|
|
||||||
export {
|
export {
|
||||||
type RequestType: enum {
|
redef enum Log::ID += { LOG };
|
||||||
CONNECTION = 1,
|
|
||||||
PORT = 2,
|
type Info: record {
|
||||||
|
## Time when the proxy connection was first detected.
|
||||||
|
ts: time &log;
|
||||||
|
uid: string &log;
|
||||||
|
id: conn_id &log;
|
||||||
|
## Protocol version of SOCKS.
|
||||||
|
version: count &log;
|
||||||
|
## Username for the proxy if extracted from the network.
|
||||||
|
user: string &log &optional;
|
||||||
|
## Server status for the attempt at using the proxy.
|
||||||
|
status: string &log &optional;
|
||||||
|
## Client requested address. Mutually exclusive with req_name.
|
||||||
|
req_h: addr &log &optional;
|
||||||
|
## Client requested domain name. Mutually exclusive with req_h.
|
||||||
|
req_name: string &log &optional;
|
||||||
|
## Client requested port.
|
||||||
|
req_p: port &log &optional;
|
||||||
|
## Server bound address. Mutually exclusive with bound_name.
|
||||||
|
bound_h: addr &log &optional;
|
||||||
|
## Server bound domain name. Mutually exclusive with bound_h.
|
||||||
|
bound_name: string &log &optional;
|
||||||
|
## Server bound port.
|
||||||
|
bound_p: port &log &optional;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
## Event that can be handled to access the SOCKS
|
||||||
|
## record as it is sent on to the logging framework.
|
||||||
|
global log_socks: event(rec: Info);
|
||||||
}
|
}
|
||||||
|
|
||||||
event socks_request(c: connection, request_type: count, dstaddr: addr, dstname: string, p: port, user: string)
|
event bro_init() &priority=5
|
||||||
{
|
{
|
||||||
Tunnel::register([$cid=c$id, $tunnel_type=Tunnel::SOCKS, $uid=c$uid]);
|
Log::create_stream(SOCKS::LOG, [$columns=Info, $ev=log_socks]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
redef record connection += {
|
||||||
|
socks: SOCKS::Info &optional;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Configure DPD
|
||||||
|
redef capture_filters += { ["socks"] = "tcp port 1080" };
|
||||||
|
redef dpd_config += { [ANALYZER_SOCKS] = [$ports = set(1080/tcp)] };
|
||||||
|
redef likely_server_ports += { 1080/tcp };
|
||||||
|
|
||||||
|
function set_session(c: connection, version: count)
|
||||||
|
{
|
||||||
|
if ( ! c?$socks )
|
||||||
|
c$socks = [$ts=network_time(), $id=c$id, $uid=c$uid, $version=version];
|
||||||
|
}
|
||||||
|
|
||||||
|
event socks_request(c: connection, version: count, request_type: count,
|
||||||
|
dstaddr: addr, dstname: string, p: port, user: string) &priority=5
|
||||||
|
{
|
||||||
|
set_session(c, version);
|
||||||
|
|
||||||
|
if ( dstaddr != [::] )
|
||||||
|
c$socks$req_h = dstaddr;
|
||||||
|
if ( dstname != "" )
|
||||||
|
c$socks$req_name = dstname;
|
||||||
|
c$socks$req_p = p;
|
||||||
|
|
||||||
|
# Copy this conn_id and set the orig_p to zero because in the case of SOCKS proxies there will
|
||||||
|
# be potentially many source ports since a new proxy connection is established for each
|
||||||
|
# proxied connection. We treat this as a singular "tunnel".
|
||||||
|
local cid = copy(c$id);
|
||||||
|
cid$orig_p = 0/tcp;
|
||||||
|
Tunnel::register([$cid=cid, $tunnel_type=Tunnel::SOCKS, $payload_proxy=T]);
|
||||||
|
}
|
||||||
|
|
||||||
|
event socks_reply(c: connection, version: count, reply: count, dstaddr: addr, dstname: string, p: port) &priority=5
|
||||||
|
{
|
||||||
|
set_session(c, version);
|
||||||
|
|
||||||
|
if ( version == 5 )
|
||||||
|
c$socks$status = v5_status[reply];
|
||||||
|
else if ( version == 4 )
|
||||||
|
c$socks$status = v4_status[reply];
|
||||||
|
|
||||||
|
if ( dstaddr != [::] )
|
||||||
|
c$socks$bound_h = dstaddr;
|
||||||
|
if ( dstname != "" )
|
||||||
|
c$socks$bound_name = dstname;
|
||||||
|
|
||||||
|
c$socks$bound_p = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
event socks_reply(c: connection, version: count, reply: count, dstaddr: addr, dstname: string, p: port) &priority=-5
|
||||||
|
{
|
||||||
|
Log::write(SOCKS::LOG, c$socks);
|
||||||
|
}
|
|
@ -6101,7 +6101,9 @@ event signature_match%(state: signature_state, msg: string, data: string%);
|
||||||
##
|
##
|
||||||
## c: The parent connection of the proxy.
|
## c: The parent connection of the proxy.
|
||||||
##
|
##
|
||||||
## t: The type of the request.
|
## version: The version of SOCKS this message used.
|
||||||
|
##
|
||||||
|
## request_type: The type of the request.
|
||||||
##
|
##
|
||||||
## dstaddr: Address that the tunneled traffic should be sent to.
|
## dstaddr: Address that the tunneled traffic should be sent to.
|
||||||
##
|
##
|
||||||
|
@ -6109,13 +6111,23 @@ event signature_match%(state: signature_state, msg: string, data: string%);
|
||||||
##
|
##
|
||||||
## p: The destination port for the proxied traffic.
|
## p: The destination port for the proxied traffic.
|
||||||
##
|
##
|
||||||
## user: Username given for the SOCKS connection.
|
## user: Username given for the SOCKS connection. This is not yet implemented for SOCKSv5.
|
||||||
event socks_request%(c: connection, request_type: count, dstaddr: addr, dstname: string, p: port, user: string%);
|
event socks_request%(c: connection, version: count, request_type: count, dstaddr: addr, dstname: string, p: port, user: string%);
|
||||||
|
|
||||||
## Generated when a SOCKS reply is analyzed.
|
## Generated when a SOCKS reply is analyzed.
|
||||||
##
|
##
|
||||||
|
## c: The parent connection of the proxy.
|
||||||
##
|
##
|
||||||
event socks_reply%(c: connection, granted: bool, dst: addr, p: port%);
|
## version: The version of SOCKS this message used.
|
||||||
|
##
|
||||||
|
## reply: The status reply from the server.
|
||||||
|
##
|
||||||
|
## dstaddr: The address that the server sent the traffic to.
|
||||||
|
##
|
||||||
|
## dstname: The name the server sent the traffic to. Only applicable for SOCKSv5.
|
||||||
|
##
|
||||||
|
## p: The destination port for the proxied traffic.
|
||||||
|
event socks_reply%(c: connection, version: count, reply: count, dstaddr: addr, dstname: string, p: port%);
|
||||||
|
|
||||||
## Generated when a protocol analyzer finds an identification of a software
|
## Generated when a protocol analyzer finds an identification of a software
|
||||||
## used on a system. This is a protocol-independent event that is fed by
|
## used on a system. This is a protocol-independent event that is fed by
|
||||||
|
|
|
@ -19,39 +19,127 @@ StringVal* array_to_string(vector<uint8> *a)
|
||||||
%}
|
%}
|
||||||
|
|
||||||
refine connection SOCKS_Conn += {
|
refine connection SOCKS_Conn += {
|
||||||
function socks_request(cmd: uint8, dstaddr: uint32, dstname: uint8[], p: uint16, user: uint8[]): bool
|
|
||||||
|
function socks4_request(request: SOCKS4_Request): bool
|
||||||
%{
|
%{
|
||||||
|
StringVal *dstname;
|
||||||
|
if ( ${request.v4a} )
|
||||||
|
dstname = array_to_string(${request.name});
|
||||||
|
|
||||||
BifEvent::generate_socks_request(bro_analyzer(),
|
BifEvent::generate_socks_request(bro_analyzer(),
|
||||||
bro_analyzer()->Conn(),
|
bro_analyzer()->Conn(),
|
||||||
cmd,
|
4,
|
||||||
new AddrVal(htonl(dstaddr)),
|
${request.command},
|
||||||
array_to_string(dstname),
|
new AddrVal(htonl(${request.addr})),
|
||||||
new PortVal(p | TCP_PORT_MASK),
|
dstname,
|
||||||
array_to_string(user));
|
new PortVal(${request.port} | TCP_PORT_MASK),
|
||||||
|
array_to_string(${request.user}));
|
||||||
|
|
||||||
static_cast<SOCKS_Analyzer*>(bro_analyzer())->EndpointDone(true);
|
static_cast<SOCKS_Analyzer*>(bro_analyzer())->EndpointDone(true);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
%}
|
%}
|
||||||
|
|
||||||
function socks_reply(granted: bool, dst: uint32, p: uint16): bool
|
function socks4_reply(reply: SOCKS4_Reply): bool
|
||||||
%{
|
%{
|
||||||
BifEvent::generate_socks_reply(bro_analyzer(),
|
BifEvent::generate_socks_reply(bro_analyzer(),
|
||||||
bro_analyzer()->Conn(),
|
bro_analyzer()->Conn(),
|
||||||
granted,
|
4,
|
||||||
new AddrVal(htonl(dst)),
|
${reply.status},
|
||||||
new PortVal(p | TCP_PORT_MASK));
|
new AddrVal(htonl(${reply.addr})),
|
||||||
|
new StringVal(""),
|
||||||
|
new PortVal(${reply.port} | TCP_PORT_MASK));
|
||||||
|
|
||||||
bro_analyzer()->ProtocolConfirmation();
|
bro_analyzer()->ProtocolConfirmation();
|
||||||
static_cast<SOCKS_Analyzer*>(bro_analyzer())->EndpointDone(false);
|
static_cast<SOCKS_Analyzer*>(bro_analyzer())->EndpointDone(false);
|
||||||
return true;
|
return true;
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
function socks5_request(request: SOCKS5_Request): bool
|
||||||
|
%{
|
||||||
|
AddrVal *ip_addr = 0;
|
||||||
|
StringVal *domain_name = 0;
|
||||||
|
|
||||||
|
// This is dumb and there must be a better way (checking for presence of a field)...
|
||||||
|
switch ( ${request.remote_name.addr_type} )
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
ip_addr = new AddrVal(htonl(${request.remote_name.ipv4}));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
domain_name = new StringVal(${request.remote_name.domain_name.name}.length(),
|
||||||
|
(const char*) ${request.remote_name.domain_name.name}.data());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
ip_addr = new AddrVal(IPAddr(IPv6, (const uint32_t*) ${request.remote_name.ipv6}, IPAddr::Network));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
BifEvent::generate_socks_request(bro_analyzer(),
|
||||||
|
bro_analyzer()->Conn(),
|
||||||
|
5,
|
||||||
|
${request.command},
|
||||||
|
ip_addr,
|
||||||
|
domain_name,
|
||||||
|
new PortVal(${request.port} | TCP_PORT_MASK),
|
||||||
|
new StringVal(""));
|
||||||
|
|
||||||
|
static_cast<SOCKS_Analyzer*>(bro_analyzer())->EndpointDone(true);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
%}
|
||||||
|
|
||||||
|
function socks5_reply(reply: SOCKS5_Reply): bool
|
||||||
|
%{
|
||||||
|
AddrVal *ip_addr = 0;
|
||||||
|
StringVal *domain_name = 0;
|
||||||
|
|
||||||
|
// This is dumb and there must be a better way (checking for presence of a field)...
|
||||||
|
switch ( ${reply.bound.addr_type} )
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
ip_addr = new AddrVal(htonl(${reply.bound.ipv4}));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
domain_name = new StringVal(${reply.bound.domain_name.name}.length(),
|
||||||
|
(const char*) ${reply.bound.domain_name.name}.data());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
ip_addr = new AddrVal(IPAddr(IPv6, (const uint32_t*) ${reply.bound.ipv6}, IPAddr::Network));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
BifEvent::generate_socks_reply(bro_analyzer(),
|
||||||
|
bro_analyzer()->Conn(),
|
||||||
|
5,
|
||||||
|
${reply.reply},
|
||||||
|
ip_addr,
|
||||||
|
domain_name,
|
||||||
|
new PortVal(${reply.port} | TCP_PORT_MASK));
|
||||||
|
|
||||||
|
bro_analyzer()->ProtocolConfirmation();
|
||||||
|
static_cast<SOCKS_Analyzer*>(bro_analyzer())->EndpointDone(false);
|
||||||
|
return true;
|
||||||
|
%}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
refine typeattr SOCKS_Request += &let {
|
refine typeattr SOCKS4_Request += &let {
|
||||||
proc: bool = $context.connection.socks_request(command, addr, empty, port, user);
|
proc: bool = $context.connection.socks4_request(this);
|
||||||
};
|
};
|
||||||
|
|
||||||
refine typeattr SOCKS_Reply += &let {
|
refine typeattr SOCKS4_Reply += &let {
|
||||||
proc: bool = $context.connection.socks_reply((status == 0x5a), addr, port);
|
proc: bool = $context.connection.socks4_reply(this);
|
||||||
|
};
|
||||||
|
|
||||||
|
refine typeattr SOCKS5_Request += &let {
|
||||||
|
proc: bool = $context.connection.socks5_request(this);
|
||||||
|
};
|
||||||
|
|
||||||
|
refine typeattr SOCKS5_Reply += &let {
|
||||||
|
proc: bool = $context.connection.socks5_reply(this);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,34 +1,115 @@
|
||||||
type SOCKS_Message(is_orig: bool) = case is_orig of {
|
|
||||||
true -> request: SOCKS_Request;
|
type SOCKS_Version(is_orig: bool) = record {
|
||||||
false -> reply: SOCKS_Reply;
|
version: uint8;
|
||||||
|
msg: case version of {
|
||||||
|
4 -> socks4_msg: SOCKS4_Message(is_orig);
|
||||||
|
5 -> socks5_msg: SOCKS5_Message(is_orig);
|
||||||
|
default -> socks_msg_fail: empty;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
type SOCKS_Request = record {
|
# SOCKS5 Implementation
|
||||||
version: uint8;
|
type SOCKS5_Message(is_orig: bool) = case $context.connection.v5_past_authentication() of {
|
||||||
|
true -> msg: SOCKS5_Real_Message(is_orig);
|
||||||
|
false -> auth: SOCKS5_Auth_Negotiation(is_orig);
|
||||||
|
};
|
||||||
|
|
||||||
|
type SOCKS5_Auth_Negotiation(is_orig: bool) = case is_orig of {
|
||||||
|
true -> req: SOCKS5_Auth_Negotiation_Request;
|
||||||
|
false -> rep: SOCKS5_Auth_Negotiation_Reply;
|
||||||
|
};
|
||||||
|
|
||||||
|
type SOCKS5_Auth_Negotiation_Request = record {
|
||||||
|
method_count: uint8;
|
||||||
|
methods: uint8[method_count];
|
||||||
|
};
|
||||||
|
|
||||||
|
type SOCKS5_Auth_Negotiation_Reply = record {
|
||||||
|
selected_auth_method: uint8;
|
||||||
|
} &let {
|
||||||
|
past_auth = $context.connection.set_v5_past_authentication();
|
||||||
|
};
|
||||||
|
|
||||||
|
type SOCKS5_Real_Message(is_orig: bool) = case is_orig of {
|
||||||
|
true -> request: SOCKS5_Request;
|
||||||
|
false -> reply: SOCKS5_Reply;
|
||||||
|
};
|
||||||
|
|
||||||
|
type Domain_Name = record {
|
||||||
|
len: uint8;
|
||||||
|
name: bytestring &length=len;
|
||||||
|
} &byteorder = bigendian;
|
||||||
|
|
||||||
|
type SOCKS5_Address = record {
|
||||||
|
addr_type: uint8;
|
||||||
|
addr: case addr_type of {
|
||||||
|
1 -> ipv4: uint32;
|
||||||
|
3 -> domain_name: Domain_Name;
|
||||||
|
4 -> ipv6: uint32[4];
|
||||||
|
default -> err: bytestring &restofdata &transient;
|
||||||
|
};
|
||||||
|
} &byteorder = bigendian;
|
||||||
|
|
||||||
|
type SOCKS5_Request = record {
|
||||||
|
command: uint8;
|
||||||
|
reserved: uint8;
|
||||||
|
remote_name: SOCKS5_Address;
|
||||||
|
port: uint16;
|
||||||
|
} &byteorder = bigendian;
|
||||||
|
|
||||||
|
type SOCKS5_Reply = record {
|
||||||
|
reply: uint8;
|
||||||
|
reserved: uint8;
|
||||||
|
bound: SOCKS5_Address;
|
||||||
|
port: uint16;
|
||||||
|
} &byteorder = bigendian;
|
||||||
|
|
||||||
|
|
||||||
|
# SOCKS4 Implementation
|
||||||
|
type SOCKS4_Message(is_orig: bool) = case is_orig of {
|
||||||
|
true -> request: SOCKS4_Request;
|
||||||
|
false -> reply: SOCKS4_Reply;
|
||||||
|
};
|
||||||
|
|
||||||
|
type SOCKS4_Request = record {
|
||||||
command: uint8;
|
command: uint8;
|
||||||
port: uint16;
|
port: uint16;
|
||||||
addr: uint32;
|
addr: uint32;
|
||||||
user: uint8[] &until($element == 0);
|
user: uint8[] &until($element == 0);
|
||||||
|
|
||||||
host: case v4a of {
|
host: case v4a of {
|
||||||
true -> name: uint8[] &until($element == 0); # v4a
|
true -> name: uint8[] &until($element == 0); # v4a
|
||||||
false -> empty: uint8[] &length=0;
|
false -> empty: uint8[] &length=0;
|
||||||
} &requires(v4a);
|
} &requires(v4a);
|
||||||
|
|
||||||
# FIXME: Can this be non-zero? If so we need to keep it for the
|
|
||||||
# next analyzer.
|
|
||||||
rest: bytestring &restofdata;
|
|
||||||
} &byteorder = bigendian &let {
|
} &byteorder = bigendian &let {
|
||||||
v4a: bool = (addr <= 0x000000ff);
|
v4a: bool = (addr <= 0x000000ff);
|
||||||
};
|
};
|
||||||
|
|
||||||
type SOCKS_Reply = record {
|
type SOCKS4_Reply = record {
|
||||||
zero: uint8;
|
zero: uint8;
|
||||||
status: uint8;
|
status: uint8;
|
||||||
port: uint16;
|
port: uint16;
|
||||||
addr: uint32;
|
addr: uint32;
|
||||||
|
|
||||||
# FIXME: Can this be non-zero? If so we need to keep it for the
|
|
||||||
# next analyzer.
|
|
||||||
rest: bytestring &restofdata;
|
|
||||||
} &byteorder = bigendian;
|
} &byteorder = bigendian;
|
||||||
|
|
||||||
|
|
||||||
|
refine connection SOCKS_Conn += {
|
||||||
|
%member{
|
||||||
|
bool v5_authenticated_;
|
||||||
|
%}
|
||||||
|
|
||||||
|
%init{
|
||||||
|
v5_authenticated_ = false;
|
||||||
|
%}
|
||||||
|
|
||||||
|
function v5_past_authentication(): bool
|
||||||
|
%{
|
||||||
|
return v5_authenticated_;
|
||||||
|
%}
|
||||||
|
|
||||||
|
function set_v5_past_authentication(): bool
|
||||||
|
%{
|
||||||
|
v5_authenticated_ = true;
|
||||||
|
return true;
|
||||||
|
%}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ connection SOCKS_Conn(bro_analyzer: BroAnalyzer) {
|
||||||
%include socks-protocol.pac
|
%include socks-protocol.pac
|
||||||
|
|
||||||
flow SOCKS_Flow(is_orig: bool) {
|
flow SOCKS_Flow(is_orig: bool) {
|
||||||
datagram = SOCKS_Message(is_orig) withcontext(connection, this);
|
datagram = SOCKS_Version(is_orig) withcontext(connection, this);
|
||||||
};
|
};
|
||||||
|
|
||||||
%include socks-analyzer.pac
|
%include socks-analyzer.pac
|
|
@ -0,0 +1,8 @@
|
||||||
|
#separator \x09
|
||||||
|
#set_separator ,
|
||||||
|
#empty_field (empty)
|
||||||
|
#unset_field -
|
||||||
|
#path socks
|
||||||
|
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p version user status req_h req_name req_p bound_h bound_name bound_p
|
||||||
|
#types time string addr port addr port count string string addr string port addr string port
|
||||||
|
1340213015.276495 UWkUyAuUGXf 10.0.0.55 53994 60.190.189.214 8124 5 - succeeded - www.osnews.com 80 192.168.0.31 - 2688
|
|
@ -0,0 +1,8 @@
|
||||||
|
#separator \x09
|
||||||
|
#set_separator ,
|
||||||
|
#empty_field (empty)
|
||||||
|
#unset_field -
|
||||||
|
#path tunnel
|
||||||
|
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p tunnel_type action
|
||||||
|
#types time string addr port addr port enum enum
|
||||||
|
1340213015.276495 - 10.0.0.55 0 60.190.189.214 8124 Tunnel::SOCKS Tunnel::DISCOVER
|
|
@ -0,0 +1,8 @@
|
||||||
|
#separator \x09
|
||||||
|
#set_separator ,
|
||||||
|
#empty_field (empty)
|
||||||
|
#unset_field -
|
||||||
|
#path socks
|
||||||
|
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p version user status req_h req_name req_p bound_h bound_name bound_p
|
||||||
|
#types time string addr port addr port count string string addr string port addr string port
|
||||||
|
1340113261.914619 UWkUyAuUGXf 10.0.0.50 59580 85.194.84.197 1080 5 - succeeded - www.google.com 443 0.0.0.0 - 443
|
|
@ -0,0 +1,8 @@
|
||||||
|
#separator \x09
|
||||||
|
#set_separator ,
|
||||||
|
#empty_field (empty)
|
||||||
|
#unset_field -
|
||||||
|
#path tunnel
|
||||||
|
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p tunnel_type action
|
||||||
|
#types time string addr port addr port enum enum
|
||||||
|
1340113261.914619 - 10.0.0.50 0 85.194.84.197 1080 Tunnel::SOCKS Tunnel::DISCOVER
|
BIN
testing/btest/Traces/socks-with-ssl.trace
Normal file
BIN
testing/btest/Traces/socks-with-ssl.trace
Normal file
Binary file not shown.
BIN
testing/btest/Traces/socks.trace
Normal file
BIN
testing/btest/Traces/socks.trace
Normal file
Binary file not shown.
6
testing/btest/scripts/base/protocols/socks/trace1.test
Normal file
6
testing/btest/scripts/base/protocols/socks/trace1.test
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
# @TEST-EXEC: bro -r $TRACES/socks.trace %INPUT
|
||||||
|
# @TEST-EXEC: btest-diff socks.log
|
||||||
|
# @TEST-EXEC: btest-diff http.log
|
||||||
|
# @TEST-EXEC: btest-diff tunnel.log
|
||||||
|
|
||||||
|
@load base/protocols/socks
|
5
testing/btest/scripts/base/protocols/socks/trace2.test
Normal file
5
testing/btest/scripts/base/protocols/socks/trace2.test
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
# @TEST-EXEC: bro -r $TRACES/socks-with-ssl.trace %INPUT
|
||||||
|
# @TEST-EXEC: btest-diff socks.log
|
||||||
|
# @TEST-EXEC: btest-diff tunnel.log
|
||||||
|
|
||||||
|
@load base/protocols/socks
|
Loading…
Add table
Add a link
Reference in a new issue