こんとろーるしーこんとろーるぶい

週末にカチャカチャッターン!したことを貼り付けていくブログ

T-PotのELK環境へWOWHoneypotログ取り込み

前回の続きです。 graneed.hatenablog.com

T-Potは、各ハニーポットのログをELKスタックに取り込んでビジュアライズしています。前回、WOWHoneypotをT-Pot環境に組み込んだため、ログも同じようにT-PotのELKスタックに取り込みます。

また、WOWHoneypotはHTTPリクエスト全体のデータをBase64エンコードしてログ出力しているため、ついでに Logstashのフィルタ機能を使用してBase64デコードします。これにより、任意のHTTPリクエストヘッダーやPOSTされたデータも検索可能になるはずです。

1. Logstashの定義変更

Logstashの処理は、Inputs→Filters→Outputsの3つのステージに分かれています。 InputsおよびFiltersステージの定義を変更します。Outputsステージは変更しなくてよさそうです。

  1. Inputsステージに、WOWHoneypot(HTTP/HTTPS両方)のログのファイルパスを追加する。
  2. Filterステージに、WOWHoneypotのログをパースして項目分割する定義を追加する。
  3. Filterステージの、ホスト名とIP付与する処理の条件に、WOWHoneypotを追加する。

ポイントは2です。備忘録も兼ねて説明を記載します。
まず、追加する定義は以下の通りです。

if [type] == "WOWHoneypot" or [type] == "WOWHoneypotssl" {
  grok {
    match => [ "message", '\A\[%{TIMESTAMP_ISO8601:timestamp}\]%{SPACE}%{IP:src_ip}%{SPACE}%{IPORHOST:http.hostname}:%{NUMBER}%{SPACE}"%{WORD:http.http_method}%{SPACE}(?:%{URIPATHPARAM:http.url}|%{URI:http.url})%{SPACE}%{DATA:http.protocol}"%{SPACE}%{NUMBER:http.http_status}%{SPACE}%{WORD:mrrid}%{SPACE}%{GREEDYDATA:http.request_b64}' ]
    remove_field => ["port"]
  }
  date {
    match => [ "timestamp", "yyyy-MM-dd HH:mm:ssZ" ]
    remove_field => ["timestamp"]
  }
  ruby {
    init => "require 'base64'"
    code => "event.set('http.request', Base64.decode64(event.get('http.request_b64')))"
  }
}

grokでは、パターンを使用して、ログから項目を切り出すための定義を行います。

以下の公式ページを参考にしました。
Grok filter plugin | Logstash Reference [6.3] | Elastic

パターンの種類は以下のページを参考にしました。
logstash-patterns-core/grok-patterns at master · logstash-plugins/logstash-patterns-core · GitHub

定義したgrokは以下のページでテストできました。便利。
Test grok patterns

なお、remove_field => ["port"]しているのは、URIパターンを使用すると勝手に出現するport項目を削除するためです。

dateでは、該当ログのタイムスタンプを示すための定義を行います。例えば、Kibanaで日時を条件にして検索やソートする際に使用されるようです。

rubyでは、任意のrubyコードを実行できますが、今回はWOWHoneypotのログにあるHTTPリクエスト全体のデータをBase64デコードするために使用しました。

以下、作業手順です。

# ディレクトリ移動
[root@massshoemaker:~]# cd /opt/tpot/docker/elk/logstash/

# 比較用にバックアップ
[root@massshoemaker:/opt/tpot/docker/elk/logstash]# cp -p dist/logstash.conf dist/logstash.conf.org

# 定義変更。具体的な変更箇所はdiff結果を参照
[root@massshoemaker:/opt/tpot/docker/elk/logstash]# vi dist/logstash.conf
[root@massshoemaker:/opt/tpot/docker/elk/logstash]# diff -u dist/logstash.conf.org dist/logstash.conf
--- dist/logstash.conf.org      2018-06-10 01:30:22.786237401 +0900
+++ dist/logstash.conf  2018-06-16 02:33:11.528242645 +0900
@@ -93,6 +93,18 @@
     path => ["/data/vnclowpot/log/vnclowpot.log"]
     type => "Vnclowpot"
   }
