Fixed some problems with the SOCKS analyzer and tests.

This commit is contained in:
Seth Hall 2012-06-20 22:57:46 -04:00
parent f59736cb17
commit 6b8b4dab71
9 changed files with 63 additions and 71 deletions

View file

@ -202,8 +202,9 @@ signature dpd_socks5_client {
signature dpd_socks5_server {
ip-proto == tcp
requires-reverse-signature dpd_socks5_client
# Watch for a single authentication method to be chosen by the server.
payload /^\x05\x01[\x00\x01\x02]/
# Watch for a single authentication method to be chosen by the server or
# the server to indicate the no authentication is required.
payload /^\x05(\x00|\x01[\x00\x01\x02])/
tcp-state responder
enable "socks"
}

View file

@ -2402,6 +2402,17 @@ type bittorrent_benc_dir: table[string] of bittorrent_benc_value;
## bt_tracker_response_not_ok
type bt_tracker_headers: table[string] of string;
module SOCKS;
export {
## This record is for a SOCKS client or server to provide either a
## name or an address to represent a desired or established connection.
type Address: record {
host: addr &optional;
name: string &optional;
} &log;
}
module GLOBAL;
@load base/event.bif
## BPF filter the user has set via the -f command line options. Empty if none.

View file

@ -17,16 +17,12 @@ export {
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 SOCKS address. Could be an address, a name or both.
request: SOCKS::Address &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;
request_p: port &log &optional;
## Server bound address. Could be an address, a name or both.
bound: SOCKS::Address &log &optional;
## Server bound port.
bound_p: port &log &optional;
};
@ -57,15 +53,12 @@ function set_session(c: connection, version: count)
}
event socks_request(c: connection, version: count, request_type: count,
dstaddr: addr, dstname: string, p: port, user: string) &priority=5
sa: SOCKS::Address, 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;
c$socks$request = sa;
c$socks$request_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
@ -75,7 +68,7 @@ event socks_request(c: connection, version: count, request_type: count,
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
event socks_reply(c: connection, version: count, reply: count, sa: SOCKS::Address, p: port) &priority=5
{
set_session(c, version);
@ -84,15 +77,11 @@ event socks_reply(c: connection, version: count, reply: count, dstaddr: addr, ds
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 = sa;
c$socks$bound_p = p;
}
event socks_reply(c: connection, version: count, reply: count, dstaddr: addr, dstname: string, p: port) &priority=-5
event socks_reply(c: connection, version: count, reply: count, sa: SOCKS::Address, p: port) &priority=-5
{
Log::write(SOCKS::LOG, c$socks);
}

View file

@ -48,6 +48,8 @@ int tcp_excessive_data_without_further_acks;
RecordType* x509_type;
RecordType* socks_address;
double non_analyzed_lifetime;
double tcp_inactivity_timeout;
double udp_inactivity_timeout;
@ -345,6 +347,8 @@ void init_net_var()
x509_type = internal_type("X509")->AsRecordType();
socks_address = internal_type("SOCKS::Address")->AsRecordType();
non_analyzed_lifetime = opt_internal_double("non_analyzed_lifetime");
tcp_inactivity_timeout = opt_internal_double("tcp_inactivity_timeout");
udp_inactivity_timeout = opt_internal_double("udp_inactivity_timeout");

View file

@ -51,6 +51,8 @@ extern int tcp_excessive_data_without_further_acks;
extern RecordType* x509_type;
extern RecordType* socks_address;
extern double non_analyzed_lifetime;
extern double tcp_inactivity_timeout;
extern double udp_inactivity_timeout;

View file

@ -6112,7 +6112,7 @@ 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. 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%);
event socks_request%(c: connection, version: count, request_type: count, sa: SOCKS::Address, p: port, user: string%);
## Generated when a SOCKS reply is analyzed.
##
@ -6127,7 +6127,7 @@ event socks_request%(c: connection, version: count, request_type: count, dstaddr
## 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%);
event socks_reply%(c: connection, version: count, reply: count, sa: SOCKS::Address, 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

View file

@ -22,19 +22,16 @@ refine connection SOCKS_Conn += {
function socks4_request(request: SOCKS4_Request): bool
%{
StringVal *dstname = 0;
RecordVal* sa = new RecordVal(socks_address);
sa->Assign(0, new AddrVal(htonl(${request.addr})));
if ( ${request.v4a} )
dstname = array_to_string(${request.name});
else
dstname = new StringVal("");
sa->Assign(1, array_to_string(${request.name}));
BifEvent::generate_socks_request(bro_analyzer(),
bro_analyzer()->Conn(),
4,
${request.command},
new AddrVal(htonl(${request.addr})),
dstname,
sa,
new PortVal(${request.port} | TCP_PORT_MASK),
array_to_string(${request.user}));
@ -45,12 +42,14 @@ refine connection SOCKS_Conn += {
function socks4_reply(reply: SOCKS4_Reply): bool
%{
RecordVal* sa = new RecordVal(socks_address);
sa->Assign(0, new AddrVal(htonl(${reply.addr})));
BifEvent::generate_socks_reply(bro_analyzer(),
bro_analyzer()->Conn(),
4,
${reply.status},
new AddrVal(htonl(${reply.addr})),
new StringVal(""),
sa,
new PortVal(${reply.port} | TCP_PORT_MASK));
bro_analyzer()->ProtocolConfirmation();
@ -66,23 +65,22 @@ refine connection SOCKS_Conn += {
return false;
}
AddrVal *ip_addr = 0;
StringVal *domain_name = 0;
RecordVal* sa = new RecordVal(socks_address);
// 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}));
sa->Assign(0, 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());
sa->Assign(1, 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));
sa->Assign(0, new AddrVal(IPAddr(IPv6, (const uint32_t*) ${request.remote_name.ipv6}, IPAddr::Network)));
break;
default:
@ -91,17 +89,11 @@ refine connection SOCKS_Conn += {
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,
sa,
new PortVal(${request.port} | TCP_PORT_MASK),
new StringVal(""));
@ -112,23 +104,22 @@ refine connection SOCKS_Conn += {
function socks5_reply(reply: SOCKS5_Reply): bool
%{
AddrVal *ip_addr = 0;
StringVal *domain_name = 0;
RecordVal* sa = new RecordVal(socks_address);
// 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}));
sa->Assign(0, 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());
sa->Assign(1, 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));
sa->Assign(0, new AddrVal(IPAddr(IPv6, (const uint32_t*) ${reply.bound.ipv6}, IPAddr::Network)));
break;
default:
@ -137,17 +128,11 @@ refine connection SOCKS_Conn += {
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,
sa,
new PortVal(${reply.port} | TCP_PORT_MASK));
bro_analyzer()->ProtocolConfirmation();

View file

@ -3,6 +3,6 @@
#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
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p version user status request.host request.name request_p bound.host 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

View file

@ -3,6 +3,6 @@
#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
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p version user status request.host request.name request_p bound.host 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