mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 14:48:21 +00:00
Update the SOCKS analyzer to support user/pass login.
- This addresses BIT-1011 - Add a new field to socks.log; "password". - Two new events; socks_login_userpass and socks_login_reply. - One new weird for unsupported authentication method. - A new test for authenticated socks traffic. - Credit to Nicolas Retrain for the initial patch. Thanks!
This commit is contained in:
parent
565ad360c6
commit
9592f64225
11 changed files with 162 additions and 21 deletions
|
@ -16,8 +16,10 @@ export {
|
|||
id: conn_id &log;
|
||||
## Protocol version of SOCKS.
|
||||
version: count &log;
|
||||
## Username for the proxy if extracted from the network.
|
||||
## Username used to request a login to the proxy.
|
||||
user: string &log &optional;
|
||||
## Password used to request a login to the proxy.
|
||||
password: string &log &optional;
|
||||
## Server status for the attempt at using the proxy.
|
||||
status: string &log &optional;
|
||||
## Client requested SOCKS address. Could be an address, a name
|
||||
|
@ -91,3 +93,21 @@ event socks_reply(c: connection, version: count, reply: count, sa: SOCKS::Addres
|
|||
if ( "SOCKS" in c$service )
|
||||
Log::write(SOCKS::LOG, c$socks);
|
||||
}
|
||||
|
||||
event socks_login_userpass(c: connection, user: string, password: string) &priority=5
|
||||
{
|
||||
# Authentication only possible with the version 5.
|
||||
set_session(c, 5);
|
||||
|
||||
c$socks$user = user;
|
||||
c$socks$password = password;
|
||||
}
|
||||
|
||||
event socks_login_reply(c: connection, code: count) &priority=5
|
||||
{
|
||||
# Authentication only possible with the version 5.
|
||||
set_session(c, 5);
|
||||
|
||||
c$socks$status = v5_status[code];
|
||||
}
|
||||
|
||||
|
|
|
@ -57,8 +57,7 @@ void SOCKS_Analyzer::DeliverStream(int len, const u_char* data, bool orig)
|
|||
// with the rest of the conneciton.
|
||||
//
|
||||
// Note that we assume that no payload data arrives before both endpoints
|
||||
// are done with there part of the SOCKS protocol.
|
||||
|
||||
// are done with their part of the SOCKS protocol.
|
||||
if ( ! pia )
|
||||
{
|
||||
pia = new pia::PIA_TCP(Conn());
|
||||
|
|
|
@ -27,3 +27,19 @@ event socks_request%(c: connection, version: count, request_type: count, sa: SOC
|
|||
## p: The destination port for the proxied traffic.
|
||||
event socks_reply%(c: connection, version: count, reply: count, sa: SOCKS::Address, p: port%);
|
||||
|
||||
## Generated when a SOCKS client performs username and password based login.
|
||||
##
|
||||
## c: The parent connection of the proxy.
|
||||
##
|
||||
## user: The given username.
|
||||
##
|
||||
## password: The given password.
|
||||
event socks_login_userpass%(c: connection, user: string, password: string%);
|
||||
|
||||
## Generated when a SOCKS server replies to a login attempt.
|
||||
##
|
||||
## c: The parent connection of the proxy.
|
||||
##
|
||||
## code: The response code for the attempted login.
|
||||
event socks_login_reply%(c: connection, code: count%);
|
||||
|
||||
|
|
|
@ -148,6 +148,31 @@ refine connection SOCKS_Conn += {
|
|||
return true;
|
||||
%}
|
||||
|
||||
function socks5_auth_request_userpass(request: SOCKS5_Auth_Request_UserPass): bool
|
||||
%{
|
||||
StringVal* user = new StringVal(${request.username}.length(), (const char*) ${request.username}.begin());
|
||||
StringVal* pass = new StringVal(${request.password}.length(), (const char*) ${request.password}.begin());
|
||||
|
||||
BifEvent::generate_socks_login_userpass(bro_analyzer(),
|
||||
bro_analyzer()->Conn(),
|
||||
user, pass);
|
||||
return true;
|
||||
%}
|
||||
|
||||
function socks5_unsupported_authentication(auth_method: uint8): bool
|
||||
%{
|
||||
reporter->Weird(bro_analyzer()->Conn(), fmt("socks5_unsupported_authentication_%d", auth_method));
|
||||
return true;
|
||||
%}
|
||||
|
||||
function socks5_auth_reply(reply: SOCKS5_Auth_Reply): bool
|
||||
%{
|
||||
BifEvent::generate_socks_login_reply(bro_analyzer(),
|
||||
bro_analyzer()->Conn(),
|
||||
${reply.code});
|
||||
return true;
|
||||
%}
|
||||
|
||||
function version_error(version: uint8): bool
|
||||
%{
|
||||
bro_analyzer()->ProtocolViolation(fmt("unsupported/unknown SOCKS version %d", version));
|
||||
|
@ -176,3 +201,18 @@ refine typeattr SOCKS5_Request += &let {
|
|||
refine typeattr SOCKS5_Reply += &let {
|
||||
proc: bool = $context.connection.socks5_reply(this);
|
||||
};
|
||||
|
||||
refine typeattr SOCKS5_Auth_Negotiation_Reply += &let {
|
||||
};
|
||||
|
||||
refine typeattr SOCKS5_Auth_Request_UserPass += &let {
|
||||
proc: bool = $context.connection.socks5_auth_request_userpass(this);
|
||||
};
|
||||
|
||||
refine typeattr SOCKS5_Auth_Reply += &let {
|
||||
proc: bool = $context.connection.socks5_auth_reply(this);
|
||||
};
|
||||
|
||||
refine typeattr SOCKS5_Unsupported_Authentication += &let {
|
||||
proc: bool = $context.connection.socks5_unsupported_authentication($context.connection.v5_auth_method());
|
||||
};
|
||||
|
|
|
@ -2,9 +2,10 @@
|
|||
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);
|
||||
1 -> socks5_auth_msg: SOCKS5_Auth_Message(is_orig);
|
||||
4 -> socks4_msg: SOCKS4_Message(is_orig);
|
||||
5 -> socks5_msg: SOCKS5_Message(is_orig);
|
||||
default -> socks_msg_fail: SOCKS_Version_Error(version);
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -14,10 +15,11 @@ type SOCKS_Version_Error(version: uint8) = record {
|
|||
|
||||
# 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);
|
||||
true -> msg: SOCKS5_Real_Message(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;
|
||||
|
@ -32,6 +34,32 @@ type SOCKS5_Auth_Negotiation_Reply = record {
|
|||
selected_auth_method: uint8;
|
||||
} &let {
|
||||
past_auth = $context.connection.set_v5_past_authentication();
|
||||
set_auth = $context.connection.set_v5_auth_method(selected_auth_method);
|
||||
};
|
||||
|
||||
type SOCKS5_Auth_Message(is_orig: bool) = case is_orig of {
|
||||
true -> req: SOCKS5_Auth_Request;
|
||||
false -> rep: SOCKS5_Auth_Reply;
|
||||
};
|
||||
|
||||
type SOCKS5_Auth_Request = case $context.connection.v5_auth_method() of {
|
||||
0x02 -> userpass : SOCKS5_Auth_Request_UserPass;
|
||||
default -> unsupported : SOCKS5_Unsupported_Authentication;
|
||||
};
|
||||
|
||||
type SOCKS5_Unsupported_Authentication = record {
|
||||
crap: bytestring &restofdata;
|
||||
};
|
||||
|
||||
type SOCKS5_Auth_Request_UserPass = record {
|
||||
ulen : uint8;
|
||||
username : bytestring &length=ulen;
|
||||
plen : uint8;
|
||||
password : bytestring &length=plen;
|
||||
};
|
||||
|
||||
type SOCKS5_Auth_Reply = record {
|
||||
code : uint8;
|
||||
};
|
||||
|
||||
type SOCKS5_Real_Message(is_orig: bool) = case is_orig of {
|
||||
|
@ -55,10 +83,10 @@ type SOCKS5_Address = record {
|
|||
} &byteorder = bigendian;
|
||||
|
||||
type SOCKS5_Request = record {
|
||||
command: uint8;
|
||||
reserved: uint8;
|
||||
remote_name: SOCKS5_Address;
|
||||
port: uint16;
|
||||
command : uint8;
|
||||
reserved : uint8;
|
||||
remote_name : SOCKS5_Address;
|
||||
port : uint16;
|
||||
} &byteorder = bigendian;
|
||||
|
||||
type SOCKS5_Reply = record {
|
||||
|
@ -99,10 +127,12 @@ type SOCKS4_Reply = record {
|
|||
refine connection SOCKS_Conn += {
|
||||
%member{
|
||||
bool v5_authenticated_;
|
||||
uint8 selected_auth_method_;
|
||||
%}
|
||||
|
||||
%init{
|
||||
v5_authenticated_ = false;
|
||||
selected_auth_method_ = 255;
|
||||
%}
|
||||
|
||||
function v5_past_authentication(): bool
|
||||
|
@ -115,5 +145,16 @@ refine connection SOCKS_Conn += {
|
|||
v5_authenticated_ = true;
|
||||
return true;
|
||||
%}
|
||||
|
||||
function set_v5_auth_method(method: uint8): bool
|
||||
%{
|
||||
selected_auth_method_ = method;
|
||||
return true;
|
||||
%}
|
||||
|
||||
function v5_auth_method(): uint8
|
||||
%{
|
||||
return selected_auth_method_;
|
||||
%}
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
#separator \x09
|
||||
#set_separator ,
|
||||
#empty_field (empty)
|
||||
#unset_field -
|
||||
#path socks
|
||||
#open 2015-02-05-16-13-12
|
||||
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p version user password status request.host request.name request_p bound.host bound.name bound_p
|
||||
#types time string addr port addr port count string string string addr string port addr string port
|
||||
1368517392.724989 CXWv6p3arKYeMETxOg 192.168.0.2 55951 192.168.0.1 1080 5 bob alice succeeded 192.168.0.2 - 22 192.168.0.1 - 55951
|
||||
#close 2015-02-05-16-13-12
|
|
@ -0,0 +1,10 @@
|
|||
#separator \x09
|
||||
#set_separator ,
|
||||
#empty_field (empty)
|
||||
#unset_field -
|
||||
#path tunnel
|
||||
#open 2015-02-05-16-13-12
|
||||
#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
|
||||
1368517392.728523 - 192.168.0.2 0 192.168.0.1 1080 Tunnel::SOCKS Tunnel::DISCOVER
|
||||
#close 2015-02-05-16-13-12
|
|
@ -3,8 +3,8 @@
|
|||
#empty_field (empty)
|
||||
#unset_field -
|
||||
#path socks
|
||||
#open 2013-08-26-19-04-20
|
||||
#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 CjhGID4nQcgTWjvg4c 10.0.0.55 53994 60.190.189.214 8124 5 - succeeded - www.osnews.com 80 192.168.0.31 - 2688
|
||||
#close 2013-08-26-19-04-20
|
||||
#open 2015-02-05-17-39-14
|
||||
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p version user password status request.host request.name request_p bound.host bound.name bound_p
|
||||
#types time string addr port addr port count string string string addr string port addr string port
|
||||
1340213015.276495 CjhGID4nQcgTWjvg4c 10.0.0.55 53994 60.190.189.214 8124 5 - - succeeded - www.osnews.com 80 192.168.0.31 - 2688
|
||||
#close 2015-02-05-17-39-14
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
#empty_field (empty)
|
||||
#unset_field -
|
||||
#path socks
|
||||
#open 2013-08-26-19-04-20
|
||||
#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 CXWv6p3arKYeMETxOg 10.0.0.50 59580 85.194.84.197 1080 5 - succeeded - www.google.com 443 0.0.0.0 - 443
|
||||
#close 2013-08-26-19-04-20
|
||||
#open 2015-02-05-17-39-29
|
||||
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p version user password status request.host request.name request_p bound.host bound.name bound_p
|
||||
#types time string addr port addr port count string string string addr string port addr string port
|
||||
1340113261.914619 CXWv6p3arKYeMETxOg 10.0.0.50 59580 85.194.84.197 1080 5 - - succeeded - www.google.com 443 0.0.0.0 - 443
|
||||
#close 2015-02-05-17-39-29
|
||||
|
|
BIN
testing/btest/Traces/socks-auth.pcap
Normal file
BIN
testing/btest/Traces/socks-auth.pcap
Normal file
Binary file not shown.
|
@ -0,0 +1,5 @@
|
|||
# @TEST-EXEC: bro -r $TRACES/socks-auth.pcap %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