+
+# WOWHoneypot
+  file {
+    path => ["/data/wowhoneypot/log/access_log"]
+    type => "WOWHoneypot"
+  }
+
+# WOWHoneypotssl
+  file {
+    path => ["/data/wowhoneypotssl/log/access_log"]
+    type => "WOWHoneypotssl"
+  }
 }

 # Filter Section
@@ -342,6 +354,22 @@
     }
   }

+# WOWHoneypot
+  if [type] == "WOWHoneypot" or [type] == "WOWHoneypotssl" {
+    grok {
+      match => [ "message", '\A\[%{TIMESTAMP_ISO8601:timestamp}\]%{SPACE}%{IP:src_ip}%{SPACE}%{IPORHOST:http.hostname}:%{NUMBER}%{SPACE}"%{WORD:http.http_method}%{SPACE}(?:%{URIPATHPARAM:http.url}|%{URI:http.url})%{SPACE}%{DATA:http.protocol}"%{SPACE}%{NUMBER:http.http_status}%{SPACE}%{WORD:mrrid}%{SPACE}%{GREEDYDATA:http.request_b64}' ]
+      remove_field => ["port"]
+    }
+    date {
+      match => [ "timestamp", "yyyy-MM-dd HH:mm:ssZ" ]
+      remove_field => ["timestamp"]
+    }
+    ruby {
+      init => "require 'base64'"
+      code => "event.set('http.request', Base64.decode64(event.get('http.request_b64')))"
+    }
+  }
+
 # Drop if parse fails
 if "_grokparsefailure" in [tags] { drop {} }

@@ -378,7 +406,7 @@
   }

 # Add T-Pot hostname and external IP
