Bro by wanghonghx

VIEWS: 15 PAGES: 38

									Bro Intrusion Detection System
     Hands-On Workshop:
      Scripting Language




             Vern Paxson
         vern@icsi.berkeley.edu
 International Computer Science Institute /
  Lawrence Berkeley National Laboratory
                     Bro
                     GGF
  Scripting Language Overview

• Types, values & constants
• Refinement/redefinition
• Functions & event handlers
• Statements & expressions
• Built-in functions



                       Bro
                       GGF
        Bro Script Data Types

• C-style:
  – bool (T, F), int, count, enum, double, string
  – (note, no general “cast” operator, though some built-ins)
• Network-oriented:
  –   addr (e.g., 131.243.2.191; 0ab:cd::ef)
  –   port (e.g., 80/tcp, 53/udp, 8/icmp)
  –   net (e.g., 131.243. ; not used much)
  –   subnet (e.g., 131.243.2.0/23)
• Time-oriented:
  – Absolute time (e.g., current_time(), network_time())
  – interval (e.g., 5 hrs)
                              Bro
                              GGF
   Aggregate Types - Records

• Analogous to C struct‟s:
  type connection: record {
       id: conn_id;
       orig: endpoint;
       resp: endpoint;
       start_time: time;
       duration: interval;
       service: string;
           # if empty, service not yet determined
       addl: string;
       hot: count;
       history: string;
  };
• Fields accessed using $ operator: e.g., c$id
                                  Bro
                                  GGF
               Records, con’t

• Create records using
   record($field1 = val1, $field2 = val2)
• E.g.,
   print record($foo = 1, $bar = "hi");
• prints:
   [foo=1, bar=hi]
• Synonym:
   print [$foo = 1, $bar = "hi"];



                                Bro
                                GGF
    Aggregate Types - Tables

• Tables serve as associative arrays
  – Indexed by any group of basic types or record‟s
• Each table element yields value of given
  (arbitrary) type
• E.g.,
  global trb: table[port, addr] of string;
  trb[22/tcp, 1.4.3.2] = “0wned”;
• Can test for membership/non-membership using
  in and !in operators:
  if ( [80/tcp, 3.2.1.9] !in trb ) …


                                Bro
                                GGF
    Aggregate Types - Tables

• Remove elements using delete statement:
  delete a[53/udp, 8.8.8.8];
• Create using:
  table([index1] = val1, [index2] = val2)
• E.g.,
  print table([23/tcp] = "telnet",
            [53/udp] = "dns");
• Prints
  {
  [53/udp] = “dns”,
  [23/tcp] = “telnet”
  }
                               Bro
                               GGF
Aggregate Types - Sets, Vectors

• Sets: identical to tables except don‟t yield a value
• E.g.,
   global a: set[port, addr];
   add a[22/tcp, 1.4.3.2];
• Vectors: 1-based arrays
• E.g.,
     global v: vector of set[string];
     v[1] = set(“la la la”, “ho ho”);
• Constructing vectors:
   • print vector(1, 5, 9);
   • produces “[1, 5, 9]”
                                Bro
                                GGF
   Additional Bro Script Types

• Functions & event handlers are “first-class” types:
   global a: table[string] of
          function(p: port): set[interval];



• file‟s provide I/O access to files
   global my_log = open_log_file(“me”)
      • Creates me.$BRO_LOG_SUFFIX (default: me.log)
   • Output via “print” statement
      • Currently, just output, no support for input




                                  Bro
                                  GGF
       Additional Types, con’t

• Type pattern holds a regular expression
  • E.g., global bad: pattern = /0wn|1337/;


• Can match patterns either exactly or for any
  internal match

  print /foobar/ == “my foobar”;
  print /foobar/ in “my foobar”;

  prints F and T, respectively.



                              Bro
                              GGF
     Internal Bro Script Types

• Type list is used internally similar to vectors
   • E.g., print www.bro-ids.org prints a list value
   • In general, dotted names yield list[addr] values
      • Pitfall: expecting these to work like regular addr‟s


