[Bro-Dev] changing Notice::policy mechanism

Seth Hall seth at icir.org
Wed Nov 7 14:04:28 PST 2012


On Nov 7, 2012, at 1:34 PM, "Siwek, Jonathan Luke" <jsiwek at illinois.edu> wrote:

> switch trigger(n: MyInfo) &case=(n$trigger==Bad) &priority=-5
>    {
>    this_stuff_never_happens();
>    }


Jon and I chatted about this for a while and I *really* don't like the &case attribute and I don't like the switch keyword much either.  I think that making this switch-like is confusing because it's not really that much like a switch, it's more like a ladder of function bodies (I don't know of a comparison to make with a feature of another language).  I think that the &case attribute would be confusing too because if you had larger conditions it would start to get unmanageable quickly and then you fall back to doing a block condition at the top of the code block which is already a pretty well established convention in Bro scripts, like this…

if ( n$note != Some_Notice )
	return;

Instead of using the "policy" keyword, how does everyone feel about "rule"?  It would probably be confusing to people coming from Snort and Suricata, but I'm not overly concerned about that.  To try and make my case, I got notice policies from a couple of sites.  These are real world, actively used notice policies.

Current style at site 1…

redef Notice::policy += {
      [$action = Notice::ACTION_BLOCK,
       $pred(n: Notice::Info) = { return n$note == SSH::Password_Guessing && n?$src && !Site::is_local_addr(n$src) && !Site::is_private_addr(n$src) && !(n$src in external_ssh_scanners_whitelist || n$src in planetlab_hosts); } ]
};

redef Notice::policy += {
      [$action = Notice::ACTION_EMAIL,
       $pred(n: Notice::Info) = { return n$note == SSH::Password_Guessing && n?$src && ( Site::is_local_addr(n$src) || Site::is_private_addr(n$src) ) && !(n$src in internal_ssh_scanners_whitelist || n$src in planetlab_hosts); } ]
};

redef Notice::policy += {
      [$action = Notice::ACTION_EMAIL,
       $pred(n: Notice::Info) = { return n$note == HTTP::Malware_Hash_Registry_Match; } ]
};

redef Notice::policy += {
      [$action = Notice::ACTION_EMAIL,
       $pred(n: Notice::Info) = { return n$note == FTP::Site_Exec_Success; } ]
};

redef Notice::policy += {
      [$action = Notice::ACTION_EMAIL,
       $pred(n: Notice::Info) = { return n$note == SSH::Watched_Country_Login; } ]
};

redef Notice::policy += {
      [$action = Notice::ACTION_EMAIL, $suppress_for = 1 day,
       $pred(n: Notice::Info) = { return n$note == Software::Vulnerable_Java; } ]
};	


New proposed style at site 1…

rule Notice::policy(n: Notice::Info)
	{
	if ( n$note == SSH::Password_Guessing && 
	     n?$src && 
	     !Site::is_local_addr(n$src) &&
	     !Site::is_private_addr(n$src) && 
	     !(n$src in external_ssh_scanners_whitelist || n$src in planetlab_hosts) )
		{
		add n$actions[Notice::ACTION_BLOCK];
		add n$actions[Notice::ACTION_EMAIL];
		}
	}

rule Notice::policy(n: Notice::Info)
	{
	if ( n$note == HTTP::Malware_Hash_Registry_Match )
		add n$actions[Notice::ACTION_EMAIL];

	else if ( n$note == FTP::Site_Exec_Success )
		add n$actions[Notice::ACTION_EMAIL];
	
	else if ( n$note == SSH::Watched_Country_Login )
		add n$actions[Notice::ACTION_EMAIL];

	else if ( n$note == Software::Vulnerable_Java )
		{
		n$suppress_for = 1day;
		add n$actions[Notice::ACTION_EMAIL];
		}
	}


Current style at site 2…

const dont_email_types: set[Notice::Type] = {
    SSL::Invalid_Server_Cert,
    SSH::Login,
    HTTP::MD5,
};

redef Notice::policy += {
        [$pred(n: Notice::Info) = { return (n$note in Notice::block_types); },
         $action = ACTION_BLOCK,
         $priority = 10],
};

redef Notice::policy += { [$action = Notice::ACTION_ALARM, $priority = 0,
                           $pred(n: Notice::Info) = { return (n$note !in dont_email_types);}
                          ] };
    
redef Notice::policy += { [$action = Notice::ACTION_LOG, $priority = 10, $halt=T,
                           $pred(n: Notice::Info) = { return (n$note == HTTP::SQL_Injection_Victim && !Site::is_local_addr(n$src));}
                          ] };

redef Notice::policy += { [$action = Notice::ACTION_LOG, $priority = 10, $halt=T,
                           $pred(n: Notice::Info) = { return (n$note == HTTP::SQL_Injection_Attacker && Site::is_local_addr(n$src));}
                          ] };

New proposed style at site 2...

const dont_email_types: set[Notice::Type] = {
    SSL::Invalid_Server_Cert,
    SSH::Login,
    HTTP::MD5,
};

redef Notice::emailed_types += {
    #DNS::EXTERNAL_FOREIGN_DNS,
    HTTP::IncorrectFileTypeBadHost,
    HTTP::SQL_Injection_Victim,
};


rule Notice::policy(n: Notice::Info) &priority=10
	{
	if ( n$note in Notice::ipblocker_types )
		add n$actions[ACTION_BLOCK];
	}

rule Notice::policy(n: Notice::Info) &priority=0
	{
	if ( n$note !in dont_email_types)
		{
		add n$actions[ACTION_ALARM];
		}
	}

rule Notice::policy(n: Notice::Info) &priority=10
	{
	if ( (n$note == HTTP::SQL_Injection_Victim && !Site::is_local_addr(n$src)) ||
	     (n$note == HTTP::SQL_Injection_Attacker && Site::is_local_addr(n$src)) )
	     {
	     n$action = ACTION_LOG;
	     return F;
	     }
	return T;
	}


I think the new style is a lot clearer and easier to work with in both cases, but I assume this will still require more discussion. :)

  .Seth

--
Seth Hall
International Computer Science Institute
(Bro) because everyone has a network
http://www.bro-ids.org/




More information about the bro-dev mailing list