[Bro] Bro scripts

Matthias Vallentin vallentin at icir.org
Fri Oct 29 16:35:14 PDT 2010


> I think it would make sense to do the following. If a profile for a
> user_session for a particular site (as defined above) exists, use it,
> and otherwise use the entire cookie value.

Attached is the full version of the sidejacking detector that includes
all the Firesheep handlers. I tested it for Twitter, Amazon, and Google.
The script successfully reports alarms when I hijack my own connections
with Firesheep.

   Matthias
-------------- next part --------------
# A simple sidejacking detector. 
#
# The script raises an alarm whenever more than one client makes use of the
# same cookie, where a user is defined a as (IP, user agent) pair.

@load notice
@load http-request
@load http-reply

module HTTP;

export
{
    redef enum Notice += { Sidejacking };

    # The time after expiring entries. This allows to roam users and later
    # reconnect from a different address without triggering a false positive.
    const cookie_expiration = 1 hr &redef;

    type cookie_info: record
    {
        url: pattern;   # URL pattern matched against Host header.
        pat: pattern;   # Cookie keys that define the user session.
    };

    # List of cookie information per service (taken from Firesheep handlers).
    const cookie_list: table[string] of cookie_info =
    {
        ["Amazon"]       = [$url=/amazon.com/, $pat=/x-main/],
        ["Basecamp"]     = [$url=/basecamphq.com/, 
                            $pat=/_basecamp_session|session_token/],
        ["bit.ly"]       = [$url=/bit.ly/, $pat=/user/],
        ["Cisco"]        = [$url=/cisco.com/, $pat=/SMIDENTITY/],
        ["CNET"]         = [$url=/cnet.com/, $pat=/urs_sessionId/],
        ["Dropbox"]      = [$url=/dropbox.com/, $pat=/lid/],
        ["Enom"]         = [$url=/enom.com/, $pat=/OatmealCookie|EmailAddress/],
        ["Evernote"]     = [$url=/evernote.com/, $pat=/auth/],
        ["Facebook"]     = [$url=/facebook.com/, $pat=/xs|c_user|sid/],
        ["Flickr"]       = [$url=/flickr.com/, $pat=/cookie_session/],
        ["Foursquare"]   = [$url=/foursquare.com/, $pat=/ext_id|XSESSIONID/],
        ["GitHub"]       = [$url=/github.com/, $pat=/_github_ses/],
        ["Google"]       = [$url=/google.com/, $pat=/NID|SID|HSID|PREF/],
        ["Gowalla"]      = [$url=/gowalla.com/, $pat=/__utma/],
        ["Hacker News"]  = [$url=/news.ycombinator.com/, $pat=/user/],
        ["Harvest"]      = [$url=/harvestapp.com/, $pat=/_enc_sess/],
        ["NY Times"]     = [$url=/nytimes.com/, $pat=/NYT-s|nyt-d/],
        ["Pivotal Tracker"] = [$url=/pivotaltracker.com/, 
                            $pat=/_myapp_session/],
        ["Slicehost"]    = [$url=/manage.slicehost.com/,
                            $pat=/_coach_session_id/],
        ["tumblr"]       = [$url=/tumblr.com/, $pat=/pfp/],
        ["Twitter"]      = [$url=/twitter.com/, $pat=/_twitter_sess/],
        ["Yahoo"]        = [$url=/yahoo.com/, $pat=/T|Y/],
        ["Yelp"]         = [$url=/yelp.com/, $pat=/__utma/],
        ["Windows Live"] = [$url=/live.com/, 
                            $pat=/MSP(Prof|Auth)|RPSTAuth|NAP/],
        ["Wordpress"]    = [$url=/wordpress.com/, 
                            $pat=/wordpress_[0-9a-fA-F]+/]
    } &redef;
}

# Map cookies to users, who are defined as a (address, user-agent) pair.
global cookies: table[string] of set[addr,string] 
    &write_expire = cookie_expiration;

# Create a unique user session identifier based on a pattern of cookie keys.
function sessionize(cookie: string, keys: pattern) : string
{
    local id = "";
    local fields = split(cookie, /; /);
    for (i in fields)
    {
        local s = split1(fields[i], /=/);
        if (keys in s[1])
            id += s[2];
    }

    return id;
}

event http_all_headers(c: connection, is_orig: bool, hlist: mime_header_list)
{
    if (! is_orig)
        return;

    local cookie = "";
    local ua = "";
    local host = "";
    for (i in hlist)
    {
        local hdr = hlist[i]$name;
        local value = hlist[i]$value;
        if (hdr == "COOKIE")
            cookie = value;
        else if (hdr == "USER-AGENT")
            ua = value;
        else if (hdr == "HOST")
            host = to_lower(value);
    }

    if (cookie == "")
        return;

    # Restrict ourselves to a subset of cookie keys that define a user session.
    local id = "";
    local desc = "";
    if (host != "")
        for (k in cookie_list)
        {
            local info = cookie_list[k];
            if (info$url in host)
            {
                id = sessionize(cookie, info$pat);
                desc = k;
                break;
            }
        }

    if (id == "")
        id = cookie;

    if (id !in cookies)
        cookies[id] = set() &mergeable;

    local client = c$id$orig_h;
    add cookies[id][client, ua];

    if (|cookies[id]| <= 1)
        return;

	local s = lookup_http_request_stream(c);
	desc = (desc == "" ? "" : fmt("%s ", desc));
    NOTICE([$note=Sidejacking, $src=client,
            $msg=fmt("%ssession hijacked by %s (%d users/cookie)", desc, 
            client, |cookies[id]|)]);
}


More information about the Bro mailing list