• Type any escapes type-checking
   • E.g., the built-in length function takes a parameter of
     type any and returns a count




                                  Bro
                                  GGF
                   Variables

• Declarations:
   – global var: type = value;
   – const var: type = value;
   – local var: type = value;
• First two are global
• const is read-only
   – But still can be redef‟d
• Locals can be initialized anywhere in function /
  event handler body
   – Persist in scope all the way to the end
   – Not just in block declared (misfeature)

                                Bro
                                GGF
              Variables, con’t

• If you leave off value, variable is uninitialized
   – Run-time error if you access its value


• If you leave off type, it is inferred
   – Based on surrounding context
   – E.g., “local x = 123/udp” infers type port for x
   – Preferred style: omit type unless non-obvious or need
     to force it:
      • E.g., “global x: int = 5”, since type inferred is count
      • Vs. “global x = +5”, which also works
   – Preferred style: don‟t declare a local until value is ready


                                   Bro
                                   GGF
          Scoping & Modules

• In a script, you can declare a naming scope:
   module BitTorrent;
• Any definitions beyond that point - except for event
  handlers - are inaccessible outside the module …
• … unless explicitly exported.

• E.g.,
   module BitTorrent;
   export {
         global active_torrents: set[addr];
      };
• allows external access to
     BitTorrent::active_torrents
                               Bro
                               GGF
                     Initializers

• When initializing a variable, Bro provides some
  shortcuts to make large inits easier/cleaner
• Can omit table/set specifier if inferrable
  global a = { [T] = “true”, [F] = “false” };
  – infers a type of table[bool] of string
• Multiple values expanded as cross-product:
  global allowed: set[addr, port] =
      { [imap4.lbl.gov, [143/tcp, 993/tcp]] };
  is equivalent to
      global allowed: set[addr, port] = {
         [128.3.41.50, 143/tcp], [128.3.41.50, 993/tcp], [128.3.41.32, 143/tcp],
         [128.3.41.32, 993/tcp]
      };
                                     Bro
                                     GGF
             Initializers, con’t

• Initializing large regular expression (pattern)
  alternatives:
  global hot_words =
      /.*etc\/shadow.*/
    | /.*etc\/ldap.secret.*/
    | /.*phatbot.*/
    | /.*botnet.*/
         ;


 is equivalent to a|b|c|d …


                               Bro
                               GGF
                  Attributes

• Types and values can have attributes associated
  with them that specify certain properties
• &default specifies value to return for missing table
  entries …
   global badness: table[addr] of string = {
        [1.2.3.4] = “keylogger”
     } &default = “not sure”;
