Thursday, December 18, 2008

New Project: Relationship Oriented Networking

In January we will begin a new project that considers a "Relationship Oriented Network". That is, an architecture that utilizes social graphs across protocols and services to provide users with more convenient and trustworthy communication. A description of the project is available. This project is joint work with Case Western Reserve University. Thoughts on such topics are very much welcome.

Draft Paper on Port Randomization

One technique proposed to mitigate the problems blind attackers can cause by injecting traffic into some connection is to carefully choose the transport layer ephemeral port number. This makes it difficult for an attacker to spoof traffic to some valid endpoint and have that traffic acted upon. A number of port selection schemes have been developed. We add to this list and evaluate the known techniques in the following draft paper. Comments welcome.

Mark Allman. Comments On Selecting Ephemeral Ports, December 2008.

Monday, December 8, 2008

Bro Issue Tracker

The Bro team is happy to announce the new Bro Issue Tracker. Feel free to submit your favorite bug there (and the other one too!)

Bro Workshop 2009

Update: The workshop has a home page now.

Update: The workshop has filled up already but we have set up a waiting list in case space becomes available.

The Bro team and the Lawrence Berkeley National Lab are pleased to announce the "Bro Workshop 2009", a 2.5-day Bro training event that will take place in Berkeley, CA, on Feb 10-12 2009.

The workshop is primarily targeted at site security personnel wishing to learn more about how Bro works, how to use its scripting language and how to generally customize the system based on a site's local policy.

Similar to the 2007 workshop, the agenda will be an informal mix of tutorial-style presentations and hands-on lab sessions. No prior knowledge about using Bro is assumed though attendees should be familiar with Unix shell usage as well as with typical networking tools like tcpdump and Wireshark.

All participants are expected to bring a Unix-based (Linux, Mac OS X, FreeBSD) laptop with a working Bro configuration. We will provide sample trace files to work with.

The 2009 workshop will be hosted by the Lawrence Berkeley National Lab. The registration is now now open. We will soon provide a web site with more detailed location information. To facilitate a productive lab environment, the number of attendees will be limited to 30 people. A nominal registration fee of $50 will be charged.

We also expect to have time for 2-3 case-study presentations from people using Bro in their environments. If you have something interesting to talk about, please contact Robin via mail.

Friday, October 31, 2008

CCS'08 paper on measuring spam conversion rates

At this week's CCS conference we presented a measurement study of spam conversion rates, based on infiltration of a real-world botnet responsible for billions of spams: the Storm botnet. This is joint work with UCSD as part of our CCIED effort.

Friday, October 17, 2008

Bro 1.4 released

We've released a new distribution of our Bro intrusion detection system, version 1.4.  This release includes significant new functionality as well as numerous refinements and fixes, per the changelog entries.

Thursday, October 16, 2008

cFlow: A High-Performance Cluster Front-End

cPacket Networks has just announced their new product cFlow, a high-performance load-balancer that implements the traffic distribution scheme we developed for the Bro Cluster. As our initial research prototypes were not suitable for a reliable production deployment, the Lawrence Berkeley National Lab collaborated with the cPacket team to develop this appliance, which delivers a load balancing front-end at full 10 GigE line rate. cPacket did a great job with this, and the cFlow will become a key component of the Lab's new, high-performance intrusion detection infrastructure. See the full press release for more information.

Tuesday, September 30, 2008


Abstract: DNS resolvers are vulnerable to many attacks on their network communication, ranging from blind attacks to full men-in-the-middle. Although a full man-in-the-middle can only be countered with cryptography, there are many layers of defenses which apply to less powerful attackers. Of particular interest are defenses which only require changing the DNS resolvers, not the authoritative servers or the DNS protocols. This document begins with a taxonomy of attacker capabilities and desires, and then discusses defenses against classes of attackers, including detecting non-disruptive attacks, entropy budgeting, detecting entropy stripping, semantics of duplication, and cache policies to eliminate "race-until-win" conditions. Proposed defenses were evaluated with traces of network behavior.

Friday, August 22, 2008

Some More Thoughts on Protecting DNS

I posted the following to the namedroppers list, and I'm crossposting here for comments. Again, this is "in progress", and largely shaped by discussions with many people, NOT a finished work. Comments are greatly appreciated.

