1. 程式人生 > 實用技巧 >ElastAlert監控日誌告警Web攻擊行為---tomcat和nginx日誌json格式

ElastAlert監控日誌告警Web攻擊行為---tomcat和nginx日誌json格式

一、ELK安裝

1.2 elk配置

logstash自定義配置檔案,取名為filebeat_log.conf :

input {
  beats {
    port => 5044
    client_inactivity_timeout => 90
    codec => json
  }

}

filter {
  date {
    match => [ "timestamp", "dd/MMM/yyyy:HH:mm:ss Z" ]
    target => ["datetime"]
  }
  geoip {
    source => "remote_addr"
  }

  mutate {
    remove_field => ["tags", "beat"]
  }
}

output {
  stdout {
   codec => rubydebug
  }

  elasticsearch {
    hosts => "localhost:9200"
    index => "logstash-%{+YYYY.MM.dd}"
  }
}

1.3 啟動方法

logstash啟動

進入/usr/share/logstash/bin:

nohup ./logstash -f filebeat_log.conf> /dev/null 2>&1 &

二、使用filebeat進行分散式收集

下面以tomcat為例子,分享我的配置檔案filebeat.yml(nginx的話,修改paths的路徑):

filebeat.prospectors:
- type: log
  enabled: true
  paths:
    - /home/qy/apache-tomcat-9.0.1/logs/localhost_access_log.*.txt
  document_type: tomcat-log
  scan_frequency: 15s
  ignore_older: 20m
  close_inactive: 12m
  clean_inactive: 30m
  close_removed: true
  clean_removed: true
  ....
  #----------------------------- Logstash output --------------------------------

output.logstash:
  hosts: ["188.88.88.88:5044"]

直接解壓下載的tar包,進入目錄修改配置檔案。然後啟動filebeat:nohup ./filebeat -e -c filebeat.yml >/dev/null 2>&1 &

三、日誌格式轉json

為方便kibana分析和elastalert的取值,日誌的格式要為json格式,上述的logstash配置檔案已適配json格式。

公司的應用伺服器中均為nginx和tomcat,故本文只介紹tomcat及nginx的json格式配置方法,其他伺服器配置方法請自行搜尋。

3.1 tomcat的json格式配置

開啟config/server.xml,在最後的位置修改log的輸出配置為:

<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log" suffix=".txt" pattern="{&quot;time&quot;:&quot;%t&quot;,&quot;remote_addr&quot;:&quot;%h&quot;,&quot;remote_user&quot;:&quot;%l&quot;,&quot;request&quot;:&quot;%r&quot;,&quot;status&quot;:&quot;%s&quot;,&quot;body_bytes_sent&quot;:&quot;%b&quot;,&quot;http_referer&quot;:&quot;%{Referer}i&quot;,&quot;http_user_agent&quot;:&quot;%{User-Agent}i&quot;,&quot;http_x_forwarded_for&quot;:&quot; %{X-Forwarded-For}i&quot;,&quot;request_time&quot;:&quot;%T&quot;,&quot;host&quot;:&quot;%v&quot;,&quot;port&quot;:&quot;%p&quot;}"/>

然後重啟tomcat,即生效。

3.2 nginx的json格式配置

進入`/etc/nginx`開啟`nginx.conf`,加入如下配置:
http {

    ##
    # Basic Settings
    ##

    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;
    # server_tokens off;

     log_format logstash_json '{"time": "$time_local", '
        '"remote_addr": "$remote_addr", '
        '"remote_user": "$remote_user", '
        '"request": "$request", '
        '"status": "$status", '
        '"body_bytes_sent": "$body_bytes_sent", '
        '"http_referer": "$http_referer", '
        '"http_user_agent": "$http_user_agent", '
        '"http_x_forwarded_for": "$http_x_forwarded_for", '
        '"request_time": "$request_time", '
        '"request_length": "$request_length", '
        '"host": "$http_host"}';
}

最後nginx -s reload即可

四、使用elastalert進行告警