• … or function to evaluate:
   global badness: table[addr] of string = {
        [1.2.3.4] = “keylogger”
     } &default =
        function(a: addr)
         { return fmt(“bad guy @ %s”, a);
                              Bro
                              GGF
            Attributes, con’t

• &optional: record field is nonmandatory
   global host_info = record {
     a: set[addr]; # associated addresses
     username: string &optional; # if we know
   }
• Test for optional fields using ?$ operator:
   if ( host_info?$username ) …
• &persistent: variable keeps its value across Bro
  invocations
• &synchronized: variable‟s value appears the same
  across multiple Bro‟s running concurrently

                             Bro
                             GGF
            Attributes, con’t

• &create_expire / &read_expire / &write_expire:
  table/set‟s entries deleted the given interval after
  element created / last read / last written
• &expire_func: function called when table element
  expires for cleanup or to defer
• &rotate_interval, &rotate_size: control when logs
  rotate to new files, or at what size
• &priority: controls which handlers for same event
  are executed first
• &redef: marks a variable‟s value as redefinable /
  refinable …
                            Bro
                            GGF
         Redef / Refinement

• General scripting language style is to support
  specifying policies as a set of tweaks (differences
  or refinements) to a base policy
• One major form: changing global var.‟s definition:
  • global worry_ports =
       { 22/tcp, 80/tcp } &redef;
• Specifies that worry_ports can be redefined:
  • redef worry_port = { 445/tcp };
• Or refined:
  • redef worry_port += { 445/tcp, 21/tcp };
  • redef worry_port -= { 22/tcp };
                             Bro
                             GGF
    Redef / Refinement, con’t

• Also applies to enum‟s:
  type attacks: enum { DoS, remote_xploit };
  redef enum attacks += { spyware };
  • This is how you add new types of Notice‟s


• (Can also redef event handlers to override all
  previously defined ones)




                           Bro
                           GGF
  Script Management: Prefixes

• One more form of customization/refinement: you can
  specify a list of prefixes associated with @load‟ing a script
   • Via $BRO_PREFIXES environment variable
   • Or bro -p prefix-to-add
   • Or @prefixes = pref       or   @prefixes += pref
• Upon @load foo, after loading foo.bro (via search path)
  Bro also loads each prefix.foo.bro
• E.g., policy/heavy-analysis.bro uses
       @prefixes += heavy
• A subsequent load of irc.bro will also load heavy.irc.bro,
  if present (no complaint if not)
    – could be in different directory, providing on search path
                                    Bro
                                    GGF
          Program Structure

• A Bro program is made up of:
  • Set of declarations
     • Types, globals
     • Functions & event handlers (really just globals)
  • Optional code to initially execute
• After init code, execution driven by events
  • Starting with bro_init()
  • Ending with bro_done()
  • Remainder in between driven off of input sources
     • Network interface(s)
     • Trace file(s)
     • External event sources (other Bro‟s; Broccoli clients)
                                Bro
                                GGF
  Functions & Event Handlers

• Syntax for function/event handler header:
  function name(arg1: type1, …): return_type
  event name(arg1: type1, arg2: type2, …)
• … followed by a body ( 0 statements in {}‟s)
• Executed imperatively until return or end-of-body
• You can define multiple event handlers for the
  same event and they will all be executed
  • Order not guaranteed unless you use &priority
  • Can‟t redefine functions, however


                            Bro
                            GGF
                 Statements

• Terminated with „;‟
• An expression by itself is a statement (e.g.,
  function call for which return value ignored)
• Usual if ( expr ) … and if ( expr ) … else …
• Print a comma-separate list of expressions:
   • print expr1, expr2, … ;
• Same, but via syslog (more generally,
  alarm_hook())
   • alarm expr1, expr2, … ;

                               Bro
                               GGF
            Statements, con’t

• Generate an event:
   • event name(arg1, arg2, …);
   • Queued for execution (asynchronous)
   • Pending events are drained after each packet
     processed
• Loop over indices of a table or set:
   • for (var in expr) stmt
   • var takes on each index present, in arbitrary order
   • next starts next iteration; break terminates abruptly
   • Can loop over multiple indices via [var1, var2] in …

                              Bro
                              GGF
          Statements, con’t

• Adding & deleting things via add, delete as
  already seen
   • delete important for state management
• Usual return statement, with expr for function
  value (event handlers can‟t return values)


• Conditional code:
  • @if ( expr ) equivalent to #if in C/C++
  • Similarly @ifdef, @ifndef, @else, @endif


                             Bro
                             GGF
            Future Execution

• Powerful when statement schedules code to
  execute if in the future something becomes true:
   • when (expr) stmt;
   • when (expr) stmt timeout interval { stmt2 };
• At any* point in the future when expr becomes
  true, stmt executes
• If interval elapses before it becomes true, stmt2
  executes instead
• Particularly useful for asynchronous activity such
  as DNS lookups
   • Can also create asynch. functions w/ return when
                              Bro
                              GGF
    Example of when statement
global t: table[addr] of count;
event connection_established(c: connection)
   {
   local orig = c$id$orig_h;
   if ( orig !in t ) {
    t[orig] = 1;
    when ( t[orig] == 5 )
        print fmt("%s has established 5 connections", orig);
    timeout 1 hr {
        print fmt("%s has NOT established 5 connections", orig);
        delete t[orig];
     }
    } else
        ++t[orig];
   }
                                    Bro
                                    GGF
                Expressions

• Usual C operators & relationals:
   • +, -, *, /, %, &&, ||, +=, -=, ++, --, [], (), ?:
• copy creates a “deep copy” of an aggregate value
• |expr| returns size of any value
• We‟ve already seen in, !in, record(…), etc.
• function(arg1: type1, …): ret_type { body } returns
  an anonymous function
• schedule interval { name(val1, val2, …) }
  schedules a timer to generate the event name at a
  time interval in the future (returning the timer)
                              Bro
                              GGF
       The match Expression

• Provides complex but powerful way to match a
  value against a whole set of alternatives
• Syntax:
   • match expr1 using expr2
• expr1 is the value to match. Say it‟s type is T1.
• expr2 is a set of records, all of the same type
• Idea is to process the value for each record in the
  set to pick the best match


                          Bro
                          GGF
  The match Expression, con’t

• Each record of Expr2 has 3 fields:
  • $pred: function(arg: T1): bool
  • $result: T2 (same type for all records)
  • $priority: count (or int or double)
• For each record, $pred function called with expr1‟s
  value as parameter
• For all of the records whose $pred returns T,
  select one with highest $priority …
• … and return its $result as match expr‟s value

                           Bro
                           GGF
  The match Expression, con’t

• Why go to all this trouble?
• Provides highly flexible way to customize notice
  processing to determine which to promote to
  alarms and in what circumstances
• policy/notice.bro uses:
  global notice_policy: set[notice_policy_item] = {
    [$pred(n: notice_info) = { return T; },
     $result = NOTICE_ALARM_ALWAYS,
     $priority = 0],
  } &redef;

                            Bro
                            GGF
  The match Expression, con’t

• Sites can then customize their policies via redef:
  redef notice_policy += {
    # Ignore sensitive URIs if the request was unsuccessful
    # (code 404, or not answered.)
    [$pred(n: notice_info) =
       {
       return n$note == HTTP::HTTP_SensitiveURI &&
                   n$msg == /.*((\(404)|(no reply)).*/;
       },
     $result = NOTICE_FILE, # log, but no excitement
     $priority = 1]
  }
                           Bro
                           GGF
  The match Expression, con’t

• Evaluation can also have side effects:
  [$pred(n: notice_info) = {
   if ( n$note == FTP::FTP_Sensitive &&
        n$msg == /.*crown_jewels.*/ ) {
          system("page_duty_officer \"crown jewels theft!\"");
          return T;
   } else
          return F;
   },
  $result = NOTICE_LOG_ALWAYS,
  $priority = 1000]

                             Bro
                             GGF
  The match Expression, con’t

• Supported notice actions:
  • NOTICE_IGNORE
  • NOTICE_FILE
  • NOTICE_ALARM_ALWAYS
     • (vs. NOTICE_ALARM_ONCE, etc., not implemented)
  • NOTICE_EMAIL
     • Sent to redef‟able mail_dest, via redef‟able mail_script
  • NOTICE_PAGE
     • Sent to redef‟able mail_page_dest




                                 Bro
                                 GGF
            Built-in Functions

• You can add a built-in function via src/bro.bif
   • Edit file and issue “make”, invokes bifcl compiler
   • Note, events are defined in src/event.bif
• E.g.:
   function double_to_count%(d: double%): count
        %{
        if ( d < 0.0 )
               builtin_run_time("bad conversion to count", @ARG@[0]);
        return new Val(bro_uint_t(rint(d)), TYPE_COUNT);
        %}
• Note: „d‟ has value from script
   • @ARG@ is array of generic Bro internal Val‟s
                                 Bro
                                 GGF
Questions?




    Bro
    GGF

								
To top