diff --git a/scripts/base/frameworks/dpd/dpd.sig b/scripts/base/frameworks/dpd/dpd.sig index 05dcee9d49..49e24cefc6 100644 --- a/scripts/base/frameworks/dpd/dpd.sig +++ b/scripts/base/frameworks/dpd/dpd.sig @@ -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" } diff --git a/scripts/base/init-bare.bro b/scripts/base/init-bare.bro index 17ea0823ac..3a323ad7fe 100644 --- a/scripts/base/init-bare.bro +++ b/scripts/base/init-bare.bro @@ -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. diff --git a/scripts/base/protocols/socks/main.bro b/scripts/base/protocols/socks/main.bro index cceea68758..96dbccb522 100644 --- a/scripts/base/protocols/socks/main.bro +++ b/scripts/base/protocols/socks/main.bro @@ -8,27 +8,23 @@ export { type Info: record { ## Time when the proxy connection was first detected. - ts: time &log; - uid: string &log; - id: conn_id &log; + ts: time &log; + uid: string &log; + id: conn_id &log; ## Protocol version of SOCKS. - version: count &log; + version: count &log; ## Username for the proxy if extracted from the network. - user: string &log &optional; + 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; + status: 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; + bound_p: port &log &optional; }; ## Event that can be handled to access the SOCKS @@ -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); } \ No newline at end of file diff --git a/src/NetVar.cc b/src/NetVar.cc index b057efad11..248ae15e1a 100644 --- a/src/NetVar.cc +++ b/src/NetVar.cc @@ -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; @@ -344,6 +346,8 @@ void init_net_var() opt_internal_int("tcp_excessive_data_without_further_acks"); 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"); diff --git a/src/NetVar.h b/src/NetVar.h index e6f6e0cfc4..2561fa0ad9 100644 --- a/src/NetVar.h +++ b/src/NetVar.h @@ -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; diff --git a/src/event.bif b/src/event.bif index d1e28a98e5..63ec361851 100644 --- a/src/event.bif +++ b/src/event.bif @@ -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 diff --git a/src/socks-analyzer.pac b/src/socks-analyzer.pac index 1d71753fb5..bf5ada4631 100644 --- a/src/socks-analyzer.pac +++ b/src/socks-analyzer.pac @@ -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(); @@ -65,24 +64,23 @@ refine connection SOCKS_Conn += { bro_analyzer()->ProtocolViolation(fmt("invalid value in reserved field: %d", ${request.reserved})); 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(); diff --git a/testing/btest/Baseline/scripts.base.protocols.socks.trace1/socks.log b/testing/btest/Baseline/scripts.base.protocols.socks.trace1/socks.log index 4241190234..08d31fdb69 100644 --- a/testing/btest/Baseline/scripts.base.protocols.socks.trace1/socks.log +++ b/testing/btest/Baseline/scripts.base.protocols.socks.trace1/socks.log @@ -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 diff --git a/testing/btest/Baseline/scripts.base.protocols.socks.trace2/socks.log b/testing/btest/Baseline/scripts.base.protocols.socks.trace2/socks.log index 556ed9263e..8fd109f3a4 100644 --- a/testing/btest/Baseline/scripts.base.protocols.socks.trace2/socks.log +++ b/testing/btest/Baseline/scripts.base.protocols.socks.trace2/socks.log @@ -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