ElastAlert使用python編寫,具有容易上手、文件全等特點,雖然這個工具擁有如此多的優點,在搭建過程還是遇到了很多很多的未知錯誤,主要原因是網上的資料大多是針對es5.x以前的版本而沒什麼現成的資料可供參考。

4.1 安裝elastalert

  git clone https://github.com/Yelp/elastalert.git 
  cd elastalert
  python setup.py install            //可能需要sudo
  Pip install -r requirements.txt    //可能需要sudo
  cp config.yaml.example config.yaml

具體的功能本文就不一一介紹了,請自行前往官方文件瞭解

4.2 建立索引

安裝完成後會系統中會自帶三個命令:

elastalert-create-indexelastalert-rule-from-kibanaelastalert-test-rule

使用elastalert-create-index,根據提示設定es後按回車預設即可。
​ 配置完索引及配置檔案後,可以使用elastalert-test-rule進行測試。這裡有個bug,如果出現TransportError(400, u'search_phase_execution_exception', u'No mapping found for [alert_time] in order to sort on')之類的錯誤,在確認沒有其他的問題時,可以先刪除索引curl -XDELETE http://localhost:9200/*,再使用elastalert-create-index重新生成索引。

4.3 配置config.yaml

  rules_folder: example_rules

  # How often ElastAlert will query Elasticsearch
  # The unit can be anything from weeks to seconds
  run_every:
    seconds: 3   #每三秒向es請求資料
  # ElastAlert will buffer results from the most recent
  # period of time, in case some log sources are not in real time
  buffer_time:
    minutes: 15  
    #日誌會延遲進入es,這裡是配置query的向前的時間範圍,這是15分鐘,即查詢 time[now-15m, now]

  # The Elasticsearch hostname for metadata writeback
  # Note that every rule can have its own Elasticsearch host
  es_host: 188.88.88.88

  # The Elasticsearch port
  es_port: 9200

  # Optional URL prefix for Elasticsearch
  #es_url_prefix: elasticsearch

  # Connect with TLS to Elasticsearch
  #use_ssl: True

  # Verify TLS certificates
  #verify_certs: True

  # GET request with body is the default option for Elasticsearch.
  # If it fails for some reason, you can pass 'GET', 'POST' or 'source'.
  # See http://elasticsearch-py.readthedocs.io/en/master/connection.html?highlight=send_get_body_as#transport
  # for details
  #es_send_get_body_as: GET

  # Option basic-auth username and password for Elasticsearch
  #es_username: someusername
  #es_password: somepassword

  # The index on es_host which is used for metadata storage
  # This can be a unmapped index, but it is recommended that you run
  # elastalert-create-index to set a mapping
  writeback_index: elastalert_status

  # If an alert fails for some reason, ElastAlert will retry
  # sending the alert until this time period has elapsed
  alert_time_limit:
    days: 1

以上各欄位的解釋:

Rules_folder:用來載入下一階段rule的設定,預設是example_rules

Run_every:用來設定定時向elasticsearch傳送請求

Buffer_time:用來設定請求裡時間欄位的範圍,預設是45分鐘

Es_host:elasticsearch的host地址

Es_port:elasticsearch 對應的埠號

Use_ssl:可選的,選擇是否用SSL連線es,true或者false

Verify_certs:可選的,是否驗證TLS證書,設定為true或者false,預設為- true

Es_username:es認證的username

Es_password:es認證的password

Es_url_prefix:可選的,es的url字首(我的理解是https或者http)

Es_send_get_body_as:可選的,查詢es的方式,預設的是GET

Writeback_index:elastalert產生的日誌在elasticsearch中的建立的索引

Alert_time_limit:失敗重試的時間限制

4.4 告警配置介紹

example_rules目錄中新建yaml配置檔案 webattack_frequency.yaml,下面分開介紹這個配置檔案的內容(下個小節將分享我的配置檔案,此小節僅解釋其中的必要設定項):

1、告警規則

ElastAlert支援11種告警規則,本文不一一介紹了,為響應web攻擊行為,本文選用的告警規則是frequency

