# Input section input { # Suricata file { path => ["/data/suricata/log/eve.json"] codec => json type => "Suricata" } # P0f file { path => ["/data/p0f/log/p0f.json"] codec => json type => "P0f" } # Ciscoasa file { path => ["/data/ciscoasa/log/ciscoasa.log"] codec => plain type => "Ciscoasa" } # Conpot file { path => ["/data/conpot/log/*.json"] codec => json type => "ConPot" } # Cowrie file { path => ["/data/cowrie/log/cowrie.json"] codec => json type => "Cowrie" } # Dionaea file { path => ["/data/dionaea/log/dionaea.json"] codec => json type => "Dionaea" } # Elasticpot file { path => ["/data/elasticpot/log/elasticpot.log"] codec => json type => "ElasticPot" } # eMobility file { path => ["/data/emobility/log/centralsystemEWS.log"] type => "eMobility" } # Glastopf file { path => ["/data/glastopf/log/glastopf.log"] type => "Glastopf" } # Glutton file { path => ["/data/glutton/log/glutton.log"] codec => json type => "Glutton" } # Heralding file { path => ["/data/heralding/log/auth.csv"] type => "Heralding" } # Honeytrap file { path => ["/data/honeytrap/log/attackers.json"] codec => json type => "Honeytrap" } # Mailoney file { path => ["/data/mailoney/log/commands.log"] type => "Mailoney" } # Rdpy file { path => ["/data/rdpy/log/rdpy.log"] type => "Rdpy" } # Host Syslog file { path => ["/data/host/log/auth.log"] codec => plain type => "Syslog" } # Host NGINX file { path => ["/data/host/log/nginx/access.log"] codec => json type => "NGINX" } # Tanner file { path => ["/data/tanner/log/tanner_report.json"] codec => json type => "Tanner" } # Vnclowpot file { path => ["/data/vnclowpot/log/vnclowpot.log"] type => "Vnclowpot" } } # Filter Section filter { # Suricata if [type] == "Suricata" { date { match => [ "timestamp", "ISO8601" ] } translate { refresh_interval => 86400 field => "[alert][signature_id]" destination => "[alert][cve_id]" dictionary_path => "/etc/listbot/cve.yaml" } } # P0f if [type] == "P0f" { date { match => [ "timestamp", "yyyy'/'MM'/'dd HH:mm:ss" ] remove_field => ["timestamp"] } mutate { rename => { "server_port" => "dest_port" "server_ip" => "dest_ip" "client_port" => "src_port" "client_ip" => "src_ip" } } } # Ciscoasa if [type] == "Ciscoasa" { kv { remove_char_key => " '{}" remove_char_value => "'{}" value_split => ":" field_split => "," } date { match => [ "timestamp", "ISO8601" ] } mutate { add_field => { "dest_ip" => "${MY_EXTIP}" } } } # Conpot if [type] == "ConPot" { date { match => [ "timestamp", "ISO8601" ] } } # Cowrie if [type] == "Cowrie" { date { match => [ "timestamp", "ISO8601" ] } mutate { rename => { "dst_port" => "dest_port" "dst_ip" => "dest_ip" } } } # Dionaea if [type] == "Dionaea" { date { match => [ "timestamp", "ISO8601" ] } mutate { rename => { "dst_port" => "dest_port" "dst_ip" => "dest_ip" } gsub => [ "src_ip", "::ffff:", "", "dest_ip", "::ffff:", "" ] } if [credentials] { mutate { add_field => { "login.username" => "%{[credentials][username]}" "login.password" => "%{[credentials][password]}" } remove_field => "[credentials]" } } } # ElasticPot if [type] == "ElasticPot" { date { match => [ "timestamp", "ISO8601" ] } } # eMobility if [type] == "eMobility" { grok { match => [ "message", "\A%{IP:src_ip}\.%{POSINT:src_port:integer}\|%{IP:dest_ip}\.%{POSINT:dest_port:integer}:%{SPACE}%{SYSLOG5424PRINTASCII}%{SPACE}%{SYSLOG5424PRINTASCII}%{SPACE}%{SYSLOG5424PRINTASCII}%{SPACE}%{SYSLOG5424PRINTASCII}%{SPACE}%{SYSLOG5424PRINTASCII}%{SPACE}%{SYSLOG5424PRINTASCII}%{SPACE}%{SYSLOG5424PRINTASCII}%{SPACE}%{SYSLOG5424PRINTASCII}%{SPACE}%{SYSLOG5424PRINTASCII}%{SPACE}%{SYSLOG5424SD}%{SYSLOG5424PRINTASCII}%{SPACE}%{SYSLOG5424PRINTASCII}%{SPACE}%{SYSLOG5424PRINTASCII}%{SPACE}%{URIPROTO:http_method}\|%{URIPATH:http_uri}\|%{TIMESTAMP_ISO8601:timestamp}" ] } date { match => [ "timestamp", "ISO8601" ] } } # Glastopf if [type] == "Glastopf" { grok { match => [ "message", "\A%{TIMESTAMP_ISO8601:timestamp}%{SPACE}%{NOTSPACE}%{SPACE}%{IP:src_ip}%{SPACE}%{WORD}%{SPACE}%{URIPROTO:http_method}%{SPACE}%{NOTSPACE:http_uri}%{SPACE}%{NOTSPACE}%{SPACE}%{HOSTNAME}:%{NUMBER:dest_port:integer}" ] } date { match => [ "timestamp", "yyyy-MM-dd HH:mm:ss,SSS" ] remove_field => ["timestamp"] } } # Glutton if [type] == "Glutton" { date { match => [ "ts", "UNIX" ] remove_field => ["ts"] } } # Heralding if [type] == "Heralding" { csv { columns => ["timestamp","auth_id","session_id","src_ip","src_port","dest_ip","dest_port","proto","username","password"] separator => "," } date { match => [ "timestamp", "yyyy-MM-dd HH:mm:ss.SSSSSS" ] remove_field => ["timestamp"] } } # Honeytrap if [type] == "Honeytrap" { date { match => [ "timestamp", "ISO8601" ] } mutate { rename => { "[attack_connection][local_port]" => "dest_port" "[attack_connection][local_ip]" => "dest_ip" "[attack_connection][remote_port]" => "src_port" "[attack_connection][remote_ip]" => "src_ip" } } } # Mailoney if [type] == "Mailoney" { grok { match => [ "message", "\A%{NAGIOSTIME}\[%{IPV4:src_ip}:%{INT:src_port:integer}] %{GREEDYDATA:smtp_input}" ] } mutate { add_field => { "dest_port" => "25" } } date { match => [ "nagios_epoch", "UNIX" ] remove_field => ["nagios_epoch"] } } # Rdpy if [type] == "Rdpy" { grok { match => { "message" => [ "\A%{TIMESTAMP_ISO8601:timestamp},domain:%{CISCO_REASON:domain},username:%{CISCO_REASON:username},password:%{CISCO_REASON:password},hostname:%{GREEDYDATA:hostname}", "\A%{TIMESTAMP_ISO8601:timestamp},Connection from %{IPV4:src_ip}:%{INT:src_port:integer}" ] } } date { match => [ "timestamp", "ISO8601" ] remove_field => ["timestamp"] } mutate { add_field => { "dest_port" => "3389" } } } # Syslog if [type] == "Syslog" { grok { match => { "message" => ["%{SYSLOGPAMSESSION}", "%{CRONLOG}", "%{SYSLOGLINE}"] } overwrite => "message" } date { match => [ "timestamp", "MMM d HH:mm:ss", "MMM dd HH:mm:ss" ] remove_field => ["timestamp"] } date { match => ["timestamp8601", "ISO8601"] remove_field => ["timestamp8601"] } grok { match => { "message" => "Connection closed by %{IP:src_ip}" } add_tag => [ "ssh_connection_closed" ] tag_on_failure => [] } grok { match => { "message" => "Received disconnect from %{IP:src_ip}" } add_tag => [ "ssh_connection_disconnect" ] tag_on_failure => [] } grok { match => { "message" => "Failed password for invalid user %{USERNAME:username} from %{IP:src_ip} port %{BASE10NUM:port} ssh2" } add_tag => [ "ssh_failed_password" ] tag_on_failure => [] } grok { match => { "message" => "Did not receive identification string from %{IP:src_ip}" } add_tag => [ "ssh_no_id" ] tag_on_failure => [] } grok { match => { "message" => "User %{USERNAME:username} from %{IP:src_ip} not allowed because not listed in AllowUsers" } add_tag => [ "ssh_user_not_allowed" ] tag_on_failure => [] } grok { match => { "message" => "authentication failure; logname=%{USERNAME:logname} uid=%{BASE10NUM:uid} euid=%{BASE10NUM:euid} tty=%{TTY:tty} ruser=%{USERNAME:ruser} rhost=(?:%{HOSTNAME:remote_host}|\s*) user=%{USERNAME:user}"} add_tag => [ "ssh_auth_failure" ] tag_on_failure => [] } grok { match => { "message" => "pam_unix\(sshd:auth\): authentication failure; logname= uid=0 euid=0 tty=%{NOTSPACE:tty} ruser= rhost=(?:%{HOSTNAME:remote_host}|\s*) user=%{USERNAME:user}"} add_tag => [ "ssh_auth_failure" ] tag_on_failure => [] } grok { match => { "message" => "Failed password for %{USERNAME:username} from %{IP:src_ip} port %{BASE10NUM:port} ssh2"} add_tag => [ "ssh_failed_password" ] tag_on_failure => [] } grok { match => { "message" => "Accepted password for %{USERNAME:username} from %{IP:src_ip} port %{BASE10NUM:port} ssh2"} add_tag => [ "ssh_accepted_password" ] tag_on_failure => [] } grok { match => { "message" => "Accepted publickey for %{USERNAME:username} from %{IP:src_ip} port %{BASE10NUM:port} ssh2"} add_tag => [ "ssh_accepted_pubkey" ] tag_on_failure => [] } grok { match => { "message" => "Accepted keyboard-interactive/pam for %{USERNAME:username} from %{IP:src_ip} port %{BASE10NUM:port} ssh2"} add_tag => [ "ssh_accepted_interactive" ] tag_on_failure => [] } } # NGINX if [type] == "NGINX" { date { match => [ "timestamp", "ISO8601" ] } } # Tanner if [type] == "Tanner" { date { match => [ "timestamp", "ISO8601" ] } mutate { rename => { "[peer][ip]" => "src_ip" "[peer][port]" => "src_port" } add_field => { "dest_port" => "80" } } } # Vnclowpot if [type] == "Vnclowpot" { grok { match => [ "message", "\A%{NOTSPACE}%{SPACE}%{TIME}%{SPACE}%{IPV4:src_ip}:%{INT:src_port}%{SPACE}%{NOTSPACE:vnc_handshake}" ] } date { match => [ "timestamp", "yyyy/MM/dd HH:mm:ss" ] remove_field => ["timestamp"] } mutate { add_field => { "dest_port" => "5900" } } } # Drop if parse fails if "_grokparsefailure" in [tags] { drop {} } # Add geo coordinates / ASN info / IP rep. if [src_ip] { geoip { cache_size => 10000 source => "src_ip" database => "/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/logstash-filter-geoip-5.0.3-java/vendor/GeoLite2-City.mmdb" } geoip { cache_size => 10000 source => "src_ip" database => "/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/logstash-filter-geoip-5.0.3-java/vendor/GeoLite2-ASN.mmdb" } translate { refresh_interval => 86400 field => "src_ip" destination => "ip_rep" dictionary_path => "/etc/listbot/iprep.yaml" } } # In some rare conditions dest_port, src_port is indexed as string, forcing integer for now if [dest_port] { mutate { convert => { "dest_port" => "integer" } } } if [src_port] { mutate { convert => { "src_port" => "integer" } } } # Add T-Pot hostname and external IP if [type] == "Ciscoasa" or [type] == "ConPot" or [type] == "Cowrie" or [type] == "Dionaea" or [type] == "ElasticPot" or [type] == "eMobility" or [type] == "Glastopf" or [type] == "Honeytrap" or [type] == "Heralding" or [type] == "Mailoney" or [type] == "Rdpy" or [type] == "Suricata" or [type] == "Tanner" or [type] == "Vnclowpot" { mutate { add_field => { "t-pot_ip_ext" => "${MY_EXTIP}" "t-pot_ip_int" => "${MY_INTIP}" "t-pot_hostname" => "${MY_HOSTNAME}" } } } } # Output section output { elasticsearch { hosts => ["elasticsearch:9200"] document_type => "doc" } if [type] == "Suricata" { file { file_mode => 0760 path => "/data/suricata/log/suricata_ews.log" } } # Debug output if [type] == "Tanner" { stdout { codec => rubydebug } } # Debug output #stdout { # codec => rubydebug #} }