├── pdf.pcap ├── scan.pcap ├── icmp-variance.pcap ├── README.md ├── simple-addr-scan-tuning.bro ├── LICENSE.md ├── pdf.bro ├── extract-all-files.bro └── detect-icmp-variance.bro /pdf.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hosom/bro-scripts/HEAD/pdf.pcap -------------------------------------------------------------------------------- /scan.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hosom/bro-scripts/HEAD/scan.pcap -------------------------------------------------------------------------------- /icmp-variance.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hosom/bro-scripts/HEAD/icmp-variance.pcap -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # bro-scripts 2 | Bro stuff. 3 | 4 | These scripts are one off bro scripts that do not belong in their own repository. 5 | 6 | I will generally try to include test packet captures where I can. 7 | -------------------------------------------------------------------------------- /simple-addr-scan-tuning.bro: -------------------------------------------------------------------------------- 1 | module SimpleAddrScanTuning; 2 | export { 3 | ## Put hosts you want to ignore scans from into this table. 4 | const exceptions: table[addr] of set[port] &redef; 5 | } 6 | 7 | hook Scan::addr_scan_policy(scanner: addr, victim: addr, scanned_port: port) 8 | { 9 | if ( scanner in exceptions && scanned_port in exceptions[scanner] ) 10 | break; 11 | } 12 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of bro-scripts nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /pdf.bro: -------------------------------------------------------------------------------- 1 | module PDF; 2 | 3 | export { 4 | ## Patterns that indicate dynamic content within PDF files. 5 | const dynamic_content_pattern = /\/JS|\/JavaScript|\/AA|\/OpenAction|\/RichMedia|\/Launch/ &redef; 6 | ## Event fired whenever the dynamic_content_pattern is matched. 7 | global dynamic_content_found: event(f: fa_file, data: string); 8 | 9 | ## Toggles logging of matches to pdf.log. 10 | const logging = T &redef; 11 | 12 | 13 | redef enum Log::ID += { LOG }; 14 | 15 | type Info: record { 16 | ts: time &log; 17 | ## The ID of the file to link to files.log. 18 | fuid: string &log; 19 | ## The data that matched the dynamic_content_pattern. 20 | data: string &log; 21 | }; 22 | 23 | global log_pdf: event(rec: Info); 24 | } 25 | 26 | event PDF::dynamic_content_found(f: fa_file, data: string) 27 | { 28 | if ( logging ) 29 | { 30 | local rec: PDF::Info = [$ts=network_time(), $fuid=f$id, $data=data]; 31 | Log::write(PDF::LOG, rec); 32 | } 33 | } 34 | 35 | event pdf_data(f: fa_file, data: string) 36 | { 37 | if ( dynamic_content_pattern in data ) 38 | { 39 | event PDF::dynamic_content_found(f, data); 40 | } 41 | } 42 | 43 | event file_sniff(f: fa_file, meta: fa_metadata) 44 | { 45 | if ( meta?$mime_type && meta$mime_type == "application/pdf") 46 | Files::add_analyzer(f, Files::ANALYZER_DATA_EVENT, [$stream_event=pdf_data]); 47 | } 48 | 49 | event bro_init() &priority=5 50 | { 51 | Log::create_stream(PDF::LOG, [$columns=Info, $ev=log_pdf]); 52 | } 53 | -------------------------------------------------------------------------------- /extract-all-files.bro: -------------------------------------------------------------------------------- 1 | module ExtractAllFiles; 2 | 3 | export { 4 | ## Path to save extracted files to 5 | const path = "./" &redef; 6 | 7 | ## This table contains a conversion of common mime types to their 8 | ## corresponding 'normal' file extensions. 9 | const common_types: table[string] of string = { 10 | ["text/plain"] = "txt", 11 | ["text/html"] = "html", 12 | ["text/json"] = "json", 13 | ["text/x-perl"] = "pl", 14 | ["text/x-python"] = "py", 15 | ["text/x-ruby"] = "rb", 16 | ["text/x-lua"] = "lua", 17 | ["text/x-php"] = "php", 18 | ["image/gif"] = "gif", 19 | ["image/x-ms-bmp"] = "bmp", 20 | ["image/jpeg"] = "jpg", 21 | ["image/png"] = "png", 22 | ["application/x-dosexec"] = "exe", 23 | ["application/msword"] = "doc", 24 | ["application/vnd.openxmlformats-officedocument.wordprocessingml.document"] = "docx", 25 | ["application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"] = "xlsx", 26 | ["application/vnd.openxmlformats-officedocument.presentationml.presentation"] = "pptx", 27 | ["application/xml"] = "xml", 28 | ["application/java-archive"] = "jar", 29 | ["application/x-java-applet"] = "jar", 30 | ["application/x-shockwave-flash"] = "swf", 31 | ["application/javascript"] = "js" 32 | }; 33 | } 34 | 35 | event file_sniff(f: fa_file, meta: fa_metadata) 36 | { 37 | if ( !meta?$mime_type ) 38 | return; 39 | 40 | local ftype = ""; 41 | if ( meta$mime_type in common_types ) 42 | ftype = common_types[meta$mime_type]; 43 | else 44 | ftype = split_string(meta$mime_type, /\//)[1]; 45 | 46 | local fname = fmt("%s%s-%s.%s", path, f$source, f$id, ftype); 47 | Files::add_analyzer(f, Files::ANALYZER_EXTRACT, [$extract_filename=fname]); 48 | } -------------------------------------------------------------------------------- /detect-icmp-variance.bro: -------------------------------------------------------------------------------- 1 | @load base/frameworks/notice 2 | @load base/frameworks/sumstats/plugins/variance.bro 3 | 4 | module DetectICMPSHell; 5 | 6 | export { 7 | redef enum Notice::Type += { 8 | ## High variance in ICMP connections indicates ICMP shells 9 | ICMP_High_Variance 10 | }; 11 | 12 | ## Tolerance level for variance of ICMP connections from the 13 | ## same client 14 | const icmp_variance_threshold = 1.0 &redef; 15 | } 16 | 17 | event icmp_sent(c: connection, icmp: icmp_conn) 18 | { 19 | SumStats::observe("icmp.shell.variance", [$host=c$id$orig_h], [$num=icmp$len]); 20 | } 21 | 22 | event icmp_echo_request(c: connection, icmp: icmp_conn, id: count, seq: count, payload: string) 23 | { 24 | SumStats::observe("icmp.shell.variance", [$host=c$id$orig_h], [$num=|payload|]); 25 | } 26 | 27 | event icmp_echo_reply(c: connection, icmp: icmp_conn, id: count, seq: count, payload: string) 28 | { 29 | SumStats::observe("icmp.shell.variance", [$host=c$id$orig_h], [$num=|payload|]); 30 | } 31 | 32 | event icmp_error_message(c: connection, icmp: icmp_conn, code: count, context: icmp_context) 33 | { 34 | SumStats::observe("icmp.shell.variance", [$host=c$id$orig_h], [$num=icmp$len]); 35 | } 36 | 37 | event icmp_neighbor_advertisement(c: connection, icmp: icmp_conn, router: bool, solicited: bool, override: bool, tgt: addr, options: icmp6_nd_options) 38 | { 39 | SumStats::observe("icmp.shell.variance", [$host=c$id$orig_h], [$num=icmp$len]); 40 | } 41 | 42 | event icmp_neighbor_solicitation(c: connection, icmp: icmp_conn, tgt: addr, options: icmp6_nd_options) 43 | { 44 | SumStats::observe("icmp.shell.variance", [$host=c$id$orig_h], [$num=icmp$len]); 45 | } 46 | 47 | event icmp_packet_too_big(c: connection, icmp: icmp_conn, code: count, context: icmp_context) 48 | { 49 | SumStats::observe("icmp.shell.variance", [$host=c$id$orig_h], [$num=icmp$len]); 50 | } 51 | 52 | event icmp_parameter_problem(c: connection, icmp: icmp_conn, code: count, context: icmp_context) 53 | { 54 | SumStats::observe("icmp.shell.variance", [$host=c$id$orig_h], [$num=icmp$len]); 55 | } 56 | 57 | event icmp_redirect(c: connection, icmp: icmp_conn, tgt: addr, dest: addr, options: icmp6_nd_options) 58 | { 59 | SumStats::observe("icmp.shell.variance", [$host=c$id$orig_h], [$num=icmp$len]); 60 | } 61 | 62 | event icmp_router_advertisement(c: connection, icmp: icmp_conn, cur_hop_limit: count, managed: bool, other: bool, home_agent: bool, pref: count, proxy: bool, rsv: count, router_lifetime: interval, reachable_time: interval, retrans_timer: interval, options: icmp6_nd_options) 63 | { 64 | SumStats::observe("icmp.shell.variance", [$host=c$id$orig_h], [$num=icmp$len]); 65 | } 66 | 67 | event icmp_router_solicitation(c: connection, icmp: icmp_conn, options: icmp6_nd_options) 68 | { 69 | SumStats::observe("icmp.shell.variance", [$host=c$id$orig_h], [$num=icmp$len]); 70 | } 71 | 72 | event icmp_time_exceeded(c: connection, icmp: icmp_conn, code: count, context: icmp_context) 73 | { 74 | SumStats::observe("icmp.shell.variance", [$host=c$id$orig_h], [$num=icmp$len]); 75 | } 76 | 77 | event icmp_unreachable(c: connection, icmp: icmp_conn, code: count, context: icmp_context) 78 | { 79 | SumStats::observe("icmp.shell.variance", [$host=c$id$orig_h], [$num=icmp$len]); 80 | } 81 | 82 | event bro_init() 83 | { 84 | local r1 = SumStats::Reducer($stream="icmp.shell.variance", 85 | $apply=set(SumStats::VARIANCE)); 86 | 87 | SumStats::create([$name="detect-icmp-shell", 88 | $epoch=5mins, 89 | $reducers=set(r1), 90 | $threshold_val(key: SumStats::Key, result: SumStats::Result): double = 91 | { 92 | return result["icmp.shell.variance"]$variance; 93 | }, 94 | $threshold=icmp_variance_threshold, 95 | $threshold_crossed(key: SumStats::Key, result: SumStats::Result) = 96 | { 97 | NOTICE([$note=ICMP_High_Variance, 98 | $src=key$host, 99 | $msg="Observed high ICMP orig_bytes variance.", 100 | $sub="May indicate an ICMP Shell.", 101 | $identifier=cat(key$host)]); 102 | }]); 103 | } 104 | --------------------------------------------------------------------------------