mirror of
https://github.com/zeek/zeek.git
synced 2025-10-07 17:18:20 +00:00
Merge remote-tracking branch 'origin/topic/seth/tunnels-merge'
* origin/topic/seth/tunnels-merge: SOCKS DPD fixes. Fix a bug in the SOCKS analyzer. SOCKS and tunnel test updates. Updates for the SOCKS analyzer. Very small updates to the tunnels framework.
This commit is contained in:
commit
6cda00c75e
30 changed files with 524 additions and 127 deletions
|
@ -6226,7 +6226,9 @@ event signature_match%(state: signature_state, msg: string, data: string%);
|
|||
##
|
||||
## 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.
|
||||
##
|
||||
|
@ -6234,13 +6236,23 @@ event signature_match%(state: signature_state, msg: string, data: string%);
|
|||
##
|
||||
## p: The destination port for the proxied traffic.
|
||||
##
|
||||
## user: Username given for the SOCKS connection.
|
||||
event socks_request%(c: connection, request_type: count, dstaddr: addr, dstname: string, p: port, user: string%);
|
||||
## user: Username given for the SOCKS connection. This is not yet implemented for SOCKSv5.
|
||||
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.
|
||||
##
|
||||
## 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
|
||||
## used on a system. This is a protocol-independent event that is fed by
|
||||
|
|
|
@ -19,39 +19,169 @@ StringVal* array_to_string(vector<uint8> *a)
|
|||
%}
|
||||
|
||||
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 = 0;
|
||||
if ( ${request.v4a} )
|
||||
dstname = array_to_string(${request.name});
|
||||
else
|
||||
dstname = new StringVal("");
|
||||
|
||||
BifEvent::generate_socks_request(bro_analyzer(),
|
||||
bro_analyzer()->Conn(),
|
||||
cmd,
|
||||
new AddrVal(htonl(dstaddr)),
|
||||
array_to_string(dstname),
|
||||
new PortVal(p | TCP_PORT_MASK),
|
||||
array_to_string(user));
|
||||
4,
|
||||
${request.command},
|
||||
new AddrVal(htonl(${request.addr})),
|
||||
dstname,
|
||||
new PortVal(${request.port} | TCP_PORT_MASK),
|
||||
array_to_string(${request.user}));
|
||||
|
||||
static_cast<SOCKS_Analyzer*>(bro_analyzer())->EndpointDone(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(),
|
||||
bro_analyzer()->Conn(),
|
||||
granted,
|
||||
new AddrVal(htonl(dst)),
|
||||
new PortVal(p | TCP_PORT_MASK));
|
||||
4,
|
||||
${reply.status},
|
||||
new AddrVal(htonl(${reply.addr})),
|
||||
new StringVal(""),
|
||||
new PortVal(${reply.port} | TCP_PORT_MASK));
|
||||
|
||||
bro_analyzer()->ProtocolConfirmation();
|
||||
static_cast<SOCKS_Analyzer*>(bro_analyzer())->EndpointDone(false);
|
||||
return true;
|
||||
%}
|
||||
|
||||
function socks5_request(request: SOCKS5_Request): bool
|
||||
%{
|
||||
if ( ${request.reserved} != 0 )
|
||||
{
|
||||
bro_analyzer()->ProtocolViolation(fmt("invalid value in reserved field: %d", ${request.reserved}));
|
||||
return false;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
default:
|
||||
bro_analyzer()->ProtocolViolation(fmt("invalid SOCKSv5 addr type: %d", ${request.remote_name.addr_type}));
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( ! ip_addr )
|
||||
ip_addr = new AddrVal(uint32(0));
|
||||
|
||||
if ( ! domain_name )
|
||||
domain_name = new StringVal("");
|
||||
|
||||
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;
|
||||
|
||||
default:
|
||||
bro_analyzer()->ProtocolViolation(fmt("invalid SOCKSv5 addr type: %d", ${reply.bound.addr_type}));
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( ! ip_addr )
|
||||
ip_addr = new AddrVal(uint32(0));
|
||||
|
||||
if ( ! domain_name )
|
||||
domain_name = new StringVal("");
|
||||
|
||||
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;
|
||||
%}
|
||||
|
||||
function version_error(version: uint8): bool
|
||||
%{
|
||||
bro_analyzer()->ProtocolViolation(fmt("unsupported/unknown SOCKS version %d", version));
|
||||
return true;
|
||||
%}
|
||||
|
||||
|
||||
};
|
||||
|
||||
refine typeattr SOCKS_Request += &let {
|
||||
proc: bool = $context.connection.socks_request(command, addr, empty, port, user);
|
||||
refine typeattr SOCKS_Version_Error += &let {
|
||||
proc: bool = $context.connection.version_error(version);
|
||||
};
|
||||
|
||||
refine typeattr SOCKS_Reply += &let {
|
||||
proc: bool = $context.connection.socks_reply((status == 0x5a), addr, port);
|
||||
refine typeattr SOCKS4_Request += &let {
|
||||
proc: bool = $context.connection.socks4_request(this);
|
||||
};
|
||||
|
||||
refine typeattr SOCKS4_Reply += &let {
|
||||
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,119 @@
|
|||
type SOCKS_Message(is_orig: bool) = case is_orig of {
|
||||
true -> request: SOCKS_Request;
|
||||
false -> reply: SOCKS_Reply;
|
||||
|
||||
type SOCKS_Version(is_orig: bool) = record {
|
||||
version: uint8;
|
||||
msg: case version of {
|
||||
4 -> socks4_msg: SOCKS4_Message(is_orig);
|
||||
5 -> socks5_msg: SOCKS5_Message(is_orig);
|
||||
default -> socks_msg_fail: SOCKS_Version_Error(version);
|
||||
};
|
||||
};
|
||||
|
||||
type SOCKS_Request = record {
|
||||
version: uint8;
|
||||
type SOCKS_Version_Error(version: uint8) = record {
|
||||
nothing: empty;
|
||||
};
|
||||
|
||||
# SOCKS5 Implementation
|
||||
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;
|
||||
port: uint16;
|
||||
addr: uint32;
|
||||
user: uint8[] &until($element == 0);
|
||||
|
||||
host: case v4a of {
|
||||
true -> name: uint8[] &until($element == 0); # v4a
|
||||
false -> empty: uint8[] &length=0;
|
||||
} &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 {
|
||||
v4a: bool = (addr <= 0x000000ff);
|
||||
};
|
||||
|
||||
type SOCKS_Reply = record {
|
||||
zero: uint8;
|
||||
status: uint8;
|
||||
type SOCKS4_Reply = record {
|
||||
zero: uint8;
|
||||
status: uint8;
|
||||
port: uint16;
|
||||
addr: uint32;
|
||||
|
||||
# FIXME: Can this be non-zero? If so we need to keep it for the
|
||||
# next analyzer.
|
||||
rest: bytestring &restofdata;
|
||||
} &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
|
||||
|
||||
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
|
Loading…
Add table
Add a link
Reference in a new issue