name: web attack

# (Required)
# Type of alert.
# the frequency rule type alerts when num_events events occur with timeframe time
type: frequency

# (Required, frequency specific)
# Alert when this many documents matching the query occur within a timeframe
num_events: 10

# (Required, frequency specific)
# num_events must occur within this amount of time to trigger an alert
timeframe:
  minutes: 1
  
# (Required)
# Index to search, wildcard supported
index: logstash-*      #對應logstash的配置檔案中output的elasticsearch index字首

filter:
- query_string:
# sql insert  xss detect
        query: "request: select.+(from|limit) OR request: union(.*?)select OR request: into.+(dump|out)file "

上述配置檔案的意圖即是:在一分鐘內將匹配query裡面的sql注入規則,若匹配次數達到10次,即進行報警。

2、使用郵箱進行告警

ElastAlert提供了 10 多種通知的型別,本文選用的是郵箱告警,還有微信告警釘釘告警,若有需要,請自行配置。

smtp_host: smtp.qiye.163.com
smtp_port: 25

smtp_auth_file: /Users/qy/Downloads/work/elastalert/example_rules/smtp_auth_file.yaml
#回覆給那個郵箱
email_reply_to: [email protected]
#從哪個郵箱傳送
from_addr: [email protected]



# (Required)
# The alert is use when a match is found
alert:
- "email"

# (required, email specific)
# a list of email addresses to send alerts to
email:
- "[email protected]"

alert_subject: "web attack may be by {} at @{}"
alert_subject_args:
  - remote_addr
  - time

alert_text_type: alert_text_only

alert_text: |
  你好,伺服器({})可能正在受到web攻擊,請採取手段阻止!!!!
  ### 截止發郵件前匹配到的請求數:{}
  > 發生時間: {}
  > timestamp:{}
  > attacker's ip: {}
  > request: {}
  > status:{}
  > UA頭:{}
  >>> 參考來源:{}

alert_text_args:
  - host
  - num_hits
  - time
  - "@timestamp"
  - remote_addr
  - request
  - status
  - http_user_agent
  - source

smtp_auth_file.yaml的配置內容會在下個小節給出,在這個配置中,我自定義了 alert 的內容,更為精確地突出了攻擊者ip、受攻擊的伺服器、攻擊事件等資訊。

3、減少重複告警的頻率

在實際的使用中,若使用上述的配置,受到攻擊的時候郵箱將不斷地收到郵件,而這些郵件都對應著同一個攻擊例項,根本沒必要重複收取,於是,我使用瞭如下的配置:

   # 用來區分報警,跟 realert 配合使用,在這裡意味著,
   # 5 分鐘內如果有重複報警,那麼當 name 不同時,會當做不同的報警處理,可以是陣列
   query_key:
     - name

   # 5 分鐘內相同的報警不會重複傳送
   realert:
     minutes: 5

   # 指數級擴大 realert 時間,中間如果有報警,
   # 則按照 5 -> 10 -> 20 -> 40 -> 60 不斷增大報警時間到制定的最大時間,
   # 如果之後報警減少,則會慢慢恢復原始 realert 時間
   exponential_realert:
     hours: 1

在本人實際測試的攻擊場景中,發現使用了exponential_realert後,會錯過很多告警(這些告警並不是同一個攻擊例項),暫時不確定原因,還請讀者們自行確定是否開啟該設定。

4.5webattack_frequency.yaml及smtp_auth_file.yaml配置檔案內容

上述的4.4小節中對每個配置都作了簡單的介紹,這裡就直接放出web攻擊預警的配置檔案供各位讀者參考。

webattack_frequency.yaml:
# Alert when the rate of events exceeds a threshold

# (Optional)
# Elasticsearch host
#es_host: 188.88.88.88

# (Optional)
# Elasticsearch port
#es_port: 9200

# (OptionaL) Connect with SSL to Elasticsearch
#use_ssl: True

# (Optional) basic-auth username and password for Elasticsearch
#es_username: someusername
#es_password: somepassword