One thought (again, I don't know how much this has been hashed out) is how robust do DNS resolvers REALLY need to be?

Any comments on the following?

I personally believe that resolvers should be robust to anything short of a man-in-the-middle ("Aware & Blocking"), yet man-in-the-middle is almost irrelevant for purposes of defending DNS. [1] Thus as long as the DNS resolvers are strong to anything short of the man-in-the-middle, its good in practice.

At the same time, such robustness must ONLY involve changes to the resolvers: the resolvers should be able to protect themselves, without relying on the authoritative servers making changes (although authoritative servers may suffer more load, especially servers which return some out-of-standard nonsenses.). [2]

And probabilistic protection is perfectly good. We don't need perfect protection against blind attacks, we just need to ensure that the attacker resources involved are far better spent elsewhere.

My thoughts:

Against blind attacks, I believe the following principles should apply:

  • No birthday attacks, of course.
  • >=20b of entropy for purposes of protecting the transaction [3]
  • >=40b of entropy for purposes of protecting the cache [4]
  • Detecting when network entropy (port #) is reduced or eliminated by an in-path network device, allowing the resolver to accurately estimate the entropy it is generating in the requests.
  • Detect and respond when there is .001% of a chance that a blind attack created one or more corrupt cache entries by either revalidating or voiding the cache.
  • NO "race until win" scenarios for ANY given mapping in the cache. ALL blind attacks should be either "Race once per TTL" or "Race until another race until win". Blind attacks should always cost time as well a packets. [5]

ALL of the previous principles seem doable using existing techniques (port and 0x20 randomization, duplication, a single global counter to count unsolicited replies, and some seemingly simple data acceptance policies)

Against transparent attacks, I believe the following should apply:

If a resolver, within its normal transaction timeout, receives a second or subsequent reply with a differing value but which would have been otherwise accepted (matching on TXID, port, server, 0x20, etc), this must be considered an attack on both the transaction and the cache. [6]

If the resolver is an intermediary, it MUST forward the second response back to the original requester, with the TTL for the "new" value set to 1 second.

For the resolver's cache, any entry which MAY have been potentially affected by the second reply MUST be treated as corrupted by an attack. Thus, depending on how much information is recorded and available, various cache entries may need to be voided or undone (up to all cache entries for the domain in question, if more precise record keeping is unavailable). Even if this would not be considered an attack, it doesn't actually make sense to cache anything which may have been dependent on this response.

For the final client, it is up to the client to determine what to do, but the strong suggestion is to consider this an attack and abort any transaction involving this name.

However, if the end client does not treat this as an attack and abort subsequent TCP connections to the final IP, this loss of transaction protection means that the few authorities which trigger this alert through "normal" behavior will simply see their results not cached rather than not accepted by the client.

[1] If an attacker can man-in-the-middle the naming stream of a victim, he can probably man-in-the-middle the data stream. If the end protocol desired is weak to a man-in-the-middle, reliable naming does no good. If the end protocol is robust to a man-in-the-middle, it never really trusted the DNS record.

[2] This is why I'm not a believer in DNSSEC. It has both bad network effects (both the resolver and authority needs to change behavior, yet the changed behavior only protects the intersection of the two sets, so neither resolvers nor authorities have strong internal incentives to deploy), yet does not actually provide, to my mind, all that much meaningful system security because the other options available to a man-in-the-middle in practice.

[3] Blind transaction attacks, when combined with protections that provide "race once per TTL per name", as far as I can tell, only work against some seriously broken protocols. By specifying a different level of protection for transactions and the cache, this allows duplication to protect the cache while still successfully resolving (but NOT caching) sites which return different values on back-to-back queries when duplication is needed to meet the entropy budget.

[4] Anyone who wants to launch a TB DOS to poison my cache has better things to do.

[5] I believe that the proper policy on accepting data into the cache can provide this, combined with treating a failure to lookup a name as an event with a ~30 second TTL. This property is an important COMPLEMENT to increased entropy, not a substitute. "Race until win" does not reduce the number of packets an attacker requires, only the time period.

[6] This will occur with high probability whenever there is a blind attack that doesn't also block the authoritative server or create traffic with a DOS condition. It will ALSO occur with high probability if an attacker is able to directly observe the request to craft a reply, but is not fully in path. More importantly, a preliminary survey survey suggests that only a few authorities actually do return such nonsense.

Tuesday, August 19, 2008

Entropy, Blind Attacks, and DNS

The following is work-in-progress. Part of the point of a blog is to look for feedback. So feedback is greatly appreciated. Its also to keep others from making my mistakes when thinking about the problem. Additionally, there may be things wrong in this post. Anything wrong is my fault. Feedback can be sent in email to nweaver at ICSI dot Berkeley dot EDU. Minor edits added 8/20

This post will focus on DNS blind attacks, detection strategies, and responses for protecting DNS resolvers. But first some background. There are at least four major properties of DNS attacks.

Blind vs Aware: In a blind attack, the attacker does not know the entropy sources (eg, TXID, port selection, captialization) of the request. In an aware attack, the attacker knows this information.

Transparent vs Blocking: In a transparent attack, the attacker is unable to block the normal authoritative server's response. In a blocking attack, the attacker can block the DNS server's response.

Direct Record vs glue: In a Direct Record attack, the attacker is only interested in corrupting the actual query, eg, that point to EVIL. In a glue attack, the attacker is interested in producing corrupted answer, authoritative or additional records which are accepted by the server beyond the server's request, eg, that points to and points to EVIL.

Transaction vs cache: In a transaction attack, the attacker only needs to corrupt the client which made the actual query. A cache attack requires that the resolver not just forward the attacker's value, but also cache it to use for future responses.

For example, Kaminski's attack is a "Blind Glue Cache" attack: the goal is to use a blind attack to cause the resolver to cache a bad authority or additional record, causing subsquent lookups for the target domain to go to the attacker's "authoritative" server.

There are many MANY variants possible, but I believe (if I'm wrong, PLEASE tell me) that all require the victim resolver to cache more than just the requested mapping of A goes to some value, because this enables the attacker to "Race until win against garbage" instead of "Race once and retry after TTL expiration". Normally, it is also a "Transparent" attack, but it could also involve a DOS of the authoritative server or enough traffic that the server's authoritative response is not returned.

Likewise, a man-in-the-middle is a "Aware and Blocking" attacker: he sees all packets and can ensure that only his response arrives, and nothing short of DNSSEC (or equivelent) can prevent a man-in-the-middle attack on DNS.

Blind attacks are actually easy to detect. Any blind attack which has a probability of succeeding will generate a large number of unsolicited DNS replies: DNS answers where the reply does not correspond to a request because it uses a different transaction ID and/or port. In our in-progress DNS cache poisoning detector, dns-poison.bro, these alerts are collected in the dns_weirds.log as "Unsolicited DNS Replies". I'd assume there is a similar snort rule available. (Note, the bro code is VERY experimental, and should NOT be viewed as authoritative. It is included mostly for interest and experimentation).

However, there are some issues that arise. To begin with, there can be false positives in the IDS. The first (marked in dns_weirds.log as "Since there has been no previous DNS traffic on this 4-tuple, we are ignoring it") can occur when the DNS requesting packet was dropped by the monitor so the IDS only sees the reply. The second is that a nontrivial number of servers (~100 when seen from ICSI over a roughly 10 day period) will generate this alert spontaneously, sending invalid replies to accompany valid replies. Thus a LOW rate of alerts is to be expected.

But a bigger problem is how to ACT on this information. There have been many proposals (I've been guilty of one myself) that by maintaining a count of failures per remote server, one could build a detection and response cycle against blind attacks into the DNS resolver without having to look for more entropy than the transaction ID.

This could work for a blind attacker who's targeting a particular authority: It doesn't require much stateholding (a single counter per authoritative server), and the response is simple: void the cache for any requests involving this authority (block "blind cache" attacks, regardless of glue policy or transparency), and observe that only limited scenarios benefit from a blind, transactional attack. [1]

However, there is a blind attack proposed by Masataka Ohta, poisted out to me by Wouter Wijngaards which can defeat such a detection and response cycle when only 16 bits of entropy (just the DNS transaction ID) is used, by generating poisoning requests targeting different domains when winning a single domain is sufficient for the attacker's goal.

As a real example, assume that the attacker has a list of 1000 domains, with targeting any single domain sufficient for his goal. At a single victim, he generates 1000 queries, on 1000 different authoritative servers, and also launches just 1000 blind responses. With just 16 bits of entropy, there is a 1.5% chance of success, and the successful packet will never tigger the alert. Thus I was WRONG: although such fine-grained detection is suitable for the IDS, it is NOT suitable for the DNS resolver as a substitute for more entropy.

But good entropy is (mostly) sufficient for countering blind attacks. If there are 32 bits of entropy (from a combination of a strongly random transaction ID, and a random source port), a blind attacker who wants a .1% chance of success would need to send rougly 4 million packets. The exact odds of success for the attacker with N bits of entropy and K attacker packets is 1 - (1 - 2^-N)^K. At 100B per packet, this would require sending 400 MB of data.

Add in a random selection of authoritative resolver (what unbound does to gain 2b of entropy) and random capitalization (David Dagon's 0x20 method) and you can easily get to 40b of entropy. Now just that .1% probability of success requires sending 1 billion packets, or 100 GB of data. Even .01% of success requires 10 GB of data.

Such an attack represents a significant DoS. If an attacker can send 100 GB of data, with spoofed source address, at your DNS resolver, to have just a .1% chance of corrupting a single cache entry, the attacker can instead make a lot more money sending 100 GB of data at a blackmail victim.

Yes, this represents a probabilistic bounds, but it is a very good bounds. Bots are a valuable resource, especially Bots capable of delivering spoofed IP packets. They can send spam, look for stolen credentials, or perform lots of other mayhem. Yet Bots which DoS are more likely to be removed, by both the ISP and end users due to the traffic. Attackers with that sort of resource aren't interested in just petty damage: they have reasons for their actions and wasting money is not one of them. "You don't need to outrun the bear, just the guy next to you".

Plus (Warning: Unbaked Speculation Ahead, feedback wanted!) one might be able to set an arbitrary bound on preventing blind, cache attacks, including Ohta's variant, by keeping a single counter of ALL unsolicited replies (rather than a per-server count which does not work). If it ever reaches the threshhold where an attacker has an X% chance of at least one success, simply invalidate the entire cache, because you don't know what's been corrupted.

This would effect a nontrivial increase in latency and traffic as the cache is repopulated, but even with a very sensitive threshold (eg .01%) and moderately poor entropy (32b), an attacker would need to send 40 MB of spoofed data just to degrade the cache performance a bit. If the cache had 1M active entries it needed to subsequently refetch, the attack would generate a few hundred MB of additional traffic to the DNS resolver from the additional requests. So there would be some amplification, but only a moderate (roughly 4x) amount to gain a very tight bounds on the blind attack.

For 40b of entropy, the attacker would have to send nearly 10 GB of data to meet this very sensitive threshold, yet would still only require fetching an additional few hundred MB of data back into the cache, a trivially small amount of amplification: the 10 GB DOS will be a far bigger effect on the server.

Finally (Warning: Still Rather Unbaked Speculation Ahead. Feedback wanted) there are many proposals to duplicate requests to increase entropy. For example David Dagon has proposed using duplication when a remote authoritative server doesn't support 0x20. I believe this can be useful also if the DNS server is behind a NAT or firewall that rewrites ports. If your resolver is behind a firewall or NAT you lose the entropy present in the port number. Since 32b of entropy is a bare minimum, and 40b is comfortable, losing nearly 16b of entropy is a big deal, and something needs to be done to bring the entropy up to a comfortable level.

Fortunatly, a resolver can check if its behind a NAT if there is a special authoritative nameserver. We have an ugly prototype: port.{anything} will return the UDP port in the lower 16 bits of the returned address. This does create a phone-home, but a resolver implementation could use such a special name to check for the presence of a NAT or other device which rewrites UDP ports. (Dispite feeling otherwise, NATs and firewalls are not actually malicious, and would not benefit from whitelisting such a test.)

Now a resolver could respond in the following way: Instead of a single query, it generates two queries for the same value, returning the first response it gets, but only caching the response if both are identical. This should protect the cache, as forcing the attacker to match both queries effectively doubles the entropy. Thus if there are only 20 bits of entropy (a 16b ID plus 4 characters of capitalization/resolver selection, because the resolver is behind a NAT), for purposes of cache poising, the blind attacker now faces effectively 40 bits of entropy.

However, this reduces protection against a blind transaction attack. For purposes of corrupting the transaction, the attacker only needs to win one race out of two. Thus instead of facing 20b of entropy for corrupting the transaction, the attacker only needs 19b, as it doubles the chance for success. Since I can come up with only limited scenarios (dealing with already broken websites) where a blind, transaction attack would be useful, this risk of transactional corruption may be acceptable. But if transaction protection is desired, the resolver needs to wait for both responses, and only return them if they agree, leaving an open issue of what to do with a highly volatile domain which returns different responses to the same request.

Thus the conclusions:

1) For IDS purposes, its easy to detect blind cache poisoning attacks, although there are some low rate false positives that operators need to be aware of.

2) For purposes of the DNS resolver, "detect and respond" to blind attacks without increasing the entropy is a bad idea: it doesn't prevent all blind attacks, instead creating a false sense of security.

3) But adding entropy, to at least 32b, ideally 40b, and the blind attack is effectively defanged.

4) For further benefit, it appears plausible that the blind caching attack against a well-randomized server could be detected and blocked, and it looks plausible to protect the cache but not transactions from blind attacks even when behind a NAT by using duplicate requests.

5) Please give me feedback! It was feedback from experts that convinced me "there is no substitute for entropy".

