# Copyright (c) 2010 Flowerfire, Inc. All Rights Reserved. cisco_pix = { plugin_version = "2.6.4" info.1.manufacturer = "Cisco Systems" info.1.device = "PIX/ASA Security Appliance" info.1.version = "500 Series" # 2006/03/10 - 2.0beta - added support for router/switch messages. # 2006/04/12 - 2.0.1beta - added support for "permitted" lines -GMF # 2006/06/05 - 2.0.2beta - KBB - added extraction of user name from Built # and Teardown lines - for systems where users authenticated with TACACS - # (note - "user_name" added and "user" commented out in datebase and log # fields, since "user" already existed, but lines where "user" is collected # were already commented out) # 2006/06/13 - 2.0.3beta - KBB - user name from Accessed URL lines # 2006/11/07 - 2.0.4beta - KBB - handle negative connection numbers in Built and Teardown lines # 2006/11/20 - 2.0.5beta - KBB - count connections on teardown and check for inbound/outbound when # determining which port is the source and which the destination # 2006/11/30 - 2.0.6beta - KBB - count connections on built as well as teardown and check for # inbound/outbound when determining which port is the source and which the destination for Built # events as well as Teardown events # 2006/12/04 - 2.0.7beta - KBB - reverse direction of 2.0.5 - was reversing to/from if inbound - now # reversing if outbound # 2006/12/29 - 2.0.8beta - KBB - added inclusion of direction with Teardown event - now collecting # Username, Group and IP from certain ASA lines - added support for more types of operations/messages # 2007/01/05 - 2.0.9beta - KBB - excluded translations from Built and Teardown events - added support # for several types of Deny events # 2007/01/11 - 2.1beta - KBB - fixed bug in look_up_service log filter - also commented out setting # service to "(unknown)" (1/15) - see comment in log filters section # 2007/02/23 - 2.2beta - KBB - added support for some types of "crashinfo" entries and # SEC-6-IPACCESSLOGP # 2007/08/09 - 2.2.1beta - KBB - added support for some VPN and AAA entries (PIX) # 2007/08/27 - 2.2.2beta - KBB - compensated for a Cisco bug where a negative number of bytes results # in huge number. # 2007/09/11 - 2.2.2 - KBB - renumbered per new beta policy and renamed from beta_cisco_pix.cfg # 2008/01/16 - 2.3 - GMF - Extracted facility, severity, and mnemonic from message code, into separate fields. # 2008/03/06 - 2.4 - GMF - Added support for CRYPTO lines. # 2009/07/01 - 2.5 - KBB & MSG - Added support for Session disconnected lines and added new fields session_type, bytes_xmt and bytes_rcv. # 2008/03/06 - 2.6 - MSG - Added support for bytes field containing a colon before the value # 2009/08/31 - 2.6.1 - GMF - Fixed extraction of client_application_version # 2009/11/20 - 2.6.2 - GMF - Fixed extraction of h:mm:ss durations on Teardown lines; removed reversal on outbound teardown events [ThreadID:699166]. # 2010/02/02 - 2.6.3 - MSG & KBB - Fixed parsing of bytes from Teardown lines. # 2010/12/28 - 2.6.4 - GMF - Changed reversal of to/from to happen on outbound, instead of on inbound [ThreadID:974447]. #2006-06-02 13:37:13 Local4.Info 44.84.4.4 :Jun 02 13:37:13 EDT: %PIX-6-302013: Built outbound TCP connection 30594850 for outside:49.14.143.45/80 (64.14.414.94/80) to inside:14.415.41.4/1451 (499.453.478.454/5454) (hwells) #2006-06-02 13:37:13 Local4.Notice 44.40.4.1 :Jun 02 13:37:13 EDT: %PIX-5-304001: hwells@10.115.81.9 Accessed URL 44.134.164.104:/urchin.js # 2010-10-06 - 2.6.4 - MSG - Edited info lines. # The name of the log format log.format.format_label = "Cisco PIX/ASA/Router/Switch Log Format" log.miscellaneous.log_data_type = "syslog_required" log.miscellaneous.log_format_type = "firewall" # The log is in this format if any of the first ten lines match this regular expression log.format.autodetect_regular_expression = "%(PIX|IDS|FW|AUTH|IKE|PPTP|ASA|SEC|CDP|SYS|LINK|DUAL|ETHCNTR|LINEPROTO|PLATFORM|PM|RADIUS|SNMP|SPANTREE|STANDBY)[^ ]*: " log.format.autodetect_lines = "200" # All log field parsing will be done using the parsing filters log.format.parse_only_with_filters = "true" # Log fields log.fields = { source_ip.type = "host" source_hostname = "" source_mac_address = "" destination_ip = "" destination_hostname = "" source_port = "" source_network_port = "" destination_port = "" destination_network_port = "" destination_service = "" source_side = "" destination_side = "" interface = "" page = "" operation = "" message_code = "" message_facility = "" message_severity = "" message_mnemonic = "" # destination_bytes = "" protocol = "" flags = "" bytes = "" faddr_host = "" faddr_port = "" faddr_service = "" gaddr_host = "" gaddr_port = "" gaddr_service = "" laddr_host = "" laddr_port = "" laddr_service = "" duration = "" access_group = "" access_list = "" page.type = "page" message = "" #user = "" command = "" type = "" direction = "" user_name = "" group = "" list = "" #action = "" reason = "" icmp_type = "" icmp_code = "" state = "" vty_line = "" aaa_status = "" aaa_server = "" group_policy = "" private_ip = "" packets = "" # CRYPTO fields client_type = "" client_public_addr = "" client_application_version = "" server_public_addr = "" assigned_public_addr = "" # Fields from "Session disconnected." lines session_type = "" bytes_xmt = "" bytes_rcv = "" } # log.fields log.filter_initialization = ` int hit_cnt_index; int hit_cnt_i; int hit_cnt; string insert_line; ` # Log Parsing Filters log.parsing_filters.parse = ` # Parse leading number: # 16: 000014: *Mar 1 00:28:47: %SEC-6-IPACCESSLOGP: list 100 permitted ... if (matches_regular_expression(v.syslog_message, '^[0-9]+: (.*)$')) then v.syslog_message = $1; if (matches_regular_expression(v.syslog_message, '^[0-9]+: (.*)$')) then v.syslog_message = $1; # Parse leading date/time # Oct 08 2005 04:32:54: if (matches_regular_expression(v.syslog_message, '^([A-Z][a-z][a-z]) ([0-9][0-9]) ([0-9][0-9][0-9][0-9]) ([0-9][0-9]:[0-9][0-9]:[0-9][0-9]): (.*)$')) then ( set_collected_field('', 'date', $2 . '/' . $1 . '/' . $3); set_collected_field('', 'time', $4); v.syslog_message = $5; ); # Parse leading date/time # :Oct 08 04:32:54 EST: else if (matches_regular_expression(v.syslog_message, '^:[A-Z][a-z][a-z] [0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9][^:]*: (.*)$')) then ( v.syslog_message = $1; ); # Chop off leading date/time # e.g. Oct 08 04:32:54.123: # e.g. *Mar 1 00:21:22: # e.g. *Mar 1 00:21:22.456: # e.g. 16: 00:05:04: %SEC-6-IPACCESSLOGP: list 100 ... if (matches_regular_expression(v.syslog_message, '^\\\\*?[A-Z][a-z][a-z] [0-9 ][0-9] (.*)$')) then ( v.syslog_message = $1; ); if (matches_regular_expression(v.syslog_message, '^[0-9][0-9]:[0-9][0-9]:[0-9][0-9][.0-9]*: (.*)')) then ( v.syslog_message = $1; ); # Parse out the message code if (matches_regular_expression(v.syslog_message, '%([^:]+): (.*)$')) then ( set_collected_field('', 'message_code', $1); v.message_code = $1; v.message = $2; v.from = ''; v.to = ''; v.remainder = ''; # Break message code into facility, severity, and mnemonic if (matches_regular_expression(v.message_code, '^([^-]+)-([^-]+)-([^-]+)$')) then ( set_collected_field('', 'message_facility', $1); set_collected_field('', 'message_severity', $2); set_collected_field('', 'message_mnemonic', $3); ); #Dec 5 01:00:22 1.1.1.10 %ASA-4-113019: Group = 2.3.4.5, Username = 2.3.4.5, IP = 2.3.4.5, Session disconnected. Session Type: IPSecLAN2LAN, Duration: 2h:59m:59s, Bytes xmt: 19992, Bytes rcv: 0, Reason: User Requested #Dec 5 01:00:22 1.1.1.10 %ASA-5-713050: Group = 2.3.4.5, IP = 2.3.4.5, Connection terminated for peer 2.3.4.5. Reason: Peer Terminate Remote Proxy 199.129.9.99, Local Proxy 179.19.29.9 #<165>:Jul 01 10:56:11 CST: %PIX-vpn-5-713131: Group = XYZ_default, Username = user1, IP = 222.222.222.22, Received unknown transaction mode attribute: 28683 # get leading user, group and ip information - assume any kind of message can follow since these # messages are shown without this info at # http://www.cisco.com/en/US/products/ps6120/products_system_message_guide_chapter09186a00805452d3.html # Note that these values might be overwritten by values in the message. if (matches_regular_expression(v.message, '^Group = ([^,]+), (.*)$')) then ( set_collected_field('', 'group', $1); v.message = $2; ); if (matches_regular_expression(v.message, '^Username = ([^,]+), (.*)$')) then ( set_collected_field('', 'user_name', $1); v.message = $2; ); if (matches_regular_expression(v.message, '^IP = ([^,]+), (.*)$')) then ( set_collected_field('', 'source_ip', $1); v.message = $2; ); # Put the complete message in the message field set_collected_field('', 'message', v.message); # Handle Session disconnected lines #Dec 5 01:00:22 1.1.1.10 %ASA-4-113019: Group = 2.3.4.5, Username = 2.3.4.5, IP = 2.3.4.5, Session disconnected. Session Type: IPSecLAN2LAN, Duration: 2h:59m:59s, Bytes xmt: 19992, Bytes rcv: 0, Reason: User Requested #Jun 29 13:28:43 asa1 %ASA-4-113019: Group = ra-webvpn, Username = SCP, IP = 66.246.66.66, Session disconnected. Session Type: SSL, Duration: 0h:31m:03s, Bytes xmt: 281419, Bytes rcv: 128102, Reason: Idle Timeout if (matches_regular_expression(v.message, 'Session disconnected. (.*)')) then ( set_collected_field('', 'operation', 'Session disconnected'); collect_listed_fields('', $1, ', ', ': ', ''); if (matches_regular_expression(get_collected_field('', 'duration'), '^([0-9]*)h:([0-9]*)m:([0-9]*)s')) then ( set_collected_field('', 'duration', (60 * 60 * $1) + (60 * $2) + $3); ) ); # Handle "list" lines #2006-03-01 11:16:22 Local7.Info 10.11.11.11 24: 00:18:27: %SEC-6-IPACCESSLOGP: list 100 permitted tcp 255.255.255.255(0) -> 255.255.255.254(0), 1 packet #2006-03-01 11:21:55 Local7.Info 10.11.11.11 121: 00:23:59: %SEC-6-IPACCESSLOGP: list 100 permitted udp 10.11.11.12(0) -> 10.10.25.52(0), 1 packet #2002-08-26 13:14:10 Local7.Info 255.255.255.251 11643: 5w5d: %SEC-6-IPACCESSLOGDP: list 101 denied icmp 255.255.255.253 (Serial2/0 *PPP*) -> 255.255.255.252 (3/13), 1 packet #2006-02-27 10:11:52 Local7.Info 192.168.22.22 1009: Feb 27 02:07:45.707: %SEC-6-IPACCESSLOGP: list sdm_fastethernet0/1_in permitted tcp 192.168.22.23(0) -> 192.168.22.22(0), 1 packet else if (matches_regular_expression(v.message, '^list ([^ ]*) ([a-z]+) ([^ ]+) (.*)$')) then ( set_collected_field('', 'list', $1); set_collected_field('', 'operation', $2); set_collected_field('', 'protocol', $3); v.from_to = $4; # Extract "from" and "to" parts of the message v.to_index = index(v.from_to, ' -> '); if (v.to_index != -1) then ( v.from = substr(v.from_to, 0, v.to_index); v.to = substr(v.from_to, v.to_index + 4); # Get packets from the end of the line if (matches_regular_expression(v.to, '^(.*), ([0-9]+) packet')) then ( v.to = $1; set_collected_field('', 'packets', $2); ); ); # if to_index != -1 # Handle v.from and v.to in a list-specific way (the handler below works for PIX, but can't easily be extended to work for PIX and "list" lines). if (matches_regular_expression(v.from, '^([0-9.]+)(.*)$')) then ( set_collected_field('', 'source_ip', $1); v.from = $2; if (matches_regular_expression(v.from, '^\\\\(([0-9]+)\\\\)(.*)$')) then ( set_collected_field('', 'source_port', $1); v.from = $2; ); if (matches_regular_expression(v.from, '^ \\\\(([^)]+)\\\\)')) then ( set_collected_field('', 'source_network_port', $1); ); ); if (matches_regular_expression(v.to, '^([0-9.]+)(.*)$')) then ( set_collected_field('', 'destination_ip', $1); v.to = $2; if (matches_regular_expression(v.to, '^\\\\(([0-9]+)\\\\)(.*)$')) then ( set_collected_field('', 'destination_port', $1); v.to = $2; ); if (matches_regular_expression(v.to, '^ \\\\(([^)]+)\\\\)')) then ( set_collected_field('', 'destination_network_port', $1); ); ); v.from = ""; v.to = ""; ); # list # Handle Built connections - note that dynamic and static connections are really translations - # exclude them (for now) and lines actually described as translations - also exclude lines like # this: Built local-host outside:99.99.99.99 #if (matches_regular_expression(v.message, '^(Built) (inbound|outbound|dynamic) (TCP|UDP|ICMP) connection [0-9]+ for (.*)$')) then ( #) #else if (matches_regular_expression(v.message, '^(Built) (.*)$')) then ( #) #else if (matches_regular_expression(v.message, '^(Built) ((inbound|outbound|dynamic|static)? ?([A-Z]+)? (connection|translation).*)')) then ( #) else if (matches_regular_expression(v.message, '^(Built) ((inbound|outbound)? ?([A-Z]+)? connection.*)')) then ( set_collected_field('', 'operation', $1); v.message = $2; v.direction = ""; # Extract the direction, if any #if (matches_regular_expression(v.message, '^(inbound|outbound|dynamic) (.*)$')) then ( if (matches_regular_expression(v.message, '^(inbound|outbound) (.*)$')) then ( set_collected_field('', 'direction', $1); v.message = $2; v.direction = $1; ); # Extract user name, if any if (matches_regular_expression(v.message, '^(.*)[ ]+\\\\(([a-zA-Z]+[a-zA-Z0-9._]+)\\\\)$')) then ( set_collected_field('', 'user_name', $2); v.message = $1; ); # Extract the protocol if (matches_regular_expression(v.message, '^(TCP|UDP|ICMP) (.*)$')) then ( set_collected_field('', 'protocol', $1); v.message = $2; ); # Discard "connection for" if (matches_regular_expression(v.message, '^connection for (.*)$')) then v.message = $1; else if (matches_regular_expression(v.message, '^connection ([0-9-]+) for (.*)$')) then ( v.message = $2; set_collected_field($1, 'direction', v.direction); ); v.from_to = v.message; # Extract "from" and "to" parts of the message v.to_index = index(v.from_to, ' to '); if (v.to_index != -1) then ( # Reverse from and to if outbound # 2010-12-28 - GMF - Changed reversal of to/from to happen on outbound, instead of on inbound [ThreadID:974447]. # 2010-12-28 - GMF - the comment says we're reversing if outbound, but the code was actually reversing if *not* outbound (v.direction eq 'outbound') # And ThreadID:974447 indicates that the reversal is happening for inbound when it shouldn't. So, changing # this to reverse on outbound as the comment says we're doing. if (v.direction ne 'outbound') then ( v.from = substr(v.from_to, 0, v.to_index); v.to = substr(v.from_to, v.to_index + 4); ); else ( v.to = substr(v.from_to, 0, v.to_index); v.from = substr(v.from_to, v.to_index + 4); ); ); # Extract faddr/gaddr/laddr information from the message else if (matches_regular_expression(v.from_to, '^faddr ([0-9.]+)/([0-9]+) gaddr ([0-9.]+)/([0-9]+) laddr ([0-9.]+)/([0-9]+)')) then ( set_collected_field('', 'faddr_host', $1); set_collected_field('', 'faddr_port', $2); set_collected_field('', 'gaddr_host', $3); set_collected_field('', 'gaddr_port', $4); set_collected_field('', 'laddr_host', $5); set_collected_field('', 'laddr_port', $6); ); # if faddr/laddr/gaddr set_collected_field('', 'connections_built', 1); # count connections at build ); # Built # handle No route to IP from IP else if (matches_regular_expression(v.message, '(No route) to ([0-9.]+) from ([0-9.]+)')) then ( set_collected_field('', 'operation', $1); set_collected_field('', 'message', $1); set_collected_field('', 'destination_ip', $2); set_collected_field('', 'source_ip', $3); ); # handle CDP duplex mismatch message else if (matches_regular_expression(v.message, '(duplex [^,]*), with ([^ ]*) (.*)$' )) then ( set_collected_field('', 'operation', 'CDP'); set_collected_field('', 'message', $1); set_collected_field('', 'source_ip', $2); set_collected_field('', 'interface', $3); ); # Handle AAA lines #<166>Jul 01 2007 10:56:11: %PIX-6-113012: AAA user authentication Successful : local database : user = user1 # from cisco.com: %ASA-6-113004: AAA user authentication Successful : server = 192.168.130.66 : user = user1 # from oreilly.com: # %PIX-6-113004: AAA user aaa_type Successful : server = server_IP_address, User = username # %PIX-6-113005: AAA user authentication Rejected : reason = reason : server = server_IP_address, User = username else if (matches_regular_expression(v.message, '^(AAA user [^ ]+) ([^ ]+) : (.*)$')) then ( set_collected_field('', 'operation', $1); set_collected_field('', 'aaa_status', $2); v.rest = $3; if (matches_regular_expression(v.rest, 'reason = ([^:]+) : (.*)$')) then ( set_collected_field('', 'reason', $1); v.rest = $2; ); if (matches_regular_expression(v.rest, '(local database)( +: +|, +)[Uu]ser += +(.*)$')) then ( set_collected_field('', 'aaa_server', $1); set_collected_field('', 'user_name', $3); ); else if (matches_regular_expression(v.rest, 'server += +([0-9.]+)( +: +|, +)[Uu]ser += +(.*)$')) then ( set_collected_field('', 'aaa_server', $1); set_collected_field('', 'user_name', $3); ); ); # AAA user authentication #<166>Jul 01 2007 10:56:11: %PIX-6-113003: AAA group policy for user user1 is being set to XYZ_default else if (matches_regular_expression(v.message, '^(AAA group policy) for user ([^ ]+) is being set to ([^ ]+)$')) then ( set_collected_field('', 'operation', $1); set_collected_field('', 'user_name', $2); set_collected_field('', 'group_policy', $3); ); # AAA group policy #<166>Jul 01 2007 10:56:11: %PIX-6-113011: AAA retrieved user specific group policy (XYZ_default) for user = user1 #<166>Jul 01 2007 10:56:11: %PIX-6-113009: AAA retrieved default group policy (XYZ_default) for user = user1 else if (matches_regular_expression(v.message, '^(AAA retrieved [a-z ]+ group policy) \\\\(([^)]+)\\\\) for user = ([^ ]+)$')) then ( set_collected_field('', 'operation', $1); set_collected_field('', 'group_policy', $2); set_collected_field('', 'user_name', $3); ); # AAA group policy #<166>Jul 01 2007 10:56:11: %PIX-6-113008: AAA transaction status ACCEPT : user = user1 else if (matches_regular_expression(v.message, '^(AAA transaction status) ([^ ]+) : user = ([^ ]+)$')) then ( set_collected_field('', 'operation', $1); set_collected_field('', 'aaa_status', $2); set_collected_field('', 'user_name', $3); ); # AAA transaction status # Handle VPN lines #<166>:Jul 02 13:50:43 CST: %PIX-vpn-6-713172: Group = XYZ_default, IP = 222.222.222.22, Automatic NAT Detection Status: Remote end IS behind a NAT device This end IS behind a NAT device else if (matches_regular_expression(v.message, '^(Automatic NAT Detection Status): +Remote end +([Ii][Ss]|[Ii][Ss] [Nn][Oo][Tt]) +behind a NAT device +This +end +([Ii][Ss]|[Ii][Ss] [Nn][Oo][Tt]) +behind a NAT device')) then ( set_collected_field('', 'operation', $1); set_collected_field('', 'remote_end_nat_status', lowercase($2)); set_collected_field('', 'this_end_nat_status', lowercase($3)); ); # VPN #<166>:Jul 01 10:56:11 CST: %PIX-vpn-6-713184: Group = XYZ_default, Username = user1, IP = 222.222.222.22, Client Type: WinNT Client Application Version: 4.6.03.0021 else if (matches_regular_expression(v.message, '^Client Type: (.*[^ ]) +Client Application Version: (.*)$')) then ( set_collected_field('', 'client_type', $1); set_collected_field('', 'client_application_version', $2); ); # VPN #<166>:Jul 01 10:56:11 CST: %PIX-vpn-6-713184: Group = XYZ_default, Username = user1, IP = 222.222.222.22, Assigned private IP address 10.1.1.1 to remote user else if (matches_regular_expression(v.message, '^(Assigned private IP address) ([0-9.]+) to remote user')) then ( set_collected_field('', 'operation', $1); set_collected_field('', 'private_ip', $2); ); # VPN #<163>:Jul 01 10:56:11 CST: %PIX-vpn-3-713119: Group = XYZ_default, Username = user1, IP = 222.222.222.22, PHASE 1 COMPLETED #<165>:Jul 01 10:56:11 CST: %PIX-vpn-5-713120: Group = XYZ_default, Username = user1, IP = 222.222.222.22, PHASE 2 COMPLETED (msgid=580f3682) else if (matches_regular_expression(v.message, '^(PHASE [0-9]+ COMPLETED)')) then ( set_collected_field('', 'operation', $1); ); # VPN #<165>:Jul 01 10:56:11 CST: %PIX-vpn-5-713049: Group = XYZ_default, Username = user1, IP = 222.222.222.22, Security negotiation complete for User (user1) Responder, Inbound SPI = 0x431ef9de, Outbound SPI = 0x5d483240 else if (matches_regular_expression(v.message, '^(Security negotiation complete) for User \\\\(([^]]*)\\\\) Responder, Inbound SPI = ([^,]*), Outbound SPI = ([^,]*)')) then ( set_collected_field('', 'operation', $1); set_collected_field('', 'user_name', $2); set_collected_field('', 'inbound_spi', lowercase($3)); set_collected_field('', 'outbound_spi', lowercase($4)); ); # VPN #<166>:Jul 01 10:56:11 CST: %PIX-vpn-6-602303: IPSEC: An outbound remote access SA (SPI= 0x5D483240) between 10.123.123.123 and 222.222.222.22 (user= user1) has been created. #<166>:Jul 01 10:56:11 CST: %PIX-vpn-6-602303: IPSEC: An inbound remote access SA (SPI= 0x431EF9DE) between 10.123.123.123 and 222.222.222.22 (user= user1) has been created. #<166>:Jul 01 10:57:13 CST: %PIX-vpn-6-602304: IPSEC: An inbound remote access SA (SPI= 0x431EF9DE) between 10.123.123.123 and 222.222.222.22 (user= user1) has been deleted. #<166>:Jul 01 10:57:13 CST: %PIX-vpn-6-602304: IPSEC: An outbound remote access SA (SPI= 0x5D483240) between 10.123.123.123 and 222.222.222.22 (user= user1) has been deleted. #Note that ips don't change positions based on direction as they do with Built/Teardown else if (matches_regular_expression(v.message, '^(IPSEC: An (inbound|outbound) remote access SA) \\\\(SPI= ([^)]+)\\\\) between ([0-9.]+) and ([0-9.]+) \\\\(user= ([^)]+)\\\\)( has been (created|deleted))')) then ( v.direction = lowercase($2); set_collected_field('', 'operation', $1 . $7); set_collected_field('', 'direction', v.direction); set_collected_field('', v.direction . '_spi', $3); set_collected_field('', 'destination_ip', $4); set_collected_field('', 'source_ip', $5); set_collected_field('', 'user_name', $6); ); # VPN #<165>:Jul 01 10:57:13 CST: %PIX-vpn-5-713050: Group = XYZ_default, Username = user1, IP = 222.222.222.22, Connection terminated for peer user1. +Reason: Peer Terminate Remote Proxy 10.1.1.1, Local Proxy 0.0.0.0 else if (matches_regular_expression(v.message, '^(Connection terminated for peer) ([^.]+). +Reason: (.*[^ ]) +Remote Proxy ([0-9.]+), Local Proxy')) then ( set_collected_field('', 'operation', $1); set_collected_field('', 'user_name', $2); set_collected_field('', 'reason', $3); set_collected_field('', 'private_ip', $4); ); # VPN # VPN lines not processed - seemingly not important #<165>:Jul 01 10:56:11 CST: %PIX-vpn-5-713131: Group = XYZ_default, Username = user1, IP = 222.222.222.22, Received unknown transaction mode attribute: 28683 #<165>:Jul 01 10:56:11 CST: %PIX-vpn-5-713075: Group = XYZ_default, Username = user1, IP = 222.222.222.22, Overriding Initiator's IPSec rekeying duration from 2147483 to 28800 seconds #<166>:Jul 01 10:56:11 CST: %PIX-vpn-6-713905: Group = XYZ_default, Username = user1, IP = 222.222.222.22, Starting P2 Rekey timer to expire in 27359 seconds # Handle Deny lines else if (matches_regular_expression(v.message, '^(Deny) (TCP|UDP|ICMP) \\\\(no connection\\\\) from (.*)$')) then ( set_collected_field('', 'operation', $1); set_collected_field('', 'protocol', uppercase($2)); v.from_to = $3; # Extract "from" and "to" parts of the message v.to_index = index(v.from_to, ' to '); if (v.to_index != -1) then ( v.from = substr(v.from_to, 0, v.to_index); v.to = substr(v.from_to, v.to_index + 4); # Get access-group from the end of the line v.flags_index = index(v.to, ' flags '); if ((v.flags_index != -1) and (matches_regular_expression(v.to, ' flags ([A-Z ]*) on interface (.*)$'))) then ( v.to = substr(v.to, 0, v.flags_index); set_collected_field('', 'flags', $1); set_collected_field('', 'interface', $2); ); ); # if to_index != -1 ); # if Deny TCP # Handle "Deny inbound TCP from" lines # %PIX-2-106006: Deny inbound UDP from 61.16.42.217 (unresolved) /37722 to 66.133.60.12 (66-133-60-12.somewhere) /1027 on interface outside else if (matches_regular_expression(v.message, '^(Deny) (inbound|outbound) (TCP|UDP|ICMP) from (.*)')) then ( set_collected_field('', 'operation', $1); set_collected_field('', 'direction', $2); set_collected_field('', 'protocol', $3); v.from_to = $4; # Extract "from" and "to" parts of the message v.to_index = index(v.from_to, ' to '); if (v.to_index != -1) then ( v.from = substr(v.from_to, 0, v.to_index); v.to = substr(v.from_to, v.to_index + 4); # Get "on interface" from the end of the line v.on_interface_index = index(v.to, ' on interface '); if ((v.on_interface_index != -1) and matches_regular_expression(v.to, ' on interface (.*)$')) then ( v.to = substr(v.to, 0, v.on_interface_index); set_collected_field('', 'interface', $1); ); ); # if to_index != -1 ); # Deny inbound ... # Handle "Deny inbound tcp" lines #%PIX-3-106011: Deny inbound (No xlate) tcp src outside:66.143.107.49 (TSNS2-LBA0LPW6A) /1724 dst outside:66.143.60.112 (66-143-60-112.datacoremarketing.com) /139 else if (matches_regular_expression(v.message, '^(Deny) (inbound|outbound) (.*)$')) then ( set_collected_field('', 'operation', $1); set_collected_field('', 'direction', $2); v.remainder = $3; # Extract no xlate if (matches_regular_expression(v.remainder, '^\\\\(No xlate\\\\) (.*)$')) then v.remainder = $1; # Get protocol and src/dst if (matches_regular_expression(v.remainder, '^(tcp|udp|icmp) src (.*)$')) then ( set_collected_field('', 'protocol', $1); v.from_to = $2; # Extract "from" and "to" parts of the message v.to_index = index(v.from_to, ' dst '); if (v.to_index != -1) then ( v.from = substr(v.from_to, 0, v.to_index); v.to = substr(v.from_to, v.to_index + 5); # Get access-group from the end of the line v.by_access_group_index = index(v.to, ' by access-group '); if ((v.by_access_group_index != -1) and (matches_regular_expression(v.to, ' by access-group "([^"]+)"'))) then ( v.to = substr(v.to, 0, v.by_access_group_index); set_collected_field('', 'access_group', $1); ); # Get type,code from the end of the line v.type_code_index = index(v.to, ' (type '); if ((v.type_code_index != -1) and (matches_regular_expression(v.to, ' \\\\(type [0-9]+.*$'))) then ( v.to = substr(v.to, 0, v.type_code_index); ); ); # if to_index != -1 ); # if no xlate ); # Deny inbound ... # Handle "Inbound TCP connection denied" lines # %PIX-2-106001: Inbound TCP connection denied from 61.143.107.49 (ASNS5-LBB0LPW6A) /1724 to 61.143.60.112 (61-143-60-112.somewhere.com) /139 flags SYN on interface outside else if (matches_regular_expression(v.message, '^(Inbound|Outbound) (TCP|UDP|ICMP) connection (denied) from (.*)')) then ( set_collected_field('', 'direction', lowercase($1)); set_collected_field('', 'operation', 'Deny'); set_collected_field('', 'protocol', $2); v.from_to = $4; # Extract "from" and "to" parts of the message v.to_index = index(v.from_to, ' to '); if (v.to_index != -1) then ( v.from = substr(v.from_to, 0, v.to_index); v.to = substr(v.from_to, v.to_index + 4); # Get "on interface" from the end of the line v.on_interface_index = index(v.to, ' on interface '); if ((v.on_interface_index != -1) and matches_regular_expression(v.to, ' on interface (.*)$')) then ( v.to = substr(v.to, 0, v.on_interface_index); set_collected_field('', 'interface', $1); ); # Get "flags" from the end of the line v.flags_index = index(v.to, ' flags '); if ((v.flags_index != -1) and matches_regular_expression(v.to, ' flags (.*)$')) then ( v.to = substr(v.to, 0, v.flags_index); v.flags = $1; while (ends_with(v.flags, ' ')) v.flags = substr(v.flags, 0, length(v.flags) - 1); set_collected_field('', 'flags', v.flags); ); ); # if to_index != -1 ); # Deny inbound ... # Handle Deny...src lines #Dec 31 23:41:05 here.there.edu Dec 31 2006 23:41:05: %FWSM-4-106023: Deny icmp src outside:166.66.66.66 dst inside:mail.here.there.com (type 8, code 0) by access-group "INBOUND" #2006-12-22 10:39:19 Local4.Warning 192.168.1.137 Dec 21 2006 18:36:14: %ASA-4-106023: Deny icmp src outside:192.168.1.135 dst inside:192.168.1.138 (type 8, code 0) by access-group "outside_access_in" [0x0, 0x0] #Dec 31 23:33:22 fx-45-pri.net.wisc.edu Dec 31 2006 23:33:23: %FWSM-4-106023: Deny udp src outside:244.44.44.44/59787 dst inside:LJPrinter/1026 by access-group "INBOUND" #Oct 31 09:12:48 tdn-ar03-outside %FWSM-5-106023: Deny protocol 46 src outside:211.11.11.11 dst inside:1.1.1.10 by access-group "outside" #Dec 31 23:33:23 here.there.edu Dec 31 2006 23:33:23: %FWSM-4-106023: Deny udp src outside:244.46.248.44/59828 dst inside:Carol/1027 by access-group "INBOUND" else if (matches_regular_expression(v.message, '^(Deny) (tcp|udp|icmp|protocol [^ ]+) src (.*)')) then ( set_collected_field('', 'operation', $1); v.protocol = $2; v.from_to = $3; if (matches_regular_expression(v.protocol, '^protocol ([^ ]+)$')) then ( v.protocol = $1; ); else ( v.protocol = uppercase(v.protocol); ); set_collected_field('', 'protocol', v.protocol); # Extract "from" and "to" parts of the message v.to_index = index(v.from_to, ' dst '); if (v.to_index != -1) then ( v.from = substr(v.from_to, 0, v.to_index); v.to = substr(v.from_to, v.to_index + 5); # get icmp type and code if present if (matches_regular_expression(v.to, '^(.*) \\\\(type ([0-9]+), code ([0-9]+)\\\\)')) then ( v.to = $1; set_collected_field('', 'icmp_type', $2); set_collected_field('', 'icmp_code', $3); ); # Get access-group from the end of the line v.by_access_group_index = index(v.to, ' by access-group '); if ((v.by_access_group_index != -1) and (matches_regular_expression(v.to, ' by access-group "([^"]+)"'))) then ( v.to = substr(v.to, 0, v.by_access_group_index); set_collected_field('', 'access_group', $1); ); ); # if to_index != -1 ); # Deny # Handle "UDP access denied by ACL" lines # %ASA-3-710003: UDP access denied by ACL from 19.25.235.19/138 to DMZ:19.25.235.255/138 else if (matches_regular_expression(v.message, '^([A-Z]+) access denied by ACL from (.*)')) then ( set_collected_field('', 'protocol', $1); set_collected_field('', 'operation', 'Deny by ACL'); v.from_to = $2; # Extract "from" and "to" parts of the message v.to_index = index(v.from_to, ' to '); if (v.to_index != -1) then ( v.from = substr(v.from_to, 0, v.to_index); v.to = substr(v.from_to, v.to_index + 4); ); # if to_index != -1 ); # UDP access denied by ACL # Handle "Denied ICMP..." lines #2006-12-19 17:03:58 Local4.Error 192.168.1.137 Dec 19 2006 01:01:15: %ASA-3-313001: Denied ICMP type=8, code=0 from 192.168.1.135 on interface outside #Dec 5 04:17:38 1.1.1.10 %ASA-3-313001: Denied ICMP type=3, code=3 from 233.33.33.33 on interface outside #Oct 31 08:17:50 tdn-ar03-outside %FWSM-4-313004: Denied ICMP type=3, from laddr 254.54.54.54 on interface inside to 1.1.1.10: no matching session else if (matches_regular_expression(v.message, '^Denied ([A-Z]+) (.*)')) then ( set_collected_field('', 'operation', 'Deny'); set_collected_field('', 'protocol', $1); v.from_to = $2; # note compensation for Boost non-greediness if (matches_regular_expression(v.from_to, '^type=([^, ]+)[, ]+([^, ].*)')) then ( set_collected_field('', 'icmp_type', $1); v.from_to = $2; ); if (matches_regular_expression(v.from_to, '^code=([^, ]+)[, ]+([^, ].*)')) then ( set_collected_field('', 'icmp_code', $1); v.from_to = $2; ); if (matches_regular_expression(v.from_to, '^from (.*)$')) then ( v.from_to = $1; ); # Extract "from", "to", "interface" and "reason" parts of the message v.on_interface_index = index(v.from_to, ' on interface '); if (v.on_interface_index != -1) then ( v.from = substr(v.from_to, 0, v.on_interface_index); v.interface = substr(v.from_to, v.on_interface_index + 14); ); # if on_interface_index != -1 v.to_index = index(v.interface, ' to '); if (v.to_index != -1) then ( v.to = substr(v.interface, v.to_index + 4); v.interface = substr(v.interface, 0, v.to_index); # for now, assume this doesn't happen if there is no "to" part if (matches_regular_expression(v.to, '([^:]+): (.*)')) then ( v.to = $1; set_collected_field('', 'reason', $2); ); ); # if to_index != -1 set_collected_field('', 'interface', v.interface); if (matches_regular_expression(v.from, 'laddr (.*)')) then ( set_collected_field('', 'laddr_host', $1); v.from = ''; ); ); # Denied ICMP # Handle "Deny UDP reverse path check" #2006-12-19 13:08:47 Local4.Alert 192.168.1.137 Dec 18 2006 21:06:05: %ASA-1-106021: Deny UDP reverse path check from 192.168.1.134 to 192.168.1.255 on interface inside else if (matches_regular_expression(v.message, '^Deny UDP reverse path check from (.*)')) then ( v.from_to = $1; set_collected_field('', 'operation', 'Deny UDP reverse path check'); v.to_index = index(v.from_to, ' to '); if (v.to_index != -1) then ( v.from = substr(v.from_to, 0, v.to_index); v.to = substr(v.from_to, v.to_index + 4); # Get "on interface" from the end of the line v.on_interface_index = index(v.to, ' on interface '); if ((v.on_interface_index != -1) and matches_regular_expression(v.to, ' on interface (.*)$')) then ( v.to = substr(v.to, 0, v.on_interface_index); set_collected_field('', 'interface', $1); ); ); # if v.to_index != -1 ); # Deny UDP reverse path check # Handle Teardown lines else if (matches_regular_expression(v.message, '^(Teardown) (UDP|TCP|ICMP) connection (.*)')) then ( set_collected_field('', 'operation', $1); set_collected_field('', 'protocol', $2); v.from_to = $3; v.direction = "outbound"; # default if there was no Built line, or there is no connection number # Extract user name, if any if (matches_regular_expression(v.from_to, '^(.*)[ ]+\\\\(([a-zA-Z]+[a-zA-Z0-9._]+)\\\\)$')) then ( set_collected_field('', 'user_name', $2); v.from_to = $1; ); # Discard connection number, if any if (matches_regular_expression(v.from_to, '^([0-9-]+) (.*)$')) then ( v.from_to = $2; #if (get_collected_field($1, 'direction') eq 'inbound') then # might be 'outbound', '' or 'dynamic' # v.direction = "inbound"; v.direction = get_collected_field($1, 'direction'); set_collected_field('', 'direction', v.direction); if (v.direction eq "") then v.direction = 'outbound'; ); # Discard "for" if (matches_regular_expression(v.from_to, '^for (.*)$')) then v.from_to = $1; # Handle faddr/laddr/gaddr syntax if (matches_regular_expression(v.from_to, '^faddr ([0-9.]+)/([0-9]+) gaddr ([0-9.]+)/([0-9]+) laddr ([0-9.]+)/([0-9]+)(.*)$')) then ( set_collected_field('', 'faddr_host', $1); set_collected_field('', 'faddr_port', $2); set_collected_field('', 'gaddr_host', $3); set_collected_field('', 'gaddr_port', $4); set_collected_field('', 'laddr_host', $5); set_collected_field('', 'laddr_port', $6); v.remainder = $7; ); # if faddr/laddr/gaddr # Handle for/to syntax else ( # Extract "from" and "to" parts of the message v.to_index = index(v.from_to, ' to '); if (v.to_index != -1) then ( v.from_part = substr(v.from_to, 0, v.to_index); v.to_part = substr(v.from_to, v.to_index + 4); # Extract duration, bytes, and flags from end of line (end of v.to_part) v.duration_index = index(v.to_part, ' duration '); if (v.duration_index != -1) then ( v.remainder = substr(v.to_part, v.duration_index); v.to_part = substr(v.to_part, 0, v.duration_index); ); # if duration # Reverse from and to if outbound # 2009-11-20 - GMF - Maybe we should do this, but I'm not convinced. Look at this log data below [ThreadID:699166]. Clearly, 1.2.3.4 is the "to" address. # Indeed, the customer reports that reversing this is wrong, and that 1.2.3.4 *is* the "to" address in this case. Lacking any example # to the contrary, I'm commenting out this reversal. # # Oct 6 06:03:14 10.28.254.116 %ASA-6-302013: Built outbound TCP connection 1008993 for outside:A_BC-DE006/80 (A_BC-DE006/80) to inside:1.2.3.4/4594 (1.2.3.4/4594) # Oct 6 06:53:14 10.28.254.116 %ASA-6-302014: Teardown TCP connection 1008993 for outside:A_BC-DE006/80 to inside:1.2.3.4/4594 duration 0:50:00 bytes 354 TCP FINs # if (v.direction eq 'outbound') then ( # v.from = v.to_part; # v.to = v.from_part; # ); # else ( v.from = v.from_part; v.to = v.to_part; # ); ); # if for/to ); # if not faddr/laddr/gaddrbytes # Handle duration/flags section at end of line if (matches_regular_expression(v.remainder, '^ duration ([0-9:]+) (.*)$')) then ( set_collected_field('', 'duration', $1); v.remainder = $2; if (matches_regular_expression(get_collected_field('', 'duration'), '^([0-9]*):([0-9]*):([0-9]*)')) then ( set_collected_field('', 'duration', (60 * 60 * $1) + (60 * $2) + $3); ); v.bytes = 0; if (matches_regular_expression(v.remainder, '^bytes ([0-9]+) (.*)$')) then ( #set_collected_field('', 'bytes', $1); v.bytes = $1; set_collected_field('', 'flags', replace_first(replace_first($2, ')', ']'), '(', '[')); ); # if bytes and flags else if (matches_regular_expression(v.remainder, '^bytes ([0-9]+)$')) then ( #set_collected_field('', 'bytes', $1); v.bytes = $1; ); else if (matches_regular_expression(v.remainder, '^bytes ([0-9]+):')) then ( #set_collected_field('', 'bytes', $1); v.bytes = $1; ); # if just bytes # Compensate for Cisco bug where if bytes is (incorrectly) a small negative number # it will appear to be a huge number because the type is unsigned. #<166>:Jul 05 03:46:29 EST: %PIX-session-6-302014: Teardown TCP connection 181441 for Outside:222.22.222.22/80 to inside:10.22.2.22/1071 duration 0:00:03 bytes 4294967288 TCP FINs if (v.bytes > 4200000000) then ( v.bytes = 0; ); set_collected_field('', 'bytes', v.bytes); ); # extract duration set_collected_field('', 'connections_torn_down', 1); # count connections at teardown ); # Teardown # Handle access-list lines #Oct 31 08:17:56 tdn-ar03-outside %FWSM-5-106100: access-list outside permitted tcp outside/133.133.133.133(24333) -> inside/1.1.22.220(80) hit-cnt 1 (600-second interval) # Note: the following example isn't supported - Cisco says "no action required" #2006-03-01 11:21:58 Local7.Info 10.10.22.22 122: 00:24:02: %SEC-6-IPACCESSLOGRL: access-list logging rate-limited or missed 51 packets else if (matches_regular_expression(v.message, '^access-list ([^ ]*) (permitted|denied) (tcp|udp|icmp) ([^ ]*) -> ([^ ]*) (.*)$')) then ( set_collected_field('', 'access_list', $1); set_collected_field('', 'operation', $2); set_collected_field('', 'protocol', uppercase($3)); v.from = $4; v.to = $5; if (matches_regular_expression(v.from, '^([^/]*)/([0-9.]+)\\\\(([0-9]+)\\\\)$')) then ( set_collected_field('', 'source_side', $1); set_collected_field('', 'source_ip', $2); set_collected_field('', 'source_port', $3); v.from = ""; ); if (matches_regular_expression(v.to, '^([^/]*)/([0-9.]+)\\\\(([0-9]+)\\\\)$')) then ( set_collected_field('', 'destination_side', $1); set_collected_field('', 'destination_ip', $2); set_collected_field('', 'destination_port', $3); v.to = ""; ); ); # Handle "Portmapped translation built" lines else if (matches_regular_expression(v.message, '^(Portmapped translation built) for (.*)$')) then ( set_collected_field('', 'operation', $1); v.for = $2; # Handle laddr/gaddr syntax if (matches_regular_expression(v.for, '^gaddr ([0-9.]+)/([0-9]+) laddr ([0-9.]+)/([0-9]+)')) then ( set_collected_field('', 'gaddr_host', $1); set_collected_field('', 'gaddr_port', $2); set_collected_field('', 'laddr_host', $3); set_collected_field('', 'laddr_port', $4); ); # if laddr/gaddr ); # Portmapped translation built # Handle "No translation group found" lines else if (matches_regular_expression(v.message, '^(No translation group found) for (tcp|udp|icmp) ')) then ( set_collected_field('', 'operation', $1); set_collected_field('', 'protocol', uppercase($2)); ); # Handle "Invalid destination" lines #Mar 4 12:23:31 here.there.com Mar 04 2003 13:40:08: %PIX-4-313003: Invalid destination for ICMP error message: ICMP source 211.11.11.11 destination 244.44.44.44 (type 3, code 1) on outside interface. Original IP payload: TCP source 222.22.22.22/8080 destination 229.9.9.9/ #Jan 1 06:54:58 here.there.org %PIX-4-313003: Invalid destination for ICMP error message: icmp src service1:172.16.6.73 dst outside:206.38.38.36 (type 3, code 3) on service1 interface. Original IP payload: udp src 236.33.33.63/53 dst 172.16.16.16/3968. #else if (matches_regular_expression(v.message, '^(Invalid destination) for ([A-Z]+) error message: ([A-Z]+) source ([0-9.]+) destination ([0-9.]+) \\\\(type ([0-9]+), code ([0-9]+)\\\\) (.*)$')) then ( else if (matches_regular_expression(v.message, '^(Invalid destination) for ([^ ]+) error message: ([^ ]+) (src|source) (.*)')) then ( set_collected_field('', 'operation', $1); set_collected_field('', 'protocol', uppercase($2)); v.src = $4; v.from_to = $5; if (matches_regular_expression(v.from_to, '^(.*) \\\\(type ([0-9]+), code ([0-9]+)\\\\) on ([^ ]+) interface')) then ( set_collected_field('', 'icmp_type', $2); set_collected_field('', 'icmp_code', $3); set_collected_field('', 'interface', $4); v.from_to = $1; ); # no examples, but if this can happen for other protocols, it probably looks like this else if (matches_regular_expression(v.from_to, '^(.*) on ([^ ]+) interface')) then ( set_collected_field('', 'interface', $2); v.from_to = $1; ); # Extract "from" and "to" parts of the message v.splitter = " dst "; v.slength = 5; if (v.src eq 'source') then ( v.splitter = " destination "; v.slength = 13; ); v.to_index = index(v.from_to, v.splitter); if (v.to_index != -1) then ( v.from = substr(v.from_to, 0, v.to_index); v.to = substr(v.from_to, v.to_index + v.slength); ); ); # if Invalid destination # Handle "Denied SSH session" lines. # e.g. Denied SSH session from 11.12.220.50 on interface abc else if (matches_regular_expression(v.message, '^(Denied SSH session) from (.*)$')) then ( set_collected_field('', 'operation', $1); v.from = $2; # v.from is now '11.12.220.50 on interface abc' in the e.g. above. # Extract interface from end of line (end of v.from) v.on_interface_index = index(v.from, ' on interface '); if (v.on_interface_index != -1) then ( set_collected_field('', 'interface', substr(v.from, v.on_interface_index + 14)); v.from = substr(v.from, 0, v.on_interface_index); ); # if on interface ); # if Denied SSH session # Handle "Received ARP request collision" lines # e.g. Received ARP request collision from 12.126.51.13/01e0.81a3.4ff1 on interface abc else if (matches_regular_expression(v.message, '^(Received ARP request collision) from ([0-9.]+)/([0-9a-zA-Z.]+) on interface (.*)$')) then ( set_collected_field('', 'operation', $1); set_collected_field('', 'source_ip', $2); set_collected_field('', 'source_mac_address', $3); set_collected_field('', 'interface', $4); ); # if Received ARP request collision # Handle "Accessed URL" else if (contains(v.message, ' Accessed URL ')) then ( set_collected_field('', 'operation', 'Accessed URL'); v.accessed_url_index = index(v.message, ' Accessed URL '); v.source = substr(v.message, 0, v.accessed_url_index); v.url = substr(v.message, v.accessed_url_index + 14); # Extract source information if (matches_regular_expression(v.source, '^([A-Za-z][A-Za-z0-9_.]+)@(.*)$')) then ( set_collected_field('', 'user_name', $1); v.source = $2; ); if (matches_regular_expression(v.source, '^([0-9.]+)(.*)$')) then ( set_collected_field('', 'source_ip', $1); v.source = $2; if (matches_regular_expression(v.source, '^ \\\\([^)]+\\\\)$')) then set_collected_field('', 'source_hostname', $1); ); # Extract page information if (matches_regular_expression(v.url, '^([^:]+):(.*)$')) then ( v.destination = $1; set_collected_field('', 'page', $2); ); # Extract destination information if (matches_regular_expression(v.destination, '^([0-9.]+)(.*)$')) then ( set_collected_field('', 'destination_ip', $1); v.destination = $2; if (matches_regular_expression(v.destination, '^ \\\\([^)]+\\\\)$')) then set_collected_field('', 'destination_hostname', $1); ); ); # if Accessed URL #2006-12-19 11:05:00 Local4.Notice 199.169.9.139 Dec 18 2006 19:02:18: %ASA-5-111008: User 'user1' executed the 'match protocol yahoo-im msn-im' command. else if (matches_regular_expression(v.message, "^User '([^']+)' executed the '([^']+)' command\\\\.")) then ( set_collected_field('', 'operation', "Command executed"); set_collected_field('', 'user_name', $1); set_collected_field('', 'command', $2); ); # Handle crashinfo entries # these examples come from http://www.cisco.com/warp/public/63/crashinfo.html #%LINK-5-CHANGED: Interface Ethernet0/5, changed state to administratively down #%LINK-5-CHANGED: Interface FastEthernet9/1/0, changed state to administratively down #%LINK-3-UPDOWN: Interface Ethernet0/0, changed state to up #%LINK-3-UPDOWN: Interface Hssi9/0/1, changed state to up #%SYS-5-CONFIG_I: Configured from console by console #%SYS-5-CONFIG_I: Configured from console by vty0 (144.254.2.77) #%SYS-5-CONFIG_I: Configured from memory by console #2007-01-16 10:39:26 Local7.Notice 10.20.20.20 866: 1w3d: %LINK-5-CHANGED: Interface FastEthernet0/36, changed state to administratively down #2007-01-16 10:39:28 Local7.Error 10.20.20.20 867: 1w3d: %LINK-3-UPDOWN: Interface FastEthernet0/36, changed state to down else if (matches_regular_expression(v.message, '^Interface ([^,]+), (changed state) to (.*)')) then ( set_collected_field('', 'operation', $2); set_collected_field('', 'interface', $1); set_collected_field('', 'state', $3); ); #2007-01-16 10:39:37 Local7.Notice 10.20.20.20 868: 1w3d: %SYS-5-CONFIG_I: Configured from console by netadmin on vty0 (10.20.20.25) else if (matches_regular_expression(v.message, '^(Configured) from ([^ ]+) by (.*)')) then ( set_collected_field('', 'operation', $1); set_collected_field('', 'location', $2); v.user = $3; if (matches_regular_expression(v.user, '^(.*) on (vty[0-9]+) \\\\(([^)]+)\\\\)')) then ( v.user = $1; set_collected_field('', 'vty_line', $2); v.from = $3; ); else if (matches_regular_expression(v.user, '^(vty[0-9]+) \\\\(([^)]+)\\\\)')) then ( set_collected_field('', 'vty_line', $1); v.from = $2; v.user = ""; ); #else ( # don't know what to call the "by" field if it isn't a user - using user for now #v.user = ''; #); set_collected_field('', 'user_name', v.user); ); #Mar 5 17:03:52 something.somewhere.com 414331: a12345: Mar 5 17:03:52.051: %CRYPTO-6-EZVPN_CONNECTION_UP: (Server) Mode=CLIENT_OR_NEM_PLUS Client_type=UNKNOWN User=someone\somegroup Group=GROUP_USERS Client_public_addr=12.34.56.78 Server_public_addr=98.76.54.32 Assigned_client_addr=23.45.67.89 else if (get_collected_field('', 'message_facility') eq 'CRYPTO') then ( if (matches_regular_expression(v.message, '^[(]Server[)] (.*)$')) then ( v.message = $1; v.double_space_index = index(v.message, ' '); set_collected_field('', 'operation', substr(v.message, 0, v.double_space_index)); v.message = substr(v.message, v.double_space_index + 2); collect_listed_fields('', v.message, ' ', '=', 'User=user_name'); ); ); #else ( # debug # echo("unmatched line " . current_log_line()); #); ## Parse out alternate-format Deny lines #collect_fields_using_regexp('() (Deny) (tcp|udp|icmp) ', '*KEY*,operation,protocol'); ## Parse out Deny lines (without access group) #collect_fields_using_regexp('() (Deny) (tcp|udp|TCP) ([a-z ]*) ', '*KEY*,operation,protocol,type'); ## Parse out the Inbound TCP connection denied lines #collect_fields_using_regexp('()(Inbound) (TCP) (connection denied) ', '*KEY*,direction,protocol,operation'); ## Parse out the ICMP packet denied lines #collect_fields_using_regexp('()(ICMP) packet type [0-9]+ (denied) ', '*KEY*,protocol,operation'); ## Parse Teardown local-host #collect_fields_using_regexp(' ()(Teardown local-host) ([^:]*):([^/ ]*)/*([0-9]*) duration ([0-9:]+)', '*KEY*,operation,source_side,source_ip,source_port,duration'); ## Parse out the Built UDP connection lines #collect_fields_using_regexp('()(Built) (UDP)', '*KEY*,operation,protocol'); ## Parse out the Teardown UDP connection lines #collect_fields_using_regexp('()(Teardown) ([^ ]*) ', '*KEY*,operation,protocol'); ## Parse out the interface #collect_fields_using_regexp('() interface ([^\\']*)', '*KEY*,interface'); ## Parse out the flags #collect_fields_using_regexp('() flags ([A-Z ]* [^ ]*)', '*KEY*,flags'); ## Parse out the bytes field #collect_fields_using_regexp('() bytes ([0-9]*)', '*KEY*,bytes'); ## Parse out the duration field #collect_fields_using_regexp('() duration ([0-9:]*)', '*KEY*,duration'); ## Parse from/to info #collect_fields_using_regexp('() from ([.0-9]*) to ([0-9.]*) ', '*KEY*,source_ip,destination_ip'); ## Parse for/to or from/to lines with unresolved hostnames #collect_fields_using_regexp('() f(or|rom) ([a-zA-Z0-9]+):([^:/ ]*)/*([0-9]*) to ([a-zA-Z0-9]+):([^:/ ]*)/*([0-9]*) ', '*KEY*,dummy,source_side,source_ip,source_port,destination_side,destination_ip,destination_port'); ## Parse src/dst or from/to lines with resolved hostname #collect_fields_using_regexp(' ()(from|src) ([a-zA-Z0-9]+):([0-9.]*) \\\\(([^)]*)\\\\) /*([0-9]*) (to|dst) ([a-zA-Z0-9]+):([0-9.]*) \\\\(([^)]*)\\\\) /*([0-9]*)', '*KEY*,dummy,source_side,source_ip,source_hostname,source_port,dummy,destination_side,destination_ip,destination_hostname,destination_port'); ## Parse src/dst lines with just IPs or just hostnames #collect_fields_using_regexp(' ()src ([a-zA-Z0-9]+):([0-9.A-Za-z_]*)/*([0-9]*) dst ([a-zA-Z0-9]+):([0-9.A-Za-z_]*)/*([0-9]*)', '*KEY*,source_side,source_ip,source_port,destination_side,destination_ip,destination_port'); ## Parse src/dest lines #collect_fields_using_regexp(' ()src ([0-9.]+) *([0-9]*) dest ([0-9.]+) *([0-9]*)', '*KEY*,source_ip,source_port,destination_ip,destination_port'); ## Parse out the source/destination IP/port #collect_fields_using_regexp('() from ([0-9.]*)/([0-9]*) to ([0-9.]*)/([0-9]*)', '*KEY*,source_ip,source_port,destination_ip,destination_port'); ## Parse out the source/destination IP/hostname/port #collect_fields_using_regexp('() from ([0-9.]*) \\\\(([^)]*)\\\\) /([0-9]*) to ([0-9.]*) \\\\(([^)]*)\\\\) /([0-9]*) ', '*KEY*,source_ip,source_hostname,source_port,destination_ip,destination_hostname,destination_port'); ## Parse out the faddr/laddr/gaddr info #collect_fields_using_regexp('() faddr ([^/]*)/([^ ]*) ', '*KEY*,faddr_host,faddr_port'); ## Parse out gaddr/laddr info #collect_fields_using_regexp('() gaddr ([^/]*)/([^ ]*) laddr ([^/]*)/([^ ]*)', '*KEY*,gaddr_host,gaddr_port,laddr_host,laddr_port'); ## Parse out global/local lines #collect_fields_using_regexp('() global ([^/]*)/([^ ]*) local ([^/]*)/([^ ]*)', '*KEY*,gaddr_host,gaddr_port,laddr_host,laddr_port'); ## Parse out the "Accessed URL" lines #collect_fields_using_regexp('() ([0-9.]*) (Accessed URL) ([^:]*):([^\\']*)', '*KEY*,source_ip,operation,destination_ip,page'); ## Parse out the "Accessed URL" lines with resolved hostnames #collect_fields_using_regexp('() ([0-9.]*) \\\\(([^)]*)\\\\) (Accessed URL) ([^:]*) \\\\(([^)]*)\\\\) :([^\\']*)', '*KEY*,source_ip,source_hostname,operation,destination_ip,destination_hostname,page'); ## Parse out the "Accessed URL" lines #collect_fields_using_regexp('() (Accessed URL) ([^\\']*)', '*KEY*,operation,url'); ## Parse a tcp|udp list line #collect_fields_using_regexp('()(list) ([^ ]*) (permitted|denied) (tcp|udp) ([0-9.]*) *\\\\(*([^)]*)\\\\)* *\\\\(([0-9]*)\\\\).*-> ([0-9.]*) *\\\\(*([^)]*)\\\\)* *\\\\(([0-9]*)\\\\), [0-9]* packet', '*KEY*,type,list,operation,protocol,source_ip,source_hostname,source_port,destination_ip,destination_hostname,destination_port'); ## Parse a access-list line with sides and IPs #collect_fields_using_regexp('()(access-list) ([^ ]*) (permitted|denied) (tcp|udp) ([^/]+)/([0-9.]*)\\\\(([0-9]*)\\\\) -> ([^/]+)/([0-9.]*)\\\\(([0-9]*)\\\\)', '*KEY*,type,list,operation,protocol,source_side,source_ip,source_port,destination_side,destination_ip,destination_port'); ## Parse a tcp|udp list line #collect_fields_using_regexp('()(tcp|udp) (connection denied) by (outbound list) ([^ ]*)', '*KEY*,protocol,operation,type,list'); ## Parse a icmp list line #collect_fields_using_regexp('()(list) ([0-9]*) (permitted|denied) (icmp) ([0-9.]*).*-> ([0-9.]*) ', '*KEY*,type,list,operation,protocol,source_ip,destination_ip'); ## Parse a route add line #collect_fields_using_regexp('()(RT): (add) ([0-9.]*) ([0-9.]*) via ([0-9.]*), isis metric \\\\[([0-9]*/[0-9]*)\\\\]', '*KEY*,type,operation,destination_ip,netmask,router,metric'); ## Parse a route delete line #collect_fields_using_regexp('()(RT): (delete route) to ([0-9.]*) via ([0-9.]*), isis metric \\\\[([0-9]*/[0-9]*)\\\\]', '*KEY*,type,operation,destination_ip,router,metric'); ## Parse a delete subnet route line #collect_fields_using_regexp('()(RT): (delete subnet route) to ([0-9.]*) ([0-9.]*)', '*KEY*,type,operation,destination_ip,subnet'); ## Parse a no routes line #collect_fields_using_regexp('()(RT): (no routes) to ([0-9.]*)', '*KEY*,type,operation,destination_ip'); ## Parse an FW-3/4 line; put the full error in message #collect_fields_using_regexp('()%FW-[34][^:]*: ([^\\']*)', '*KEY*,message'); ## Parse an FW-3 line with initiator info #collect_fields_using_regexp('()%FW-3[^:]*: (.*)\\\\(total ([0-9]*) chars\\\\) from initiator \\\\(([0-9.]*):([0-9]*)', '*KEY*,message,bytes,source_ip,source_port'); ## Parse an FW-6 line #if (matches_regular_expression(v.syslog_message, '%FW-6[^:]*: (Stop http session): initiator \\\\(([0-9.]+):([0-9]+)\\\\) sent ([0-9]+) bytes -- responder \\\\(([0-9.]+):([0-9]+)\\\\) sent ([0-9]+) bytes')) then ( # set_collected_field('', 'operation', $1); # set_collected_field('', 'source_ip', $2); # set_collected_field('', 'source_port', $3); # set_collected_field('', 'bytes', $4); # set_collected_field('', 'destination_ip', $5); # set_collected_field('', 'destination_port', $6); # set_collected_field('', 'destination_bytes', $7); #); ## Parse an AUDIT_TRAIL line #collect_fields_using_regexp('()AUDIT_TRAIL: ([a-z-]*) (session initiator) \\\\(([0-9.]*):([0-9]*)\\\\) sent ([0-9]*) bytes -- responder \\\\(([0-9.]*):([0-9]*)\\\\) sent ([0-9]*) bytes', '*KEY*,protocol,operation,source_ip,source_port,bytes,destination_ip,destination_port,destination_bytes'); ## parse IDS events #collect_fields_using_regexp('() (IDS:.*) from', '*KEY*,message'); ## parse audit cmd lines #collect_fields_using_regexp('() User *\\'([^\\']*)\\' executed cmd: ([^\\']*)', '*KEY*,user,command'); ## Parse out the audit command lines #collect_fields_using_regexp('()User *\\'([^\\']*)\\' executed the \\'([^\\']*)\\' command', '*KEY*,user,command'); ## Parse out the audit operation lines #collect_fields_using_regexp('()User *\\'([^\\']*)\\' executed the \\'([^\\']*)\\' command', '*KEY*,user,command'); ## Parse out the audit operation lines #collect_fields_using_regexp('() (New user added to local dbase|User deleted from local dbase): Uname: ([^ ]*) ', '*KEY*,operation,user'); # Parse "from" information if (v.from ne '') then ( if (matches_regular_expression(v.from, '^([^:]+):(.*)$')) then ( set_collected_field('', 'source_side', $1); v.from = $2; ); if (matches_regular_expression(v.from, '^([^ ]*)/([0-9]+)')) then ( set_collected_field('', 'source_ip', $1); set_collected_field('', 'source_port', $2); ); else if (matches_regular_expression(v.from, '^([0-9.]+) \\\\(([^)]+)\\\\)(.*)$')) then ( set_collected_field('', 'source_ip', $1); set_collected_field('', 'source_hostname', $2); v.remainder = $3; if (matches_regular_expression(v.remainder, '^ /([0-9]+)')) then set_collected_field('', 'source_port', $1); ); else if (matches_regular_expression(v.from, '^([0-9.]+)$')) then ( set_collected_field('', 'source_ip', $1); ); ); # Parse "to" information if (v.to ne '') then ( if (matches_regular_expression(v.to, '^([^:]+):(.*)$')) then ( set_collected_field('', 'destination_side', $1); v.to = $2; ); if (matches_regular_expression(v.to, '^([^ ]*)/([0-9]+)')) then ( set_collected_field('', 'destination_ip', $1); set_collected_field('', 'destination_port', $2); ); else if (matches_regular_expression(v.to, '^([0-9.]+) \\\\(([^)]+)\\\\)(.*)$')) then ( set_collected_field('', 'destination_ip', $1); set_collected_field('', 'destination_hostname', $2); v.remainder = $3; if (matches_regular_expression(v.remainder, '^ /([0-9]+)')) then set_collected_field('', 'destination_port', $1); ); else if (matches_regular_expression(v.to, '^([0-9.]+)$')) then ( set_collected_field('', 'destination_ip', $1); ); ); # Accept this log entry accept_collected_entry('', false); # Handle repeat lines (specified with hit-cnt) hit_cnt_index = index(v.message, 'hit-cnt'); if (hit_cnt_index != -1) then ( if (matches_regular_expression(current_log_line(), '^(.*) hit-cnt ([0-9]+)(.*)$')) then ( hit_cnt = $2; insert_line = $1 . $3; for (hit_cnt_i = 1; hit_cnt_i < hit_cnt; hit_cnt_i++) set_subnode_value('volatile.log_line_insertions', hit_cnt_i, insert_line); ); ); ); # if message code extracted ` # Database fields database.fields = { operation = "" message = "" message_code = "" message_facility = "" message_severity = "" message_mnemonic = "" protocol = "" source_ip = "" source_mac_address = "" location = "" destination_ip = "" source_hostname = "" destination_hostname = "" source_port = "" destination_port = "" source_side = "" destination_side = "" destination_service = "" interface = "" direction = "" user_name = "" group = "" access_group = "" access_list = "" faddr_host = "" faddr_port = "" faddr_service = "" gaddr_host = "" gaddr_port = "" gaddr_service = "" laddr_host = "" laddr_port = "" laddr_service = "" page = "" flags = "" #user = "" command = "" type = "" list = "" reason = "" icmp_type = "" icmp_code = "" state = "" vty_line = "" aaa_status = "" aaa_server = "" group_policy = "" private_ip = "" # CRYPTO fields client_type = "" client_public_addr = "" client_application_version = "" server_public_addr = "" assigned_public_addr = "" session_type = "" } # database.fields # Log Filters log.filters = { set_page_for_worm = { label = "$lang_admin.log_filters.set_page_for_worm_label" comment = "$lang_admin.log_filters.set_page_for_worm_comment" value = "if (starts_with(worm, '(')) then '' else page = '[worm]';" } # set_page_for_worm detect_page_views = { label = '$lang_admin.log_filters.detect_page_views_label' comment = '$lang_admin.log_filters.detect_page_views_comment' value = "if ((page eq '(empty)') or (file_type eq 'JPEG') or (file_type eq 'JPG') or (file_type eq 'GIF') or (file_type eq 'ICO') or (file_type eq 'PNG') or (file_type eq 'CSS') or (file_type eq 'SWF') or (file_type eq 'JS')) then page_views = 0; else page_views = 1;" } # detect_page_views # strip_non_page_views = { # label = '$lang_admin.log_filters.strip_non_page_views_label' # comment = '$lang_admin.log_filters.strip_non_page_views_comment' # value = "if (page_views == 0) then url = substr(url, 0, last_index(url, '/') + 1) . '(nonpage)';" # } # strip_non_page_views simplify_page = { label = "Simplify page" comment = "This removes page information from the database" value = "page = '(page removed)'" } # simplify_page strip_message = { label = '$lang_admin.log_filters.strip_message_label' comment = '$lang_admin.log_filters.strip_message_comment' value = "message = '[message removed]'" } # strip_message mark_entry = { label = '$lang_admin.log_filters.mark_entry_label' comment = '$lang_admin.log_filters.mark_entry_comment' value = 'events = 1;' } # mark_entry # Setting the service to "(unknown)" was removed at the request of an IOS user # who feels that the port and protocol are valuable information in this context. # It is left commented out to make it easy to put back if anyone wants to. look_up_service = { label = '$lang_admin.log_filters.look_up_service' comment = '$lang_admin.log_filters.look_up_comment' value = ` if ((destination_port eq '(empty)') and (protocol eq '(empty)')) then ( destination_service = '(empty)'; ); else ( destination_service = destination_port . "_" . lowercase(protocol); if (subnode_exists('rewrite_rules.services', destination_service)) then destination_service = node_value(subnode_by_name("rewrite_rules.services", destination_service)); #else # destination_service = '(unknown)'; ); ` } # look_up_service look_up_faddr_service = { label = 'Look up faddr service' comment = 'Compute faddr service from faddr port and protocol' value = ` faddr_service = faddr_port . "_" . (if (starts_with(protocol, '.')) then 'tcp' else lowercase(protocol)); if (subnode_exists('rewrite_rules.services', faddr_service)) then faddr_service = node_value(subnode_by_name("rewrite_rules.services", faddr_service)); else faddr_service = '(unknown)'; ` } # look_up_faddr_service look_up_gaddr_service = { label = 'Look up gaddr service' comment = 'Compute gaddr service from gaddr port and protocol' value = ` gaddr_service = gaddr_port . "_" . (if (starts_with(protocol, '.')) then 'tcp' else lowercase(protocol)); if (subnode_exists('rewrite_rules.services', gaddr_service)) then gaddr_service = node_value(subnode_by_name("rewrite_rules.services", gaddr_service)); else gaddr_service = '(unknown)'; ` } # look_up_gaddr_service look_up_laddr_service = { label = 'Look up laddr service' comment = 'Compute laddr service from laddr port and protocol' value = ` laddr_service = laddr_port . "_" . (if (starts_with(protocol, '.')) then 'tcp' else lowercase(protocol)); if (subnode_exists('rewrite_rules.services', laddr_service)) then laddr_service = node_value(subnode_by_name("rewrite_rules.services", laddr_service)); else laddr_service = '(unknown)'; ` } # look_up_laddr_service } # log.filters log.field_options = { sessions_page_field = "destination_ip" sessions_visitor_id_field = "source_ip" sessions_event_field = "page_views" } # log.field_options database.numerical_fields = { events = { default = true requires_log_field = false entries_field = true } # events connections_built = { default = true requires_log_field = false } # connections_built connections_torn_down = { default = true requires_log_field = false } # connections_torn_down page_views = { requires_log_field = false } # page_views unique_source_ips = { log_field = "source_ip" type = "unique" display_format_type = "integer" } # unique_source_ips bytes = { type = "float" display_format_type = "bandwidth" } # bytes bytes_xmt = { type = "float" display_format_type = "bandwidth" } # bytes_xmt bytes_rcv = { type = "float" display_format_type = "bandwidth" } # bytes_rcv # destination_bytes = { # type = "float" # display_format_type = "bandwidth" # } # destination_bytes duration = { type = int display_format_type = duration_compact } # duration packets = "" } # database.numerical_fields create_profile_wizard_options = { host_tracking = true # How the reports should be grouped in the report menu report_groups = { date_time_group = "" source_group = { source_ip = true source_hostname = true source_port = true source_side = true source_mac_address = true #user = true interface = true laddr_host = true laddr_port = true laddr_service = true location = true user_name = true group = true } destination_group = { destination_ip = true destination_hostname = true destination_port = true destination_side = true page = true faddr_host = true faddr_port = true faddr_service = true gaddr_host = true gaddr_port = true gaddr_service = true destination_service = true destination_ip_by_source_ip = true destination_service_by_source_ip = true faddr_host_by_laddr_host = true faddr_service_by_laddr_host = true gaddr_host_by_laddr_host = true gaddr_service_by_laddr_host = true } crypto_group = { client_type = true client_public_addr = true server_public_addr = true assigned_public_addr = true } # crypto_group other_group = { logging_device = true syslog_priority = true list = true operation = true direction = true access_group = true access_list = "" message = true message_code = true message_facility = true message_severity = true message_mnemonic = true protocol = true flags = true command = true type = true reason = true icmp_type = true icmp_code = true state = true vty_line = true aaa_status = true aaa_server = true group_policy = true private_ip = true session_type = true } } # report_groups } # create_profile_wizard_options } # cisco_pix