mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 06:38:20 +00:00
99 lines
2.1 KiB
Text
99 lines
2.1 KiB
Text
# $Id: proxy.bro,v 1.1.4.2 2006/05/31 00:16:22 sommer Exp $
|
|
#
|
|
# Finds open proxies by matching incoming HTTP requests with outgoing ones.
|
|
|
|
@load notice
|
|
|
|
module Proxy;
|
|
|
|
export {
|
|
const KnownProxies: set[addr] = { };
|
|
|
|
redef enum Notice += {
|
|
HTTPProxyFound,
|
|
};
|
|
}
|
|
|
|
|
|
type request: record {
|
|
p: port;
|
|
paths: set[string];
|
|
};
|
|
|
|
# Maps the address of the potential proxy to the paths that
|
|
# have been requested from it.
|
|
global requests: table[addr] of request;
|
|
|
|
# A parsed URL.
|
|
type url: record {
|
|
host: string;
|
|
path: string;
|
|
};
|
|
|
|
global found_proxies: set[addr] &create_expire = 24 hrs;
|
|
|
|
function parse_url(u: string) : url
|
|
{
|
|
# The URL parsing is imperfect, but should work sufficiently well.
|
|
local a = split1(u, /:\/\//);
|
|
if ( |a| == 1 )
|
|
return [$host="", $path=a[1]];
|
|
|
|
local b = split1(a[2], /\//);
|
|
return [$host=b[1], $path=(|b| == 2 ? cat("/", b[2]) : "/")];
|
|
}
|
|
|
|
event http_request(c: connection, method: string, original_URI: string,
|
|
unescaped_URI: string, version: string)
|
|
{
|
|
if ( method != "GET" && method != "CONNECT" )
|
|
return;
|
|
|
|
local client = c$id$orig_h;
|
|
local server = c$id$resp_h;
|
|
|
|
if ( server in KnownProxies )
|
|
return;
|
|
|
|
# FIXME: Which one? original_URI or unescaped_URI?
|
|
local u = parse_url(original_URI);
|
|
|
|
if ( client in requests )
|
|
{
|
|
# We have already seen requests to this host. Let's see
|
|
# any matches the one we're very currently seeing.
|
|
local r = requests[client];
|
|
if ( u$path in r$paths )
|
|
{
|
|
if ( client !in found_proxies )
|
|
{
|
|
NOTICE([$note=HTTPProxyFound,
|
|
$conn=c, $src=client,
|
|
$p=r$p, $URL=original_URI,
|
|
$msg=fmt("HTTP proxy found %s:%d (%s)",
|
|
client, r$p, original_URI)]);
|
|
add found_proxies[client];
|
|
}
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
if ( u$host == "" )
|
|
# A relative URL. That's fine.
|
|
return;
|
|
|
|
# An absolute URL. Remember path for later.
|
|
#
|
|
# Note: using "when", could even lookup the destination
|
|
# host and remember that one, too!
|
|
|
|
if ( server !in requests )
|
|
{
|
|
local empty_set: set[string] &read_expire = 15 secs;
|
|
local req = [$p=c$id$resp_p, $paths=empty_set];
|
|
requests[server] = req;
|
|
}
|
|
|
|
add requests[server]$paths[u$path];
|
|
}
|