Skip to content
Switch branches/tags

Latest commit


Git stats


Failed to load latest commit information.
Latest commit message
Commit time

Contributed Bro Scripts


The roam.bro script collects IP-to-MAC mappings (and vice versa) of machines that may have more than one IP address over time due to a DHCP server in the network.

When keeping per-IP-address state, it could well be that the address becomes invalid because the client's DHCP lease expired or because it received a new IP address after rejoining the network. Ideally, this state would roam with the user. But many Bro script data structures use per-address indices and would mechanistically instantiate state for a new client even though it merely reappeared under a new IP address. To incorporate the notion of roaming, roam.bro makes available two data structures that script writers can use:

global ip_to_mac: table[addr] of string
&read_expire = alias_expiration &synchronized;
global mac_to_ip: table[string] of set[addr]
&read_expire = alias_expiration &synchronized;

Event handlers for the dhcp_ack and arp_reply events populate these tables. For example, the sidejacking script (see below) makes use of roam.bro to test whether a certain client IP address is an alias of another IP address:


function is_aliased(client: addr, ctx: cookie_context) : bool {

if (client in Roam::ip_to_mac) {

local mac = Roam::ip_to_mac[client]; if (mac == ctx$mac && mac in Roam::mac_to_ip

&& client in Roam::mac_to_ip[mac]) return T;


return F;


If the two tables are not accessed for more than the alias_expiration, the entry will expire. It is possible to redefine the expiration interval:

redef Roam::alias_expiration = 7 days;

Requires Bro 1.5

Author: Matthias Vallentin


The sidejack.bro script detects the reuse of session cookies in different contexts. Sidejacking is also known as cookie hijacking and means that an attacker captured a session cookie of a victim to reuse that session. Off-the-shelf tools like Firesheep implement this attack as a Firefox extension, which makes this attack accessible to the masses.

In its default settings, the script raises a SessionCookieReuse notice when the same session cookie is seen from different user agents. If in addition the IP addresses do not match, a Sidejack notice is being triggered.

There exist various options to tweak the behavior of the script. First, the notion of a user can be changed. In flat IP address space, it makes sense to identify a user by its IP address, but this would fail in a NAT environment where a single IP accommodates several users. For NAT scenarios, one could define a user as a pair of IP address and USER-AGENT header. For large NATs or NATs with identically configured machines, this latter notion of user could be prone to false positives. The user can change the definition of a user via

redef HTTP::user_is_ip = F;

Another issue poses the presence of absence of link-layer context. Consider a hotspot or coffeeshop network operator with a private IP space. If Bro can see DHCP or ARP traffic, we can crisply identify a user by its MAC address and do not have to resort to high-level notions, such as provided by HTTP headers. In a static setup, however, this context will likely not be available. At the same time, if a different address reuses a session cookie in a static IP topology, we probably observed a sidejacking attack. Furthermore, if the same address uses the same session cookie from a different user agent, we report such activity. By setting

redef HTTP::use_aliasing = T;

one tells Bro to use keep track of multiple IP addresses for the same host via roam.bro. It makes only sense to set this flag when Bro actually sees DHCP or ARP traffic.

There is another subtlety: the cookie header consists of a list of key-value pairs, yet only a subset of those represent a user session while the others could be random. Simply comparing the entire cookie string against a value seen in the past would thus be prone to false negatives. Hence we have to restrict ourselves to the relevant session-identifying subset. In fact, this is how Firesheep works: it ships with site-specific handlers that define the cookie keys to extract and then sets only those to impersonate a user. This motivates the following design: if a specification for a particular service is available, restrict the cookie to the relevant fields, and otherwise use the cookie as a whole. The default set of known services that ships with the detector is based on all handlers Firesheep currently implements. To extend the detection to all cookies, one can set

redef HTTP::known_services_only = F;

Finally, the timeout for cookie expiration can be adjusted, e.g.,

redef HTTP::cookie_expiration = 1 day;

If a cookie is not seen after the cookie_expiration, the associated state is removed. More information about the script can be found at SidejackingBlogPost.

Requires Bro 2.x.

Author: Matthias Vallentin

Contributors: Jordi Ros-Giralt (Reservoir Labs)


The mime-attachment.bro script extracts MIME entities from a STMP session and reports suspicious email attachments, and optionally saves them to disk. Storing attachment on disk allows for powerful out-of-the-loop post-processing, such as scanning office documents for malicious JavaScript or executables for viruses.

The script works by registering a callback handler for the CONTENT-TYPE header in an SMTP session. Then both MIME type and the name of the attachment is examined. If either looks suspicious, Bro generates a SensitiveMIMEType or SensitiveExtension notice. The user can customize the the analyzer behavior in many ways. To change the directory where the attachments are stored on disk, one can redefine the attachment_dir variable:

redef Email::attachment_dir = "foo";

The script stores attachments by default, but this behavior can easily changed via:

# Whether attachments with sensitive MIME types should be stored.
redef Email::store_sensitive_mime_types = F;

# Whether attachments with sensitive file extensions should be stored.
redef Email::store_sensitive_extensions = F;

It is also possible to restrict or extend the regular expression used to determine whether an attachment is sensitive or not:

# Deem only application\/octet-stream as suspicious.
redef Email::sensitive_mime_types = /application\/octet-stream;

# Restrict sensitive extensions to office documents and executables.
redef Email::sensitive_extensions =
  | /[dD][oO][cC][xX]?$/
  | /[xX][lL][sS]$/
  | /[pP][pP][sStT]$/
  | /[eE][xX][eE]$/
  | /[cC][oO][mM]$/
  | /[bB][aA][tT]$/;

The script generates a file of the form <ID>-<filename> where ID is a unique attachment ID that is monotonically increasing and filename is the name of the attachment or just the MIME type if the attachment does not have a name.

Requires Bro 1.5

Author: Matthias Vallentin


This script is the Bro 1.5 scan detector ported to Bro 2.0.

The script has evolved over many years and is quite a mess right now. We have adapted it to work with Bro 2.x, but eventually Bro 2.x will get its own rewritten and generalized scan detector.

In addition, there's scan.cluster.bro that adapts scan.bro to work in cluster settings. It mimics the default 1.5 configuration as installed by BroControl.

Requires Bro 2.0

Author: Many over many years.


Misc. Bro scripts



No releases published


No packages published