Init RDP analyzer

This commit is contained in:
Josh Liburdi 2015-02-14 13:16:48 -08:00
parent 4bcb9d2d92
commit 46713fb5c7
14 changed files with 1161 additions and 1 deletions

View file

@ -0,0 +1,4 @@
# Generated by binpac_quickstart
@load ./consts
@load ./main
@load-sigs ./dpd.sig

View file

@ -0,0 +1,287 @@
module RDP;
export {
# http://www.c-amie.co.uk/technical/mstsc-versions/
const builds = {
[0419] = "RDP 4.0",
[2195] = "RDP 5.0",
[2221] = "RDP 5.0",
[2600] = "RDP 5.1",
[3790] = "RDP 5.2",
[6000] = "RDP 6.0",
[6001] = "RDP 6.1",
[6002] = "RDP 6.2",
[7600] = "RDP 7.0",
[7601] = "RDP 7.1",
[9200] = "RDP 8.0",
[9600] = "RDP 8.1",
[25189] = "RDP 8.0 (Mac)",
[25282] = "RDP 8.0 (Mac)"
} &default = function(n: count): string { return fmt("client_build-%d", n); };
const encryption_methods = {
[0] = "None",
[1] = "40bit",
[2] = "128bit",
[8] = "56bit",
[10] = "FIPS"
} &default = function(n: count): string { return fmt("encryption_method-%d", n); };
const encryption_levels = {
[0] = "None",
[1] = "Low",
[2] = "Client compatible",
[3] = "High",
[4] = "FIPS"
} &default = function(n: count): string { return fmt("encryption_level-%d", n); };
const results = {
[0] = "Success",
[1] = "User rejected",
[2] = "Resources not available",
[3] = "Rejected for symmetry breaking",
[4] = "Locked conference",
} &default = function(n: count): string { return fmt("result-%d", n); };
# http://msdn.microsoft.com/en-us/goglobal/bb964664.aspx
const languages = {
[1078] = "Afrikaans - South Africa",
[1052] = "Albanian - Albania",
[1156] = "Alsatian",
[1118] = "Amharic - Ethiopia",
[1025] = "Arabic - Saudi Arabia",
[5121] = "Arabic - Algeria",
[15361] = "Arabic - Bahrain",
[3073] = "Arabic - Egypt",
[2049] = "Arabic - Iraq",
[11265] = "Arabic - Jordan",
[13313] = "Arabic - Kuwait",
[12289] = "Arabic - Lebanon",
[4097] = "Arabic - Libya",
[6145] = "Arabic - Morocco",
[8193] = "Arabic - Oman",
[16385] = "Arabic - Qatar",
[10241] = "Arabic - Syria",
[7169] = "Arabic - Tunisia",
[14337] = "Arabic - U.A.E.",
[9217] = "Arabic - Yemen",
[1067] = "Armenian - Armenia",
[1101] = "Assamese",
[2092] = "Azeri (Cyrillic)",
[1068] = "Azeri (Latin)",
[1133] = "Bashkir",
[1069] = "Basque",
[1059] = "Belarusian",
[1093] = "Bengali (India)",
[2117] = "Bengali (Bangladesh)",
[5146] = "Bosnian (Bosnia/Herzegovina)",
[1150] = "Breton",
[1026] = "Bulgarian",
[1109] = "Burmese",
[1027] = "Catalan",
[1116] = "Cherokee - United States",
[2052] = "Chinese - People's Republic of China",
[4100] = "Chinese - Singapore",
[1028] = "Chinese - Taiwan",
[3076] = "Chinese - Hong Kong SAR",
[5124] = "Chinese - Macao SAR",
[1155] = "Corsican",
[1050] = "Croatian",
[4122] = "Croatian (Bosnia/Herzegovina)",
[1029] = "Czech",
[1030] = "Danish",
[1164] = "Dari",
[1125] = "Divehi",
[1043] = "Dutch - Netherlands",
[2067] = "Dutch - Belgium",
[1126] = "Edo",
[1033] = "English - United States",
[2057] = "English - United Kingdom",
[3081] = "English - Australia",
[10249] = "English - Belize",
[4105] = "English - Canada",
[9225] = "English - Caribbean",
[15369] = "English - Hong Kong SAR",
[16393] = "English - India",
[14345] = "English - Indonesia",
[6153] = "English - Ireland",
[8201] = "English - Jamaica",
[17417] = "English - Malaysia",
[5129] = "English - New Zealand",
[13321] = "English - Philippines",
[18441] = "English - Singapore",
[7177] = "English - South Africa",
[11273] = "English - Trinidad",
[12297] = "English - Zimbabwe",
[1061] = "Estonian",
[1080] = "Faroese",
[1065] = "Farsi",
[1124] = "Filipino",
[1035] = "Finnish",
[1036] = "French - France",
[2060] = "French - Belgium",
[11276] = "French - Cameroon",
[3084] = "French - Canada",
[9228] = "French - Democratic Rep. of Congo",
[12300] = "French - Cote d'Ivoire",
[15372] = "French - Haiti",
[5132] = "French - Luxembourg",
[13324] = "French - Mali",
[6156] = "French - Monaco",
[14348] = "French - Morocco",
[58380] = "French - North Africa",
[8204] = "French - Reunion",
[10252] = "French - Senegal",
[4108] = "French - Switzerland",
[7180] = "French - West Indies",
[1122] = "French - West Indies",
[1127] = "Fulfulde - Nigeria",
[1071] = "FYRO Macedonian",
[1110] = "Galician",
[1079] = "Georgian",
[1031] = "German - Germany",
[3079] = "German - Austria",
[5127] = "German - Liechtenstein",
[4103] = "German - Luxembourg",
[2055] = "German - Switzerland",
[1032] = "Greek",
[1135] = "Greenlandic",
[1140] = "Guarani - Paraguay",
[1095] = "Gujarati",
[1128] = "Hausa - Nigeria",
[1141] = "Hawaiian - United States",
[1037] = "Hebrew",
[1081] = "Hindi",
[1038] = "Hungarian",
[1129] = "Ibibio - Nigeria",
[1039] = "Icelandic",
[1136] = "Igbo - Nigeria",
[1057] = "Indonesian",
[1117] = "Inuktitut",
[2108] = "Irish",
[1040] = "Italian - Italy",
[2064] = "Italian - Switzerland",
[1041] = "Japanese",
[1158] = "K'iche",
[1099] = "Kannada",
[1137] = "Kanuri - Nigeria",
[2144] = "Kashmiri",
[1120] = "Kashmiri (Arabic)",
[1087] = "Kazakh",
[1107] = "Khmer",
[1159] = "Kinyarwanda",
[1111] = "Konkani",
[1042] = "Korean",
[1088] = "Kyrgyz (Cyrillic)",
[1108] = "Lao",
[1142] = "Latin",
[1062] = "Latvian",
[1063] = "Lithuanian",
[1134] = "Luxembourgish",
[1086] = "Malay - Malaysia",
[2110] = "Malay - Brunei Darussalam",
[1100] = "Malayalam",
[1082] = "Maltese",
[1112] = "Manipuri",
[1153] = "Maori - New Zealand",
[1146] = "Mapudungun",
[1102] = "Marathi",
[1148] = "Mohawk",
[1104] = "Mongolian (Cyrillic)",
[2128] = "Mongolian (Mongolian)",
[1121] = "Nepali",
[2145] = "Nepali - India",
[1044] = "Norwegian (Bokmål)",
[2068] = "Norwegian (Nynorsk)",
[1154] = "Occitan",
[1096] = "Oriya",
[1138] = "Oromo",
[1145] = "Papiamentu",
[1123] = "Pashto",
[1045] = "Polish",
[1046] = "Portuguese - Brazil",
[2070] = "Portuguese - Portugal",
[1094] = "Punjabi",
[2118] = "Punjabi (Pakistan)",
[1131] = "Quecha - Bolivia",
[2155] = "Quecha - Ecuador",
[3179] = "Quecha - Peru CB",
[1047] = "Rhaeto-Romanic",
[1048] = "Romanian",
[2072] = "Romanian - Moldava",
[1049] = "Russian",
[2073] = "Russian - Moldava",
[1083] = "Sami (Lappish)",
[1103] = "Sanskrit",
[1084] = "Scottish Gaelic",
[1132] = "Sepedi",
[3098] = "Serbian (Cyrillic)",
[2074] = "Serbian (Latin)",
[1113] = "Sindhi - India",
[2137] = "Sindhi - Pakistan",
[1115] = "Sinhalese - Sri Lanka",
[1051] = "Slovak",
[1060] = "Slovenian",
[1143] = "Somali",
[1070] = "Sorbian",
[3082] = "Spanish - Spain (Modern Sort)",
[1034] = "Spanish - Spain (Traditional Sort)",
[11274] = "Spanish - Argentina",
[16394] = "Spanish - Bolivia",
[13322] = "Spanish - Chile",
[9226] = "Spanish - Colombia",
[5130] = "Spanish - Costa Rica",
[7178] = "Spanish - Dominican Republic",
[12298] = "Spanish - Ecuador",
[17418] = "Spanish - El Salvador",
[4106] = "Spanish - Guatemala",
[18442] = "Spanish - Honduras",
[22538] = "Spanish - Latin America",
[2058] = "Spanish - Mexico",
[19466] = "Spanish - Nicaragua",
[6154] = "Spanish - Panama",
[15370] = "Spanish - Paraguay",
[10250] = "Spanish - Peru",
[20490] = "Spanish - Puerto Rico",
[21514] = "Spanish - United States",
[14346] = "Spanish - Uruguay",
[8202] = "Spanish - Venezuela",
[1072] = "Sutu",
[1089] = "Swahili",
[1053] = "Swedish",
[2077] = "Swedish - Finland",
[1114] = "Syriac",
[1064] = "Tajik",
[1119] = "Tamazight (Arabic)",
[2143] = "Tamazight (Latin)",
[1097] = "Tamil",
[1092] = "Tatar",
[1098] = "Telugu",
[1054] = "Thai",
[2129] = "Tibetan - Bhutan",
[1105] = "Tibetan - People's Republic of China",
[2163] = "Tigrigna - Eritrea",
[1139] = "Tigrigna - Ethiopia",
[1073] = "Tsonga",
[1074] = "Tswana",
[1055] = "Turkish",
[1090] = "Turkmen",
[1152] = "Uighur - China",
[1058] = "Ukrainian",
[1056] = "Urdu",
[2080] = "Urdu - India",
[2115] = "Uzbek (Cyrillic)",
[1091] = "Uzbek (Latin)",
[1075] = "Venda",
[1066] = "Vietnamese",
[1106] = "Welsh",
[1160] = "Wolof",
[1076] = "Xhosa",
[1157] = "Yakut",
[1144] = "Yi",
[1085] = "Yiddish",
[1130] = "Yoruba",
[1077] = "Zulu",
[1279] = "HID (Human Interface Device)",
} &default = function(n: count): string { return fmt("keyboard-%d", n); };
}