Much thanks to feedback from Christian Kreibich, Vern Paxson, Robin Sommer, Mattias Vallentin and Wouter Wijngaaards.

[1] The only scenario I can come up with is cookie stealing, or similar hijacking, and can actually be used against a major site. The following example is how TRADITIONAL blind cache poisoning, against a 16b transaction ID as the only entropy, can be used to intercept yahoo mail as a blind transactional attack, rather than a cache attack. eventually resolves to being which has a ttl of just 60 seconds. Thus the attacker gets the victim to go to a web page the attacker controls. This attacker code has a bit of javascript that opens up an iFrame which points to at a time the attacker choses.

When the web browser does the lookup, the attacker sends ~1000 poison attempts at the victim's DNS resolver. If it fails, ah well, no big loss, the attacker closes the iframe (by redirecting to another page) and tries again in 60 seconds. But if it succeeds, the web browser THINKS is the attacker's machine, allowing him to man-in-the-middle the browser and enabling him to get the victim's login cookie etc (which are happily transmitted in the clear!). If DNS is protected by just a 16b transaction ID, the attacker has a 1.5% chance of winning the FIRST race, and if the victim doesn't notice for an hour, the attacker has a 60% chance.

Thus, at least for the purposes of protecting Yahoo mail, even DNS transactions need to be protected with significantly more entropy. (However, this is an extreme case, and Yahoo mail is broken in so many other ways because attackers on a wireless network can do the same thing.)