# (Required)
# Rule name, must be unique
name: web attack

realert:
  minutes: 5

# (Required)
# Type of alert.
# the frequency rule type alerts when num_events events occur with timeframe time
type: frequency

# (Required)
# Index to search, wildcard supported
index: logstash-*

# (Required, frequency specific)
# Alert when this many documents matching the query occur within a timeframe
num_events: 10

# (Required, frequency specific)
# num_events must occur within this amount of time to trigger an alert
timeframe:
  #hours: 4
  minutes: 1

# (Required)
# A list of Elasticsearch filters used for find events
# These filters are joined with AND and nested in a filtered query
# For more info: http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl.html
#filter:
#- term:
#    some_field: "some_value"

filter:
- query_string:
# sql insert  xss detect
        query: "request: select.+(from|limit) OR request: union(.*?)select OR request: into.+(dump|out)file OR

        request: (base64_decode|sleep|benchmark|and.+1=1|and.+1=2|or%20|exec|information_schema|where%20|union%20|%2ctable_name%20|cmdshell|table_schema) OR

        request: (iframe|script|body|img|layer|div|meta|style|base|object|input|onmouseover|onerror|onload) OR

        request: .+etc.+passwd OR http_user_agent:(HTTrack|harvest|audit|dirbuster|pangolin|nmap|sqln|-scan|hydra|Parser|libwww|BBBike|sqlmap|w3af|owasp|Nikto|fimap|havij|PycURL|zmeu|BabyKrokodil|netsparker|httperf|bench) OR

        status: (400|404|500|501)

        NOT (request:_health.html OR remote_addr:222.222.222.222  )
        "


smtp_host: smtp.qiye.163.com
smtp_port: 25

smtp_auth_file: /Users/qy/Downloads/work/elastalert/example_rules/smtp_auth_file.yaml
#回覆給那個郵箱
email_reply_to: [email protected]
#從哪個郵箱傳送
from_addr: [email protected]



# (Required)
# The alert is use when a match is found
alert:
- "email"

# (required, email specific)
# a list of email addresses to send alerts to
email:
- "[email protected]"

alert_subject: "web attack may be by {} at @{}"
alert_subject_args:
  - remote_addr
  - time

alert_text_type: alert_text_only

alert_text: |
  你好,伺服器({})可能正在受到web攻擊,請採取手段阻止!!!!
  ### 截止發郵件前匹配到的請求數:{}
  > 發生時間: {}
  > timestamp:{}
  > attacker's ip: {}
  > request: {}
  > status:{}
  > UA頭:{}
  >>> 參考來源:{}

alert_text_args:
  - host
  - num_hits
  - time
  - "@timestamp"
  - remote_addr
  - request
  - status
  - http_user_agent
  - source
smtp_auth_file.yaml:
user: [email protected]
password: password

4.6 執行elastalert

在成功配置完ElastAlert後將生成三個配置檔案:

config.yaml、webattack_frequency.yaml、smtp_auth_file.yaml
  • 啟動elastalert服務,監聽elasticsearch:
nohup python -m elastalert.elastalert --verbose --rule webattack_frequency.yaml >/dev/null 2>&1 &
  • 為實現守護程序的作用,可以配合supervisor進行使用,本文不再闡述。

4.7 執行效果:

當匹配到自定義攻擊規則的時候,ElastAlert將會以郵件方式傳送告警資訊:

web attack may be by 104.38.13.21 at @[13/Jan/2018:16:06:58 +0800]
xxx 發給 shystartree   
你好,伺服器(199.222.36.31)可能正在受到web攻擊,請採取手段阻止!!!!
### 截止發郵件前匹配到的請求數:20
> 發生時間: [13/Jan/2018:16:06:58 +0800]
> timestamp:2018-01-13T08:07:04.930Z
> attacker's ip: 184.233.9.121
> request: GET /dbadmin/scripts/setup.php HTTP/1.0
> status:200
> UA頭:ZmEu
>>> 參考來源:/log/localhost_access_log.2018-01-13.txt