-  if [type] == "ConPot" or [type] == "Cowrie" or [type] == "Dionaea" or [type] == "ElasticPot" or [type] == "eMobility" or [type] == "Glastopf" or [type] == "Honeytrap" or [type] == "Mailoney" or [type] == "Rdpy" or [type] == "Suricata" or [type] == "Vnclowpot" {
+  if [type] == "ConPot" or [type] == "Cowrie" or [type] == "Dionaea" or [type] == "ElasticPot" or [type] == "eMobility" or [type] == "Glastopf" or [type] == "Honeytrap" or [type] == "Mailoney" or [type] == "Rdpy" or [type] == "Suricata" or [type] == "Vnclowpot" or [type] == "WOWHoneypot" or [type] == "WOWHoneypotssl" {
     mutate {
       add_field => {
         "t-pot_ip_ext" => "${MY_EXTIP}"

2. Dockerイメージ更新、再起動

定義変更を反映させるため、LogstashのDockerイメージを更新します。

# 停止
[root@massshoemaker:/opt/tpot/docker/elk/logstash]# systemctl stop tpot

# Dockerイメージ更新
[root@massshoemaker:/opt/tpot/docker/elk/logstash]# docker build -t dtagdevsec/logstash:1710 .
Sending build context to Docker daemon 30.72 kB
Step 1/6 : FROM alpine
 ---> 3fd9065eaf02
Step 2/6 : MAINTAINER MO
 ---> Using cache
 ---> 213ca7b23dda
Step 3/6 : ADD dist/ /root/dist/
 ---> 6d20cf1a3a93
Removing intermediate container 0add569df296
(snip)
Removing intermediate container 86dc8db88c7e
Successfully built 1b72b8280ec3

# 起動
[root@massshoemaker:/opt/tpot/docker/elk/logstash]# systemctl start tpot

3. 稼働確認

httpとhttpsでそれぞれアクセスできるか確認します。

[root@massshoemaker:~]# curl http://localhost/ -H "AAA: BBB" -d "aaa=bbb"
<html>
<head>
  <title>sample</title>
</head>
<body>
  <h1>sample page</h1>
</body>
</html>

[root@massshoemaker:~]# curl https://localhost/ -H "AAA: BBB" -d "aaa=bbb" -k
<html>
<head>
  <title>hello</title>
</head>
<body>
  <h1>hello</h1>
</body>
</html>

4. Kibana表示確認

Kibanaで、稼働確認した際のリクエストを見てみます。

f:id:graneed:20180616033758p:plain

http.request項目を見ると、HTTPリクエスト全体が平文で表示されており、HTTPヘッダーもHTTPボディも表示できていることを確認できました。

次回は、KibanaでWOWHoneypotのダッシュボードを作ります。

T-PotにWOWHoneypot組み込み+SSL対応

T-Potでは、HTTP(80番ポート)へのアクセスはglastopf、HTTPS(443番ポート)へのアクセスはDionaeaが受け付けています。 本記事では、glastopfとDionaeaの代わりに、WOWHoneypotにてHTTPおよびHTTPSを受け付ける手順を説明します。

WOWHoneypotは、ハニーポッターの森久氏が開発されているハニーポットです。ルール定義によって、攻撃者のリクエストに応じてレスポンスを変えることができる点が特徴かと思います。

github.com

変更後のT-Potのアーキテクチャ図は以下のようになります。
赤い点線枠がオリジナルのT-Potからの変更点です。 f:id:graneed:20180614230512p:plain

1. WOWHoneypotのSSL対応

1.1. WOWHoneypotにSSL対応機能追加

以下のコードを参考に、SSL対応できるようにWOWHoneypotを改修します。
gist.github.com

SSLを復号するサーバプロセスを用意して中継させる方法もあるかと思いますが、正直やり方がわからず、今回はWOWHoneypotを改修する方法で対応しました。

# githubからWOWHoneypotのマスターをコピー
[honey@massshoemaker:~]$ git clone https://github.com/morihisa/WOWHoneypot.git
Cloning into 'WOWHoneypot'...
remote: Counting objects: 146, done.
remote: Total 146 (delta 0), reused 0 (delta 0), pack-reused 146
Receiving objects: 100% (146/146), 54.11 KiB | 0 bytes/s, done.
Resolving deltas: 100% (70/70), done.
Checking connectivity... done.

# 比較用にバックアップ
[honey@massshoemaker:~]$ cd ./WOWHoneypot/
[honey@massshoemaker:~/WOWHoneypot]$ cp -p wowhoneypot.py wowhoneypot.py.org
[honey@massshoemaker:~/WOWHoneypot]$ cp -p config.txt config.txt.org

# wowhoneypot.pyをSSLを受け付けられるように改修。具体的な変更箇所はdiff結果を参照
[honey@massshoemaker:~/WOWHoneypot]$ vi wowhoneypot.py
[honey@massshoemaker:~/WOWHoneypot]$ diff -u wowhoneypot.py.org wowhoneypot.py
--- wowhoneypot.py.org  2018-06-14 00:55:53.575472978 +0900
+++ wowhoneypot.py      2018-06-13 22:01:00.000000000 +0900
@@ -17,6 +17,7 @@
 import socket
 import select
 import urllib.parse
+import ssl
 from http.server import HTTPServer, BaseHTTPRequestHandler
 from mrr_checker import parse_mrr
 from datetime import datetime, timedelta, timezone
@@ -43,6 +44,8 @@
 blacklist = {}
 separator = " "
 ipmasking = False
+ssl_enable = False
+certfilepath = ""

 class WOWHoneypotHTTPServer(HTTPServer):
     def server_bind(self):
@@ -326,6 +329,10 @@
                     ipmasking = True
                 else:
                     ipmasking = False
+            if line.startswith("certfilepath"):
+                global ssl_enable,certfilepath
+                ssl_enable = True
+                certfilepath = line.split('=')[1].strip()

         global accesslogfile
         accesslogfile = os.path.join(logpath, accesslogfile_name)
@@ -425,8 +432,11 @@
     logging_system("WOWHoneypot(version {0}) start. {1}:{2} at {3}".format(WOWHONEYPOT_VERSION, ip, port, get_time()), False, False)
     logging_system("Hunting: {0}".format(hunt_enable), False, False)
     logging_system("IP Masking: {0}".format(ipmasking), False, False)
+    logging_system("SSL Enable: {0}".format(ssl_enable), False, False)
     myServer = WOWHoneypotHTTPServer((ip, port), WOWHoneypotRequestHandler)
     myServer.timeout = timeout
+    if ssl_enable:
+        myServer.socket = ssl.wrap_socket(myServer.socket, certfile=certfilepath, server_side=True)
     try:
         myServer.serve_forever()
     except KeyboardInterrupt:


# ポート番号の変更およびSSL証明書ファイルパスの定義を追加。具体的な変更箇所はdiff結果を参照
[honey@massshoemaker:~/WOWHoneypot]$ vi config.txt
[honey@massshoemaker:~/WOWHoneypot]$ diff -u config.txt.org config.txt
--- config.txt.org      2018-06-14 00:55:53.575472978 +0900
+++ config.txt  2018-06-14 00:59:04.768945780 +0900
@@ -1,5 +1,5 @@
 # default port: 8080
-port=8080
+port=44333

 # default server header: Apache
 serverheader=Apache
@@ -31,3 +31,6 @@

 # for GDPR(True: replace source ip address with 0.0.0.0)
 ipmasking=False
+
+# SSL certfile path
+certfilepath=./server.pem

2. WOWHoneypotのDockerイメージ作成

HTTP用のWOWHoneypotのDockerイメージを作成します。
以下の記事を参考にさせて頂きました。
tk-secu.hateblo.jp

更に以下のDockerfileのベスト・プラクティスを参考にして変更しました。
Dockerfile を書くベスト・プラクティス — Docker-docs-ja 17.06.Beta ドキュメント

2.1. Dockerfile作成

まずはDockerfileを作成します。 ここから先はsudo su等でrootユーザに切り替えて作業します。

# ディレクトリ作成&移動
[root@massshoemaker:~]# mkdir /opt/tpot/docker/wowhoneypot
[root@massshoemaker:~]# cd /opt/tpot/docker/wowhoneypot

# Dockerfile作成
[root@massshoemaker:/opt/tpot/docker/wowhoneypot]# vi Dockerfile
[root@massshoemaker:/opt/tpot/docker/wowhoneypot]# cat Dockerfile
FROM ubuntu:latest

RUN apt-get update \
 && apt-get install -y git python3 \
 && apt-get clean \
 && rm -rf /var/lib/apt/lists/*
RUN git clone https://github.com/morihisa/WOWHoneypot.git /opt/wowhoneypot

WORKDIR /opt/wowhoneypot/
CMD ["python3", "wowhoneypot.py"]

2.2. Dockerイメージ作成

Dockerイメージを作成します。
他のT-PotのDockerイメージのリポジトリ命名規則に倣います。

[root@massshoemaker:/opt/tpot/docker/wowhoneypot]# docker build -t dtagdecsec/wowhoneypot .
Sending build context to Docker daemon 2.048 kB
Step 1/5 : FROM ubuntu:latest
 ---> 113a43faa138
Step 2/5 : RUN apt-get update  && apt-get install -y git python3  && apt-get clean  && rm -rf /var/lib/apt/lists/*
 ---> Running in e8e4c3845c45
Get:1 http://security.ubuntu.com/ubuntu bionic-security InRelease [83.2 kB]
(snip)
Step 3/5 : RUN git clone https://github.com/morihisa/WOWHoneypot.git /opt/wowhoneypot
 ---> Running in d9cfcd1a5cc3
Cloning into '/opt/wowhoneypot'...
 ---> a8b39658101f
Removing intermediate container d9cfcd1a5cc3
Step 4/5 : WORKDIR /opt/wowhoneypot/
 ---> 5b0416f9e345
Removing intermediate container 438ca050e69b
Step 5/5 : CMD python3 wowhoneypot.py
 ---> Running in 6b9cec675c0d
 ---> 0780f96e6831
Removing intermediate container 6b9cec675c0d
Successfully built 0780f96e6831

3. SSL対応版WOWHoneypotのDockerイメージ作成

HTTPS用のWOWHoneypotのDockerイメージを作成します。

3.1. Dockerfile作成

Dockerfileを作成します。2.1のDockerfileに処理を追加しています。

# ディレクトリ移動
[root@massshoemaker:~]# mkdir /opt/tpot/docker/wowhoneypotssl
[root@massshoemaker:~]# mkdir /opt/tpot/docker/wowhoneypotssl/dist
[root@massshoemaker:~]# cd /opt/tpot/docker/wowhoneypotssl

# Dockerfile作成
[root@massshoemaker:/opt/tpot/docker/wowhoneypotssl]# vi Dockerfile
[root@massshoemaker:/opt/tpot/docker/wowhoneypotssl]# cat Dockerfile
FROM ubuntu:latest

RUN apt-get update \
 && apt-get install -y git python3 \
 && apt-get clean \
 && rm -rf /var/lib/apt/lists/*
RUN git clone https://github.com/morihisa/WOWHoneypot.git /opt/wowhoneypot

ADD dist/ /root/dist/

RUN mv /root/dist/wowhoneypot.py /opt/wowhoneypot/ && \
    mv /root/dist/config.txt /opt/wowhoneypot/ && \
    mv /root/dist/server.pem /opt/wowhoneypot/

WORKDIR /opt/wowhoneypot/
CMD ["python3", "wowhoneypot.py"]

3.2. 改修ファイルの配置

1で改修したファイルをdistディレクトリに配備します。

[root@massshoemaker:/opt/tpot/docker/wowhoneypotssl]# cp -p /home/honey/WOWHoneypot/wowhoneypot.py ./dist/
[root@massshoemaker:/opt/tpot/docker/wowhoneypotssl]# cp -p /home/honey/WOWHoneypot/config.txt ./dist/

3.3. 証明書ファイル生成

オレオレ証明書ファイルをdistディレクトリに作成します。

[root@massshoemaker:/opt/tpot/docker/wowhoneypotssl]# openssl req -new -x509 -keyout ./dist/server.pem -out ./dist/server.pem -days 365 -nodes
Generating a 2048 bit RSA private key
........................................+++
....+++
writing new private key to './dist/server.pem'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:
Email Address []:

3.4. Dockerイメージ作成

Dockerイメージを作成します。
2.2.で作成したDockerイメージのキャッシュを使用しているため早いですね。

[root@massshoemaker:/opt/tpot/docker/wowhoneypotssl]# docker build -t dtagdecsec/wowhoneypotssl .
Sending build context to Docker daemon  25.6 kB
Step 1/7 : FROM ubuntu:latest
 ---> 113a43faa138
Step 2/7 : RUN apt-get update  && apt-get install -y git python3  && apt-get clean  && rm -rf /var/lib/apt/lists/*
 ---> Using cache
 ---> 396f3587dc6a
Step 3/7 : RUN git clone https://github.com/morihisa/WOWHoneypot.git /opt/wowhoneypot
 ---> Using cache
 ---> a8b39658101f
Step 4/7 : ADD dist/ /root/dist/
 ---> 2c3004b5ebdd
Removing intermediate container a2e384ac6264
Step 5/7 : RUN mv /root/dist/wowhoneypot.py /opt/wowhoneypot/ &&     mv /root/dist/config.txt /opt/wowhoneypot/ &&     mv /root/dist/server.pem /opt/wowhoneypot/
 ---> Running in 959f9568da84
 ---> 49f7b79ef9f8
Removing intermediate container 959f9568da84
Step 6/7 : WORKDIR /opt/wowhoneypot/
 ---> b42c6d1d1762
Removing intermediate container ae0b2e645c9f
Step 7/7 : CMD python3 wowhoneypot.py
 ---> Running in 5b8533982c55
 ---> acda12ef20c4
Removing intermediate container 5b8533982c55
Successfully built acda12ef20c4

4. ewsposterの設定変更

T-Potに同梱されているewsposterは、各ハニーポットのログデータをコミュニティに提出するツールです。 WOWHoneypotでHTTP(80番ポート)を受け付けるためglastopfを停止すると、ewsposterのglastopfログ収集処理がエラーになってしまいます。よって、ewsposterの設定を変更して、glastopfログ収集を停止します。 ewsposterごと停止することも可能ですが、T-Potの公式で、

We encourage you not to disable the data submission as it is the main purpose of the community approach - as you all know sharing is caring 😍

とのことで、glastopfログ収集のみ停止します。

4.1. 定義変更

ewsposterの定義ファイルを変更します。

# ディレクトリ移動
[root@massshoemaker:~]# cd /opt/tpot/docker/ews

# 比較用にバックアップ
[root@massshoemaker:/opt/tpot/docker/ews]# cp -p ./dist/ews.cfg ./dist/ews.cfg.org

# glastopfv3をfalseに変更。具体的な変更箇所はdiff結果を参照
[root@massshoemaker:/opt/tpot/docker/ews]# vi ./dist/ews.cfg
[root@massshoemaker:/opt/tpot/docker/ews]# diff -u ./dist/ews.cfg.org ./dist/ews.cfg
--- ./dist/ews.cfg.org  2018-06-10 01:30:22.786237401 +0900
+++ ./dist/ews.cfg      2018-06-15 12:31:30.288911865 +0900
@@ -30,7 +30,7 @@
 jsondir = /data/ews/json/

 [GLASTOPFV3]
-glastopfv3 = true
+glastopfv3 = false
 nodeid = glastopfv3-community-01
 sqlitedb = /data/glastopf/db/glastopf.db
 malwaredir = /data/glastopf/data/files/

4.2. Dockerイメージ更新

定義変更を反映させるため、ewsposterのDockerイメージを更新します。
更新前にはT-Potサービスを停止します。

# 停止
[root@massshoemaker:/opt/tpot/docker/ews]# systemctl stop tpot

# Dockerイメージ更新
[root@massshoemaker:/opt/tpot/docker/ews]# docker build -t dtagdevsec/ewsposter:1710 .
Sending build context to Docker daemon 10.75 kB
Step 1/5 : FROM alpine
latest: Pulling from library/alpine
ff3a5c916c92: Already exists
(snip)
Step 5/5 : CMD sleep 10 && /usr/bin/python /opt/ewsposter/ews.py -l 60
 ---> Running in e8bf148bda02
 ---> b006857e64e5
Removing intermediate container e8bf148bda02
Successfully built b006857e64e5

# 起動
[root@massshoemaker:/opt/tpot/docker/ews]# systemctl start tpot

5. T-PotへWOWHoneypot組み込み

ログ格納用のディレクトリを作成します。

[root@massshoemaker:~]# mkdir -p /data/wowhoneypot/log
[root@massshoemaker:~]# mkdir -p /data/wowhoneypotssl/log

T-PotのDocker Composeの設定ファイルを変更します。
変更内容は以下の通りです。

  • Dionaeaへの443ポートのマッピングを停止するため該当定義をコメントアウト
  • 80番ポートを使用しているglastopfを停止するため該当定義をコメントアウト
  • HTTP(80番ポート)用のWOWHoneypotコンテナ起動定義を追加
  • HTTPS(443番ポート)用のWOWHoneypotコンテナ起動定義を追加
# 比較用にバックアップ
[root@massshoemaker:~]# cd /opt/tpot/etc
[root@massshoemaker:/opt/tpot/etc]# cp -p tpot.yml tpot.yml.org

# 変更。変更内容は以下のdiff参照。
[root@massshoemaker:/opt/tpot/etc]# vi tpot.yml

# 比較
[root@massshoemaker:/opt/tpot/etc]# diff tpot.yml.org tpot.yml
15a16,17
>   wowhoneypot_local:
>   wowhoneypotssl_local:
53c55
<      - "443:443"
---
> #     - "443:443"
160,170c162,172
<   glastopf:
<     container_name: glastopf
<     restart: always
<     networks:
<      - glastopf_local
<     ports:
<      - "80:80"
<     image: "dtagdevsec/glastopf:1710"
<     volumes:
<      - /data/glastopf/db:/opt/glastopf/db
<      - /data/glastopf/log:/opt/glastopf/log
---
> #  glastopf:
> #    container_name: glastopf
> #    restart: always
> #    networks:
> #     - glastopf_local
> #    ports:
> #     - "80:80"
> #    image: "dtagdevsec/glastopf:1710"
> #    volumes:
> #     - /data/glastopf/db:/opt/glastopf/db
> #     - /data/glastopf/log:/opt/glastopf/log
284a287,310
>
> # WOWHoneypot
>   wowhoneypot:
>     container_name: wowhoneypot
>     restart: always
>     networks:
>      - wowhoneypot_local
>     ports:
>      - "80:8080"
>     image: "dtagdecsec/wowhoneypot"
>     volumes:
>       - /data/wowhoneypot/log:/opt/wowhoneypot/log
>
> # WOWHoneypot(SSL)
>   wowhoneypotssl:
>     container_name: wowhoneypotssl
>     restart: always
>     networks:
>      - wowhoneypotssl_local
>     ports:
>      - "443:44333"
>     image: "dtagdecsec/wowhoneypotssl"
>     volumes:
>       - /data/wowhoneypotssl/log:/opt/wowhoneypot/log

6. T-Pot再起動

変更結果を反映させるためにT-Potのサービスを再起動します。

# 停止
[root@massshoemaker:~]# systemctl stop tpot

# 起動
[root@massshoemaker:~]# systemctl start tpot

# 各コンテナの起動確認
[root@massshoemaker:~]# /opt/tpot/bin/dps.sh
========| System |========
    Date:  Thu Jun 14 21:01:20 JST 2018
  Uptime:  21:01:20 up 17:33,  4 users,  load average: 2.36, 0.91, 0.89
No sensors found!
Make sure you loaded all the kernel drivers you need.
Try sensors-detect to find out which these are.
CPU temp:

NAME                STATUS                               PORTS
cowrie              Up About a minute                    0.0.0.0:22->2222/tcp,
                                                         0.0.0.0:23->2223/tcp
dionaea             Up About a minute                    0.0.0.0:20-21->20-21/tcp,
                                                         0.0.0.0:42->42/tcp,
                                                         0.0.0.0:135->135/tcp,
                                                         0.0.0.0:445->445/tcp,
                                                         0.0.0.0:1433->1433/tcp,
                                                         0.0.0.0:1723->1723/tcp,
                                                         0.0.0.0:1883->1883/tcp,
                                                         0.0.0.0:3306->3306/tcp,
                                                         0.0.0.0:69->69/udp,
                                                         0.0.0.0:5060-5061->5060-5061/tcp,
                                                         0.0.0.0:27017->27017/tcp,
                                                         0.0.0.0:5060->5060/udp,
                                                         0.0.0.0:8081->80/tcp
elasticpot          Up About a minute                    0.0.0.0:9200->9200/tcp
elasticsearch       Up About a minute (healthy)          127.0.0.1:64298->9200/tcp
kibana              Up 36 seconds (healthy)              127.0.0.1:64296->5601/tcp
logstash            Up 36 seconds (health: starting)
head                Up 36 seconds (healthy)              127.0.0.1:64302->9100/tcp
ewsposter           Up 2 seconds
honeytrap           Up About a minute
mailoney            Up About a minute                    0.0.0.0:25->2525/tcp
netdata             Up 37 seconds (healthy)
rdpy                Up About a minute                    0.0.0.0:3389->3389/tcp
spiderfoot          Up About a minute (healthy)          127.0.0.1:64303->8080/tcp
ui-for-docker       Up About a minute                    127.0.0.1:64299->9000/tcp
suricata            Up About a minute
p0f                 Up About a minute
vnclowpot           Up About a minute                    0.0.0.0:5900->5900/tcp
wowhoneypot         Up About a minute                    0.0.0.0:443->44333/tcp
wowhoneypotssl      Up About a minute                    0.0.0.0:443->44333/tcp

7. 稼働確認

httpとhttpsでそれぞれアクセスできるか確認します。

[root@massshoemaker:~]# curl http://localhost/
<html>
<head>
  <title>sample</title>
</head>
<body>
  <h1>sample page</h1>
</body>
</html>

[root@massshoemaker:~]# curl https://localhost/ -k
<html>
<head>
  <title>hello</title>
</head>
<body>
  <h1>hello</h1>
</body>
</html>

一応、ブラウザでも表示確認します。
f:id:graneed:20180614020255p:plain

これにて組み込み完了です。
しばらくすると、/data/wowhoneypot/log/data/wowhoneypotssl/log配下のaccess_logファイルで攻撃を確認できると思います。

次回は、access_logファイルをT-Potと同じELK環境に取り込みます。

graneed.hatenablog.com

  • 変更履歴
    2018/6/15 4.ewsposterの設定変更の章を追加。

Amazon EC2(t2.medium)でT-Pot構築(その3)

その2の続きです。 graneed.hatenablog.com

前回まででインストールは完了しましたが、ギリギリの性能であるため、放っておくと問題が発生します。
ここではチューニング方法を記載します。

1. Swap領域の有効化

t2.mediumはメモリ4GBです。T-Potの要求スペックを満たしているものの、実は推奨スペックは8GBです。しばらく運用を続けて、elasticsearchにデータが積みあがってくるとメモリ不足になります。ちなみに、インストール直後がこの状態です。

[root@massshoemaker:/home/honey]# htop

f:id:graneed:20180610170236p:plain よって、Swap領域を作成してメモリ使用量の増加に備えます。

# Swap領域の作成
[root@massshoemaker:/home/honey]# mkdir /var/swap
[root@massshoemaker:/home/honey]# dd if=/dev/zero of=/var/swap/swap0 bs=1M count=2048
2048+0 records in
2048+0 records out
2147483648 bytes (2.1 GB, 2.0 GiB) copied, 27.3182 s, 78.6 MB/s
[root@massshoemaker:/home/honey]# chmod 600 /var/swap/swap0
[root@massshoemaker:/home/honey]# mkswap /var/swap/swap0
Setting up swapspace version 1, size = 2 GiB (2147479552 bytes)
no label, UUID=20e34a6e-7f6e-4cca-ab52-674475bcd45a

# Swap領域の有効化
[root@massshoemaker:/home/honey]# swapon /var/swap/swap0

# Swap領域の自動マウント
[root@massshoemaker:/home/honey]# echo '/var/swap/swap0 swap swap defaults 0 0' >> /etc/fstab

# Swap領域の確認
[root@massshoemaker:/home/honey]# swapon -s
Filename                                Type            Size    Used    Priority
/var/swap/swap0                         file            2097148 0       -1

これでSwap領域を2GB確保しました。

2. ログ保存期間短縮によるディスク使用量の節約

攻撃状況にもよりますが、AWSの無料利用枠の範囲内であるSSD 30GBで構築すると、1か月経たずにディスクがいっぱいになりました。 T-Potは、各ハニーポットのログを/data領域に保存しており、デフォルトは30日間保存しています。 その保存期間を変更して、ディスク使用量を節約します。

# 設定ファイルのバックアップ
[root@massshoemaker:/home/honey]# cp -p /opt/tpot/etc/logrotate/logrotate.conf /opt/tpot/etc/logrotate/logrotate.conf.org

# 設定ファイルの編集。rotateを30から15に変更。
[root@massshoemaker:/home/honey]# vi /opt/tpot/etc/logrotate/logrotate.conf

# 変更内容を確認
[root@massshoemaker:/home/honey]# diff -u /opt/tpot/etc/logrotate/logrotate.conf.org /opt/tpot/etc/logrotate/logrotate.conf
--- /opt/tpot/etc/logrotate/logrotate.conf.org  2018-06-10 01:30:22.830235993 +0900
+++ /opt/tpot/etc/logrotate/logrotate.conf      2018-06-10 12:24:06.095311754 +0900
@@ -33,6 +33,6 @@
        daily
         missingok
         notifempty
-       rotate 30
+       rotate 15
        compress
 }

これで保存期間を15日間に変更できました。

3. elasticsearch保存期間の短縮によるCPUバースト抑制

運用を始めて2か月を過ぎたあたりのある日、Kibanaでダッシュボードを表示すると、しばらく表示を待たされた結果、タイムアウトが発生してまともに使用できない状態になりました。

glances等のモニタリングツールで調べていると、stealが発生しており、各プロセスにCPUが割り当たっていない状態になっていることがわかりました。どうやら、elasticsearhのCPU使用率が徐々に高くなっており、AWSのCPUのバーストが発生しCPUクレジットを消費し尽くしていました。
t2.mediumの場合、CPU使用率が20%を超えると、CPUクレジットを消費していきます。

参考:CPU クレジットおよびベースラインパフォーマンス - Amazon Elastic Compute Cloud

elasticsearhはデータ量に比例してCPU使用率が高くなっていくようです。 elasticserchのデータは、デフォルトで90日間保存されています。その保存期間を変更して、CPU使用率を抑えます。

# 設定ファイルのバックアップ
[root@massshoemaker:/home/honey]# cp -p /opt/tpot/etc/curator/actions.yml /opt/tpot/etc/curator/actions.yml.org

# 設定ファイルの編集。unit_countを90から45に変更。
[root@massshoemaker:/home/honey]# vi /opt/tpot/etc/curator/actions.yml

# 変更内容を確認
[root@massshoemaker:/home/honey]# diff -u /opt/tpot/etc/curator/actions.yml.org /opt/tpot/etc/curator/actions.yml
--- /opt/tpot/etc/curator/actions.yml.org       2018-06-10 01:30:22.830235993 +0900
+++ /opt/tpot/etc/curator/actions.yml   2018-06-10 16:33:48.623398098 +0900
@@ -23,4 +23,4 @@
       direction: older
       timestring: '%Y.%m.%d'
       unit: days
-      unit_count: 90
+      unit_count: 45

これで保存期間を45日間に変更できました。

4. まとめ

保存期間を短縮すると、当然、観察する頻度を上げる必要がありますし、後から確認しづらくなります。
ハニーポットの運用目的や運用サイクルを鑑みて、パラメータを決定する必要があります。