ELK - Logstash exemples de patterns grok
Alasta 16 Novembre 2015 linux shell cli BigData
Description : Nous allons voir des exemples de patterns grok.
Patterns :
Access log Apache
#Gestion des logs access apache dans syslog
grok {
match => { "message" => "%{SYSLOG5424PRI}%{SYSLOGBASE2} %{COMBINEDAPACHELOG}" }
add_tag => [ "apache", "accesslogs" ]
}
iptables
grok {
patterns_dir => ["/etc/logstash/patterns"]
match => { "message" => "%{IPTABLES}"}
add_tag => [ "iptables", "iptables-drop"]
}
Fichier de pattern :
DHCPD ((%{SYSLOGTIMESTAMP:timestamp})\s*(%{HOSTNAME:hostname})\s*dhcpd\S+\s*(%{WORD:dhcp_action})?.*[for|on] (%{IPV4:dhcp_client_ip})?.*[from|to] (%{COMMONMAC:dhcp_client_mac})?.*via (%{USERNAME:interface}))
#IPTABLES ((%{SYSLOGTIMESTAMP:nf_timestamp})\s*(%{HOSTNAME:nf_host})\s*kernel\S+\s*(%{WORD:nf_action})?.*IN=(%{USERNAME:nf_in_interface})?.*OUT=(%{USERNAME:nf_out_interface})?.*MAC=(%{COMMONMAC:nf_dst_mac}):(%{COMMONMAC:nf_src_mac})?.*SRC=(%{IPV4:nf_src_ip}).*DST=(%{IPV4:nf_dst_ip}).*PROTO=(%{WORD:nf_protocol}).?*SPT=(%{INT:nf_src_port}?.*DPT=%{INT:nf_dst_port}?.*))
#Gestion de IPv4 et v6
IPTABLES ((%{SYSLOGTIMESTAMP:nf_timestamp})\s*(%{HOSTNAME:nf_host})\s*kernel\S+\s*(%{WORD:nf_action})?.*IN=(%{USERNAME:nf_in_interface})?.*OUT=(%{USERNAME:nf_out_interface})?.*MAC=(%{COMMONMAC:nf_dst_mac}):(%{COMMONMAC:nf_src_mac})?.*SRC=(%{IP:nf_src_ip}).*DST=(%{IP:nf_dst_ip}).*PROTO=(%{WORD:nf_protocol}).?*SPT=(%{INT:nf_src_port}?.*DPT=%{INT:nf_dst_port}?.*))
DNS ((%{MONTHDAY:day})-(%{MONTH:month})-(%{YEAR:year}) (%{TIME:timestamp}) client (%{IPV4:dns_client_ip})#(%{NONNEGINT:dns_uuid})?.*query: (%{HOSTNAME:dns_dest}) (%{WORD:dns_type}) (%{WORD:dns_record})?.*(%{IPV4:dns_server}))
PGSQL ((%{SYSLOGTIMESTAMP:pgsql_timestamp}) (%{HOSTNAME:pgsql_hostname})?.*SAST >(%{WORD:pgsql_severity}): (%{GREEDYDATA:pgsql_message}))
SQUID ((%{DATA:squid_timestamp_unix}) (%{INT:squid_time_elapsed_ms}) (%{IPV4:squid_client_ip}) (%{DATA:squid_action})/(%{INT:squid_reply_code}) (%{INT:squid_request_size}) (%{WORD:squid_method}) (%{URIPROTO:squid_request_protocol})://(%{DATA:squid_request_hostname}) - (%{WORD:squid_heirarchy})/(%{IPV4:squid_dest_ip}) (%{WORD:squid_content_type})/(%{WORD:squid_content_object}))
RADIUSINFO ((%{SYSLOGTIMESTAMP:radius_timestamp}) (%{YEAR}) : (%{WORD:radius_severity}): (%{GREEDYDATA:radius_messsage}))
RADIUSERROR ((%{SYSLOGTIMESTAMP:radius_timestamp}) (%{YEAR}) : (%{WORD:radius_severity}): (%{DATA:radius_module}): (%{GREEDYDATA:radius_messsage}))
RADIUSAUTHOKMAC ((%{SYSLOGTIMESTAMP:radius_timestamp}) (%{YEAR}) : (%{WORD:radius_severity}): (%{GREEDYDATA:radius_login_status}) \[(%{USERNAME:radius_user})/(%{USERNAME:radius_password})\] \(from client (%{GREEDYDATA:radius_from_client}) port (%{INT:radius_nas_port}) (%{WORD}) (%{GREEDYDATA:radius_mac})\))
RADIUSAUTHOK ((%{SYSLOGTIMESTAMP:radius_timestamp}) (%{YEAR}) : (%{WORD:radius_severity}): (%{GREEDYDATA:radius_login_status}) \[(%{USERNAME:radius_user})/(%{USERNAME:radius_password})\] \(from client (%{GREEDYDATA:radius_from_client}) port (%{INT:radius_nas_port}))
RADIUSAUTHFAIL ((%{SYSLOGTIMESTAMP:radius_timestamp}) (%{YEAR}) : (%{WORD:radius_severity}): (%{GREEDYDATA:radius_login_status}): \[(%{USERNAME:radius_user})/(%{USERNAME:radius_password})\] \(from client (%{GREEDYDATA:radius_from_client}) port (%{INT:radius_nas_port}))
fail2ban
grok {
match => { "message" => "(%{SYSLOGTIMESTAMP:f2b_timestamp})\s*(%{HOSTNAME:f2b_host})\s*fail2ban.action\S+\s*(%{WORD:f2b_level})\s*\[(%{GREEDYDATA:f2b_jail})\s*\]\s*(%{WORD:f2b_action})\s*(%{IPORHOST:src_ip})" }
add_tag => [ "fail2ban" ]
}
DenyALL rWeb
Trafic logs
grok {
keep_empty_captures => true
match => { "message" => "<(?<id>[^>]+)>(?<first_timestamp_MMM>\w{3})\s+(?<first_timestamp_dd>\d{1,2})\s+(?<first_timestamp_hh>\d{2}):(?<first_timestamp_mm>\d{2}):(?<first_timestamp_ss>\d{2})\s+(?<device>\S+)\s+(?<program>\S+)\s+(?<timestamp_yyyy>\d{4})-(?<timestamp_MM>\d{2})-(?<timestamp_dd>\d{2})\s+(?<timestamp_hh>\d{2}):(?<timestamp_mm>\d{2}):(?<timestamp_ss>\d{2})\.(?<timestamp_SSSSS>\d+)\s+(?<timestamp_ZZ>[^,]*),%{IP:local_ip},(?<hostname>[^,]+),%{IP:remote_ip},(?<x_forwarded_for>(\"([^\"])*\")|([^,]*)),(?<via>[^,]*),(?<user>[^,]*),(?<user_agent>(\"+[^\"]+\"+|[^,]*)),(?<SSL>\d),(?<SSL_version>[^,]*),(?<SSL_client_DN>[^,]*),(?<SSL_certificate_start>[^,]*),(?<SSL_certificate_end>[^,]*),(?<HTTP_method>[^,]+),(?<URL>[^,]+),(?<URL_options>.*),(?<HTTP_version>HTTP[^,]+),%{NUMBER:HTTP_response_code:int},%{NUMBER:HTTP_response_time:int},%{NUMBER:bytes_received:int},%{NUMBER:bytes_sent:int},(?<referrer>[^,]*),(?<cache>[^,]*),(?<gzip_ratio>[^,]*),(?<applicationID>[^,]+),(?<source_port>\d+),(?<application>[^,]+),(?<unique_id>[^,]+),(?<cookie>[^,]*)(,?)(?<posted_data>.*)"}
# Specify in this custom field the +/- hours of the timezone (+1h for Europe/Paris)
add_field => [ "timezone", "+0100" ]
add_field => [ "log_type", "traffic" ]
add_tag => [ "rweb_logs", "rweb_traffic_logs" ]
}
Alert logs
grok {
keep_empty_captures => true
match => { "message" => "<(?<id>[^>]+)>(?<first_timestamp_MMM>\w{3})\s+(?<first_timestamp_dd>\d{1,2})\s+(?<first_timestamp_hh>\d{2}):(?<first_timestamp_mm>\d{2}):(?<first_timestamp_ss>\d{2})\s+(?<device>\S+)\s+\S+\s+(?<log_id>\d+)\s+(?<timestamp_yyyy>\d{4})-(?<timestamp_MM>\d{2})-(?<timestamp_dd>\d{2})\s+(?<timestamp_hh>\d{2}):(?<timestamp_mm>\d{2}):(?<timestamp_ss>\d{2})\.(?<timestamp_SSSSS>\d+)\s+%{IP:source_ip}\s+%{IP:remote_ip}\s+\S+\s+(?<alert_id>\d+\.\d+\.\d+\.\d+)\s+(?<applicationID>\S+)\s+(?<unique_id>\S+)\s+(?<sec_bl_sl_id>(([0-9]{5}|.{0})-[0-9]{0,3}\s)+)\s*(?<sec_attack_id>([0-9a-zA-Z]{8}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{12}|-))\s+\'(?<description>[^']*)\'\s+\'(?<attack_family>[^']+)\'" }
# Specify in this custom field the +/- hours of the timezone (+1h for Europe/Paris)
add_field => [ "timezone", "+0100" ]
add_field => [ "log_type", "alert" ]
# Duplicate field for get Application Name after
add_field => [ "application", "%{applicationID}" ]
add_tag => [ "rweb_logs" , "rweb_alert_logs"]
}
Du fait que les Alert logs ne fournissent pas le nom d’application mais que l’UID, on duplique l’UID dans un nouveau champ (application) et ensuite on modifie de manière statique (ou scripté) via un mutate.
mutate {
# remove_field => [ "message" ]
} alter {
condrewrite => [
"user", "", "-",
"bytes_received", "", "-",
"referrer", "", "-",
"application", "56b7df6c-e9e6-454d-9ab5-45d357aaf5e7", "APP_NAME",
"timestamp_MM", "01", "Jan",
"timestamp_MM", "02", "Feb",
"timestamp_MM", "03", "Mar",
"timestamp_MM", "04", "Apr",
"timestamp_MM", "05", "May",
"timestamp_MM", "06", "Jun",
"timestamp_MM", "07", "Jul",
"timestamp_MM", "08", "Aug",
"timestamp_MM", "09", "Sep",
"timestamp_MM", "10", "Oct",
"timestamp_MM", "11", "Nov",
"timestamp_MM", "12", "Dec" ]
}
}