View file

@ -0,0 +1,19 @@
# Generated by binpac_quickstart
signature dpd_rdp_client_request {
ip-proto == tcp
payload /.*Cookie: mstshash\=.*/
enable "rdp"
}
signature dpd_rdp_client_header {
ip-proto == tcp
payload /.*Duca.*(rdpdr|rdpsnd|drdynvc|cliprdr).*/
enable "rdp"
}
signature dpd_rdp_server_response {
ip-proto == tcp
payload /.*McDn.*/
enable "rdp"
}

View file

@ -0,0 +1,200 @@
@load ./consts
module RDP;
export {
redef enum Log::ID += { LOG };
type Info: record {
## Timestamp for when the event happened.
ts: time &log;
## Unique ID for the connection.
uid: string &log;
## The connection's 4-tuple of endpoint addresses/ports.
id: conn_id &log;
## Cookie value used by the client machine.
## This is typically a username.
cookie: string &log &optional;
## Keyboard layout (language) of the client machine.
keyboard_layout: string &log &optional;
## RDP client version used by the client machine.
client_build: string &log &optional;
## Hostname of the client machine.
client_hostname: string &log &optional;
## Product ID of the client machine.
client_product_id: string &log &optional;
## Name of the server.
server_name: vector of string &log &optional;
## Authentication result for the connection. This value is extracted from the payload for native authentication.
## TODO: Perform heuristic authentication determination for NLA.
authentication_result: string &log &optional;
## Encryption level of the connection.
encryption_level: string &log &optional;
## Encryption method of the connection.
encryption_method: string &log &optional;
## Track status of logging RDP connections.
done: bool &default=F;
};
## Variable to track if NTLM authentication is used.
global ntlm = F;
## Size in bytes of data sent by the server at which the RDP connection is presumed to be successful (NTLM authentication only).
const authentication_data_size = 1000 &redef;
## Event that can be handled to access the rdp record as it is sent on
## to the loggin framework.
global log_rdp: event(rec: Info);
}
const ports = { 3389/tcp };
redef likely_server_ports += { ports };
event bro_init() &priority=5
{
Log::create_stream(RDP::LOG, [$columns=Info, $ev=log_rdp]);
Analyzer::register_for_ports(Analyzer::ANALYZER_RDP, ports);
}
redef record connection += {
rdp: Info &optional;
};
function rdp_done(c: connection, done: bool)
{
if ( done )
{
c$rdp$done = T;
# Not currently implemented
# if ( ntlm && use_conn_size_analyzer )
# {
# if ( c$resp$size > authentication_data_size )
# c$rdp$authentication_result = "Success (H)";
# else c$rdp$authentication_result = "Undetermined";
# }
if ( c$rdp?$authentication_result && ( ! c$rdp?$encryption_method || ! c$rdp?$encryption_level ) )
Reporter::error(fmt("Error parsing RDP security data in connection %s",c$uid));
Log::write(RDP::LOG, c$rdp);
skip_further_processing(c$id);
set_record_packets(c$id, F);
}
}
event rdp_tracker(c: connection)
{
if ( c$rdp$done )
return;
local id = c$id;
if ( ! connection_exists(id) )
{
rdp_done(c,T);
return;
}
lookup_connection(id);
if ( connection_exists(id) )
{
# If the RDP connection has been alive for more than 5secs, log it
# This duration should be sufficient to collect the data that needs to be logged
local diff = network_time() - c$rdp$ts;
if ( diff > 5secs )
{
rdp_done(c,T);
return;
}
}
# schedule the event to run again if necessary
schedule +5secs { rdp_tracker(c) };
}
function set_session(c: connection)
{
if ( ! c?$rdp )
{
c$rdp = [$ts=network_time(),$id=c$id,$uid=c$uid];
add c$service["rdp"];
}
}
event connection_state_remove(c: connection) &priority=-5
{
# Log the RDP connection if the connection is removed but the session has not been marked as done
if ( c?$rdp && ! c$rdp$done )
rdp_done(c,T);
}
event rdp_native_client_request(c: connection, cookie: string) &priority=5
{
if ( "Cookie" in clean(cookie) )
{
set_session(c);
local cookie_val = sub(cookie,/Cookie.*\=/,"");
c$rdp$cookie = sub(cookie_val,/\x0d\x0a.*$/,"");
schedule +5secs { rdp_tracker(c) };
}
}
event rdp_native_client_info(c: connection, keyboard_layout: count, build: count, hostname: string, product_id: string) &priority=5
{
set_session(c);
c$rdp$keyboard_layout = languages[keyboard_layout];
c$rdp$client_build = builds[build];
c$rdp$client_hostname = gsub(cat(hostname),/\\0/,"");
c$rdp$client_product_id = gsub(cat(product_id),/\\0/,"");
schedule +5secs { rdp_tracker(c) };
}
event rdp_native_authentication(c: connection, result: count) &priority=5
{
set_session(c);
c$rdp$authentication_result = results[result];
schedule +5secs { rdp_tracker(c) };
}
event rdp_native_server_security(c: connection, encryption_method: count, encryption_level: count, random: string, certificate: string) &priority=5
{
set_session(c);
c$rdp$encryption_method = encryption_methods[encryption_method];
c$rdp$encryption_level = encryption_levels[encryption_level];
schedule +5secs { rdp_tracker(c) };
}
event rdp_ntlm_client_request(c: connection, server: string) &priority=5
{
set_session(c);
ntlm = T;
if ( ! c$rdp?$server_name )
c$rdp$server_name = vector();
c$rdp$server_name[|c$rdp$server_name|] = server;
schedule +5secs { rdp_tracker(c) };
}
event rdp_ntlm_server_response(c: connection, server: string) &priority=5
{
set_session(c);
ntlm = T;
if ( ! c$rdp?$server_name )
c$rdp$server_name = vector();
c$rdp$server_name[|c$rdp$server_name|] = server;
schedule +5secs { rdp_tracker(c) };
}
event rdp_debug(c: connection, remainder: string)
{
Reporter::error(fmt("Debug RDP data generated in connection %s: %s",c$uid,remainder));
}