Sunday, August 17, 2008

New Time Machine Release & Paper

Jointly with our colleagues at TU Berlin, we have just released a new version of the Time Machine, a high-performance packet bulk-recorder.

This is a major release providing many improvements in functionality and performance, including a NIDS interface for automatic control and retrieval. See the web page for more information about the changes.

We will present the Time Machine at the ACM SIGCOMM conference this week in Seattle, WA. The SIGCOMM paper also contains more background information, including a performance evaluation and experiences with interfacing the Time Machine to the Bro NIDS.

Wednesday, August 6, 2008

HotSec Paper on Network Visibility

We presented the following paper at HotSec last week:

Thursday, July 17, 2008

New Bro Blog from OSU

Seth Hall of The Ohio State University started A Bro Blog to share his experiences as well as some of his Bro scripts. I'm sure there will be plenty of cool stuff to be found there.

Update: I learned it's The Ohio State University. :-)

Monday, June 30, 2008

The Emerging-Bro Project

Matt Jonkman of Emerging Threats just announced an exciting new project, nicknamed Emerging-Bro. Led by CS Lee, the goal is to provide their most important, high-threat signatures in Bro's syntax on a regular basis. They also plan to provide their IP blacklists directly for Bro. That's all pretty cool, thanks for your effort guys!

Thursday, June 19, 2008

Bro's Signature Engine

Bro relies primarily on its extensive scripting language for the definition of detection policies. In addition, however, Bro also provides an independent signature language for doing low-level, Snort-style pattern matching. While signatures are not Bro's preferred detection tool, they sometimes come in handy and are closer to what many people are familiar with from using other NIDS. This posting gives a brief overview on Bro's signatures and covers some of their technical subtleties.


The syntax of signatures is documented in Bro's reference manual; I won't duplicate that information here. Let's rather look at an example:

signature my-first-sig {
    ip-proto == tcp
    dst-port == 80
    payload /.*root/
    event "Found root!"

This signature asks Bro to match the regular expression .*root on all TCP connections going to port 80.

When the signature triggers, Bro will raise an event signature_match of the form:

event signature_match(state: signature_state, 
   msg: string, data: string)

Here, state contains more information on the connection that triggered the match (see policy/bro.init for the definition of signature_state); msg is the string specified by the signature's event statement (Found root!), and data is the last piece of payload which triggered the pattern match.

To turn such signature_match events into actual alarms, you need to load signature.bro. This script contains a default event handler which raises SensitiveSignature notices (as well as others; see the beginning of the script).

Things to keep in mind when writing signatures

  • Each signature is reported at most once for every connection, further matches of the same signature are ignored.

  • Header conditions are only evaluated for the first packet from each endpoint. If a header condition does not match the initial packets, the signature will not trigger. Bro optimizes for the most common application here, which is header conditions picking the connection to be examined closer with payload statements.

  • A number of analyzer-specific content conditions perform pattern matching on elements extracted from an application protocol dialogue. For example, http /.*passwd/ scans URLs requested within HTTP sessions. The thing to keep in mind here is that these conditions only perform any matching when the corresponding application analyzer is actually active for a connection. Note that by default, analyzers are not enabled if the corresponding Bro script has not been loaded.

    A good way to double-check whether an analyzer "sees" a connection is checking its log file for corresponding entries. If you cannot find the connection in the analyzer's log, very likely the signature engine has also not seen any application data.

  • As the name indicates, the payload keyword matches on packet payload only. You cannot use it to match on packet headers; use header conditions for that.

  • For UDP and ICMP flows, the payload matching is done on a per-packet basis; i.e., any content crossing packet boundaries will not be found. For TCP connections, the matching semantics depend on whether Bro is reassembling the connection (i.e., putting all of a connection's packets in sequence). By default, Bro is reassembling the first 1K of every TCP connection, which means that within this window, matches will be found without regards to packet order or boundaries (i.e., stream-wise matching).

  • For performance reasons, by default Bro stops matching on a connection after seeing 1K of payload; see the section on options below for how to change this behaviour. The default was chosen with Bro's main user of signatures in mind: the dynamic protocol detection works well even when examining just connection heads.

  • Regular expressions are implicitly anchored, i.e., they work as if prefixed with the ^ operator. For reassembled TCP connections, they are anchored at the first byte of the payload stream. For all other connections, they are anchored at the first payload byte of each packet. To match at arbitrary positions, you can prefix the regular expression with .*, as done in the example above.

  • To match on non-ASCII characters, Bro's regular expressions support the \x<hex> operator. CRs/LFs are not treated specially by the signature engine and can be matched on with \r and \n, respectively. Generally, Bro follows flex's regular expression syntax. See the DPD signatures in policy/sigs/dpd.bro for some examples of fairly complex payload patterns.

  • The data argument of the signature_match handler might not carry the full text matched by the regular expression. Bro performs the matching incrementally as packets come in; when the signature eventually fires, it can only pass on the most recent chunk of data.


The following options control details of Bro's matching process:

dpd_reassemble_first_packets: bool (default: T)

If true, Bro reassembles the beginning of every TCP connection (of up to dpd_buffer_size bytes, see below), to facilitate reliable matching across packet boundaries. If false, only connections are reassembled for which an application-layer analyzer gets activated (e.g., by Bro's dynamic protocol detection).

dpd_match_only_beginning : bool (default: T)

If true, Bro performs packet matching only within the initial payload window of dpd_buffer_size. If false, it keeps matching on subsequent payload as well.

dpd_buffer_size: count (default: 1024)

Defines the window size for the two preceding options. In addition, this value determines the amount of bytes Bro buffers for each connection in order to activate application analyzers even after parts of the payload have already passed through. This is needed by the dynamic protocol detection capability to defer the decision which analyzers to use.

So, how about using Snort signatures with Bro?

There was once a script, snort2bro, which converted Snort signatures automatically into Bro's signature syntax. However, in our experience this didn't turn out to be very useful because by simply using Snort signatures, one can't benefit from the additional capabilities Bro provides; the approaches of the two systems are too different. We therefore stopped maintaining the snort2bro script, and there are now many newer Snort options which it doesn't support. While the script is still part of the Bro distribution, I don't recommend using it anymore, and we will likely remove it in future versions. (If, however, anybody feels like updating the script to support the new Snort options, that would certainly still be appreciated ... It won't be exactly trivial though.)

Monday, June 9, 2008

Predicting the Resource Consumption of a NIDS

Last week at SIGMETRICS 2008, we presented a poster on Predicting the Resource Consumption of Network Intrusion Detection Systems. The extended abstract describes the work in a bit more detail; the full paper will appear at RAID 2008 later this year.

Friday, May 30, 2008

Slides from IETF P2PI meeting...

The following opinions are my own, not that of the rest of the ICSI networking group or any funder.

Here are my slides for my 5 minute talk at the IETF Peer to Peer Infrastructure meeting in Boston. In them, I argue that bulk-data P2P is not about cost savings but about cost shifting: moving the cost of providing content from the content provider to the recipient or the recipient's ISP. In particular, this cost shifting is very inefficient, greatly increasing aggregate costs, as ISP transit costs significantly more than content provider transit. This is, I believe, the root of the conflict between bulk data P2P and ISPs.

I also believe that caches are a non-starter, as they are less transport efficient than HTTP caches, are lawsuit bait for illegal content, and don't have a business rationale for the ISP to provide one for legal content.

Friday, May 2, 2008

Measurement Framework Papers at PAM

We presented two papers at PAM in Cleveland this week. Both of them involve new frameworks and systems for taking network measurements. The papers are: Both of these represent early work and comments are certainly welcome and appreciated.

Tuesday, April 22, 2008

Should PCs Grapple With Ethics?

Last week at the USENIX WOWCS workshop the following paper was presented:

Tuesday, April 15, 2008

LEET'08 paper on botnet-based spam campaign infiltration

At today's LEET'08 workshop we presented a detailed analysis of the internal workings of a large-scale spamming operation, namely that orchestrated using the Storm botnet.
  • C. Kreibich, C. Kanich, K. Levchenko, B. Enright, G. Voelker, V. Paxson, and S. Savage. On the Spam Campaign Trail. First USENIX Workshop on Large-scale Exploits and Emergent Threats (LEET '08), 2008, San Francisco, USA.
This is joint work with UCSD as part of our CCIED effort.

Tuesday, April 8, 2008

An Interactive Shell For Operating Bro Setups

For the Bro Cluster, we are developing an interactive shell to facilitate easy operation of such multi-system setups. The shell provides a customizable framework for all the common tasks involved in maintaining a Bro setup, such as configuration & installation, log rotation & archival, mail notifications, profiling, etc.

While we originally intended the shell to be used with clusters, it seems only natural to provide the same functionality for traditional, single-system Bro setups as well. Consequently, we added a standalone mode to the shell, and the freshly updated shell documentation explains how to set this up.

Be careful though: this is still under development and requires an unstable development version of Bro. Things are still in flux and the shell is not suitable for production use at this time. If however the standalone mode turns out to work well, it might at some point replace Bro's current BroLite run-time framework, which is no longer maintained.

Wednesday, April 2, 2008

Note About Peer Review

A new short note on refereeing appears in the editorial zone of the April issue of CCR:
  • Mark Allman. Thoughts on Reviewing. ACM Computer Communication Review, Editorial Contribution, 38(2), April 2008.
Comments welcome!

ICSI's CyberTrust Poster

Our Poster from the CyberTrust PI Meeting is online. This acts as a very high level summary of four of our current focuses: Understanding the underground economy, developing situational awareness across time and space, parallelizing intrusion detection, and web tripwires.

Monday, March 31, 2008

Evaluating Congestion Control Mechanisms

Two new documents have been published on the evaluation of congestion control mechanisms. A document on "Metrics for the Evaluation of Congestion Control Mechanisms" has, after a slow process, appeared as an Informational RFC, RFC 5166. This is a product of the Transport Modeling Research Group. In addition, the short, multi-author PFLDnet 2008 paper Towards a Common TCP Evaluation Suite has been published.

Thursday, March 27, 2008

Telling Bro What's Important

One of the easiest ways to customize Bro is writing a local notice policy. Bro can detect a great number of potentially interesting situations, and the notice policy tells which of them the user wants to be escalated into a alarms. The notice policy can also specify further actions to be taken, such as paging the security officer. This article gives an introduction into writing such a notice policy.

Let us start with a little bit of background on Bro's philosophy on reporting things. Bro ships with a large number of policy scripts which perform a wide variety of analyses. Most of these scripts monitor for activity which might be of interest for the administrator. However, none of these scripts assesses the importance of what it finds itself. Instead, the scripts only flag situations as potentially interesting, leaving it to the local configuration to define which of them are in fact alarm-worthy. This decoupling of detection and reporting allows Bro to address the different needs sites have: the definition of what constitutes an attack differs quite a bit between environments, and activity deemed malicious at one place might be fully acceptable at another.

Whenever one of Bro's analysis scripts sees something potentially interesting, it flags the situation by raising a Notice. A Notice has a type, which reflects the kind of activity which has been detected, and it is usually augmented with additional context about the situation. For example, whenever the HTTP analyzer sees a suspicious URL being requested (such as /etc/passwd), it raises a Notice of the type HTTP_SensitiveURI and augments it with the requested URL itself as well as the involved hosts.

In terms of script code, "raising a Notice" is just a call to a predefined function called NOTICE. For example, to raise an HTTP_SensitiveURI such a call could look like this:

NOTICE([$note=HTTP_SensitiveURI, $conn=connection, 
        $URL=url, ...])

If one wants to know which types of Notices a Bro script can raise, one can just grep the script for calls to the NOTICE function.

Once raised, all Notices are processed centrally. By default, all Notices are in fact automatically turned into alarms and will therefore show up in alarm.log. The local site policy can however change this default behavior, as we describe in the following.

In general, each raised Notice gets mapped to one out of a set of predefined actions. Such an action can, e.g., be to send a mail to the administrator or to simply ignore the Notice. In the current trunk, the following actions are defined:

Action Description
NOTICE_IGNORE Ignore Notice completely.
NOTICE_FILE File Notice only to notice.log; do not write an entry into alarm.log.
NOTICE_ALARM_ALWAYS Report in alarm.log.
NOTICE_EMAIL Send out a mail and report in alarm.log.
NOTICE_PAGE Page security officer and report in alarm.log.

NOTICE_ALARM_ALWAYS reflects the default behavior if no other action is defined for a Notice. All notice actions except NOTICE_IGNORE also log to notice.log.

We can define which action is taken for a Notice in two ways. The first is to generally assign an action to all instances of a particular Notice type; the second provides the flexibility to filter individual Notice instances independent of their type. We discuss both in turn.

To generally apply the same action to all instances of a specific type, we assign a notice action filter to the type. In the most simple case such a filter does directly correspond to the intended action, per the following table:

Filter Name Action
ignore_notice NOTICE_IGNORE
file_notice NOTICE_FILE
send_email_notice NOTICE_EMAIL
send_page_notice NOTICE_PAGE

(As NOTICE_ALARM_ALWAYS is the default action, there is no corresponding filter).

We map a Notice type to such a filter by adding an entry to Bro's predefined notice_action_filters table. For example, to just file all sensitive URIs into notice.log rather than turning them into alarms, we define:

@load notice-action-filters
redef notice_action_filters += {
        [HTTP_SensitiveURI] = file_notice

Notice action filters are more powerful than just directly defining an action. Each filter is in fact a script function which gets the Notice instance as a parameter and returns the action Bro should take. In general, these functions can implement arbitrary schemes to settle on an action, which is why they are called "filters". In addition to the filters mentioned above (which just return the corresponding action without further ado), Bro's default script notice-action-filters.bro also defines the following ones (and more):

Filter name Description
tally_notice_type Count how often each Notice type occurred. The totals are reported when Bro terminates as new Notices of the type NoticeTally. The original Notices are just filed into notice.log.
tally_notice_type_and_ignore Similar to tally_notice_type but discards original Notices.
file_if_remote Do not alarm if Notice was triggered by a remote address.
notice_alarm_per_orig Alarm only the first time we see the Notice type for each source address.
notice_alarm_per_orig_tally Count Notice types per source address. Totals are reported, by default, every 5 hours as new NoticeTally Notices. The original Notices are just filed into notice.log.

Such filter functions are actually pretty easy to write. Have a look at the implementations in notice-action-filters.bro if you need different behavior.

Bro's set notice_policy provides the second way to define an action to be taken for a Notice. While notice_action_filters maps all instances of a particular Notice type to the same filter, notice_policy works on individual Notice instances. Each entry of notice_policy defines (1) a condition to be matched against all raised Notices and (2) an action to be taken if the condition matches.

Here's a simple example which tells Bro to ignore all Notices of type HTTP_SensitiveURI if the requested URL indicates that an image was requested (simplified example taken from policy/notice-policy.bro):

redef notice_policy += {
  [$pred(n: notice_info) = {
     return n$note == HTTP::HTTP_SensitiveURI &&
           n$URL == /.*\.(gif|jpg|png)/; 
   $result = NOTICE_IGNORE]

While the syntax might look a bit convoluted at first, it provides a lot of flexibility by leveraging Bro's match statement. $pred defines the entry's condition in the form of a predicate written as a Bro function. The function gets passed the raised Notice and it returns a boolean indicating whether the entry applies. If the predicate evaluates to true, Bro takes the action specified by $result. (If $result is omitted, the default action for a matching entry is NOTICE_FILE).

The notice_policy set can hold an arbitrary number of such entries. For each Notice, Bro evaluates the predicates of all of them. If multiple predicates evaluate to true, it is undefined which of the matching results is taken. One can however associate a priority with an entry by adding a field $priority=<int> to its definition; see policy/notice-policy.bro for examples. In the case of multiple matches with different priorities, Bro picks the one with the highest. If $priority is omitted, as it is in the example above, the default priority is 1.

Wednesday, February 20, 2008

Making Sure Your Bro Code Does Not Leak

This is for people hacking on Bro's C++ source code. Internally, Bro's memory management is pretty complex and when writing new code it's unfortunately pretty easy to introduce memory leaks. If Bro's memory footprint keeps growing over time (hours or days), and there's no script-level state table to blame for what you see, it might be a leak in Bro's C++ event-engine.

Bro has been in use for many years and we are pretty confident that there aren't any major leaks left in the more common code paths these days. However, there's also code which isn't used very regularly and and it still happens that people run into leaks in these parts.

But most importantly, for new code it is crucial to make sure that it does not introduce new leaks. The lesson we learned in the past is that even the tiniest leak can have devastating effects when it occurs for every connection Bro analyses. Whenever you are writing code for Bro's event engine, such as a new protocol analyzer, it's a good idea to double-check that all the memory it allocates will for sure be released later. As a rule of thumb: whenever you allocate memory but cannot guarantee that it will be freed at a well-defined point of time other than termination, there's likely something wrong.

There are various tools out there which can help with leak-checking. In the past we had most success with valgrind (good but slow with large input traces) and Google's perftools. Bro has some support built in for perftools which I'll summarize in the following. Note that perftools' leak-checking works on Linux systems only at the moment.

In the past, we have found quite a few leaks in Bro with perftools and we recommend to run new code through it to see whether there's something turning up. The nice thing about perftools is that its performance is sufficiently good that one can actually run Bro with some non-trival amount of traffic, which is crucial because often leaks are in code paths not triggered when analyzing just a few connections.

To use perftools for checking Bro for leaks, get the current source code from perftools' download page. Compile and install it with the usual ./configure && make install cycle.

Next, you need to configure Bro with debugging code and enable perftools support:

   > ./configure --enable-debug --enable-perftools 
   > make 

Make sure that the output at the end of the configure run indicates that configure has indeed found the perftools installation:

                    Bro Configuration Summary
      - Debugging enabled:      yes
      - Using perftools:        yes

If it didn't find perftools, try giving it the paths to your perftools installation directly, as in the following example (replace <prefix> with whatever prefix you were using when configuring the perftools distribution):

  > export LDFLAGS=-L<prefix>/lib
  > export CFLAGS=-I<prefix>/include
  > export CPPFLAGS=-I<prefix>/include
  > export LD_LIBRARY_PATH=<prefix>/lib
  > ./configure --enable-debug --enable-perftools 

Once the configure output looks ok, compile Bro as usual with make.

The last preparation step is setting perftools' environment variable HEAPCHECK to local to activate perftool's memory checking:

  > export HEAPCHECK=local

Finally, start Bro as usual but add the option -m to the command-line, e.g,:

  > bro -m -r trace tcp

You likely want to run from a trace instead of live because the memory checking decreases Bro's performance significantly.

Once Bro terminates (which is fine to trigger via CTRL-C if necessary), perftools will output leak information into /tmp/bro.*.heap files. (There might be output saying that something "has failed" but it seems that you can you can safely ignore this.). The recorded data will only contain leaks which appeared within Bro's main packet processing loop; any leaks during initialization and termination are skipped as they won't cause any trouble during live operation.

At termination, Bro will print out a pre-built command-line to start the pprof utility. pprof is perftools' user interface to inspect the leak information, and you can just literally copy & paste the command line into your shell (except that you might want to skip the -gv option to suppress the graphical output in favor of the interactive interface)

Inside pprof, typing help shows the available commands. Most importantly, there's top which shows the top leaks as determined by perftools. See here for more information about how to interpret its output, and here for more details about perftools' heap checking in general.

Friday, February 15, 2008

Python Bindings for Broccoli

We have developed a set of Python bindings for Broccoli, Bro's client communication library. The bindings make it easy to send and receive Bro events from external Python scripts. See the module documentation for more information.

Wednesday, February 6, 2008

Now Accepting Internship Applications

We are now accepting applications for summer interns for the upcoming summer. Please see this announcement for details.

Friday, February 1, 2008

Sidejacking, Forced Sidejacking, and Gmail

The following is not original, just an analysis and summary of other work and the current security state of Gmail's login cookie and sidejacking. Its been well known (Errata Security) for months that Google's cookie management has some serious problems, even when you use SSL. Mike Perry's Bugtraq posting from over half a year ago explains it well.

Executive summary: Google's failure to properly use the secure attribute on Gmail's cookies means that Gmail over SSL offers effectively no security against an active attacker when compared with Gmail without SSL. This is a well known problem.

First, some general purpose background on cookies and sidejacking:

What is a cookie? A cookie is a small value stored in the user's web browser that is sent to the web server. Whenever a webpage is fetched, the browser sends all cookies associated with that web site. Likewise, the web site can set cookies in the reply.

Cookies are often used as "login cookies" or "session cookies", a way for the server to know who a user is and that he's allowed to log in. Often, these cookies are marked as secure, which means they will only be sent over an encrypted (https) session. But if they aren't marked as secure, they will be sent with every page request made to the server, regardless of encryption.

What is sidejacking? Sidejacking is simply stealing the session cookies when they are sent over an insecure (normal HTTP) session and reusing them. If you can grab someone's login cookie, you can impersonate them on whatever website the cookie is for, such as read their email on Gmail or Hotmail, or whatever other impersonation is desired.

What is forced sidejacking? (Also known as a cross site request forgery attack, but that's not as catchy a name). If a session is unencrypted, someone able to observe packets (such as the guy sitting next to you in Starbucks) can obviously see, intercept, and reuse any cookies seen in the classic Sidejack attack. But often an attacker wants to get the cookies associated with a connection which is not currently active, or when the session is encrypted.

In this case, if the attacker can inject packets, instead of being an eavesdropper he can become a man in the middle. And since listening in on packets to capture people's email accounts is already illegal, there is no reason for the attacker who's sitting next to you in starbucks to limit himself to just passive snooping.

By performing packet injection or any one of half a dozen other attacks, the attacker can fool your web browser into going where the attacker wants and revealing all the cookies for the site he wants, by modifying your web browsing.

As an example, the attacker could replace the victim's fetch of any normal web page with an "HTTP 302 Temporarily moved" pointing to the web site he wants to steal the cookies from. Thus the victim's browser then thinks "Oh, I should visit this instead", so it creates a request which includes all cookies which aren't secure. The attacker then replaces the reply with another "HTTP Temporarily moved", back to the page the victim was trying to visit. [1]

As a result, the attacker has learned what the cookies are for the victim's login to the targeted site, but the victim doesn't observe anything (it just looks like the page took a little longer to load, and the address bar might flicker).

Any site which does not allow HTTPS is trivially vulnerable to sidejacking and forced sidejacking. Thus, Hotmail can always be forced sidejacked. However, sites which use SSL to access can set the secure attribute on the login cookie, which should prevent this attack.

Unfortunately, Gmail, although it supports SSL, does NOT set the secure attribute on the login cookie (which is named "GX"). Thus if you manually type, you are safe from a passive eavesdropper (passive sidejacking), but just as vulnerable to an active attacker (forced sidejacking) as you are with the "SSL only for the login" Hotmail or Gmail over plain http! This is because although your session is encrypted, an attacker could still redirect any of your other surfing to "", which reveals your GX cookie to the attacker. And since its just as illegal to sniff a person's cookies to access their email account as it is to modify their browsing, and almost as easy to inject traffic instead of just sniffing traffic, Gmail's SSL offers effectively no security over the non-SSL option [2].

This situation will remain until Google changes the GX cookie to secure. But the situation, as you will see, is more complex then a one-line change.

Naturally, I thought there would be an easy fix: use greasemonkey to change the GX cookie to secure whenever I visit Gmail. (Greasemonkey allows you to inject arbitrary Javascript into a set of pages you view, which can both read and change cookie attributes). Now if the attacker tried to actively sidejack me, my browser just wouldn't send the cookie because its not an HTTPS session.

But that doesn't work, as Google uses a two stage login process for Gmail, Blogger, etc which prevents the quick fix from working. There is a local session cookie (GX) and a global user login cookie group (SID (insecure) and LSID (secure)) which are used by Google's single signon system. The LSID cookie is restricted to, and has the secure attribute set, to the attacker can't grab it directly.

Yet an active attacker can use the global login cookie directly, if he's performing forced sidejacking.

The Gmail login procedure (verified as of 2/1/2008) works as follows:

  • If the GX cookie is set, log in the user.
  • If the GX cookie is NOT set, perform an HTTP redirect to
  • checks if the LSID and SID cookies are valid. If so, it redirects to{auth_info}.. which sets the GX cookie and redirects the user back to (if no SSL was used) or (if was entered manually).
  • Otherwise gives the login prompt

This is why, if you are logged into Gmail, you can log into blogger by just clicking the "log me in" button: blogger redirects you to, which checks the same SID and LSID cookies and then redirects you back to Blogger.

But the result is Greasemonkey can't fix the Gmail cookie, because all the attacker needs to do is redirect the victim's surfing to If the GX cookie is set, the attacker gets it, and redirects the victim back to his original web site.

Otherwise, the attacker lets redirect the victim to which redirects the victim to which sets the GX cookie and gives an HTTP redirect back to which will happily spit out the GX cookie, followed by the attacker redirecting the request back to where the victim was going in the first place.

Since no page ever loaded (it was all "HTTP 302 moved temporarily"), the browser reveals the GX cookie before any page loaded, and therefore before Greasemonkey-injected Javascript can run.

The result is, IF the victim is logged into ANY single-sign-on Google service (even using SSL) and visits ANY web page while still logged in, an active attacker can capture login cookies for any Google service which allows (not requires, just allows) non-SSL use, even if they aren't currently logged into the particular Google service.

This also suggests that attempting to fix other sites with Greasemonkey wouldn't work either if they have any form of "URL for SSL that transitions to non SSL and updates the cookie" that the attacker can inject to extract a session cookie from. And it points out the problem with any site which uses "SSL-only" to check an existing login cookie to generate a session cookie: to an active attacker, although the attacker can't capture the SSL-only login cookie, he can use the login cookie to generate a session cookie.

In the specific case of Google, Google needs to infer and set "paranoid" cookies. [3] If the user logs into a Google service by manually selecting "https", it checks if the local login cookie also has a corresponding local paranoid cookie. If so, it should just proceed normally after ensuring that the login and paranoid cookies have the secure attribute set.

But if the paranoid cookie is not set, but the user explicitly selected https, it should redirect to regardless of the cookie status. In this case, Google should set a GLOBAL paranoid cookie. This paranoid cookie should cause to always redirect to https if the service supports it, and any local service login cookie to be set with the SECURE attribute and a corresponding local service paranoid cookie.

Now only services which don't support HTTPS for all operation (like blogger) could be actively or passively sidejacked, and once a user logs in with https://, all newly authenticated sessions will default to https until the user manually logs out by pressing the logout button.

Finally, this problem is not unique to Google, as there are rumors of other significant sites which fail to properly set secure on their session or login cookies, even when all traffic should be restricted to encrypted links.

[1] There are other ways to inject content as well to force the victim's browser to visit a targeted site, such as iframe injection through ARP cache poisoning.

[2] The only exception is if ONLY gmail is accessed from the web browser (no other browsing or even RSS fetches) and the user clicks the "logout" button when done. Since only the truely paranoid would do such a thing, I believe it is safe to say that Gmail with https really is not more secure than Hotmail in the face of an active attacker.

[3] Google doesn't use HTTPS-only for gmail for several reasons, but the biggest one is that HTTPS has considerably more latency when starting a connection, something which occurs often in web browsing. Yet this is obviously not a concern for anyone who manually selects an encrypted link.

Many thanks to Christian Kreibech, Vern Paxson, and Mike Perry for comments and feedback.

Edit/Extension: Here's how to find out if a site you use is vulnerable.

  • Clear all cookies (in firefox, Preferences->privacy)
  • Go to the site and log in.
  • Close the browser window.
  • Reopen the site, if you become logged in, then there is a saved login cookie.
  • Now close the window. In Firefox, open up "Preferences/Privacy", manually delete EVERY cookie marked as "SECURE"
  • Reopen the site. If you become logged in again, the site is vulnerable!

    NOTE PLEASE: As of Sept 2008, gmail does appear to be inferring that the user wants SECURE access when the user manually inputs, in addition to providing an "always use SSL" preference. Thus the attack on the GX cookie is NOW OBSOLETE, the problem with gmail has been fixed. Many other sites may remain vulnerable, however.

Tuesday, January 29, 2008

OT: Thinking about AT&T's Copyfighting...

On my personal blog, I have some speculation on AT&T's proposal to enforce copyright on the wire, and how it can be done cheaply, efficiently, (reasonably) precisely, without deep packet inspection/wiretapping or actually deciding what material is copyrighted, robustly, against high-volume, "open world" piracy (eg, pirated DVDs through BitTorrent which are widely available).

The observation is that a short term "notice and takedown" structure could be deployed which could target P2P piracy, should AT&T wish to cooperate with the content providers.

I don't necessarily think its a good thing, but I believe that should AT&T want to, they have significant incentives to do so, and the technological means at their disposal.

More here