[Linux] bashで超簡易的な改ざん検知を行いSlackに投げる

小ネタが続いてますが、今回も小ネタですw Webサイトの改ざん検知を手軽にパパッと行いたい場合、単純にcurlなどで取得したファイルをdiffで比較するだけでも実現できます。

というわけで以下がコード。ここでは最終的にSlackに通知しています。

#!/bin/bash

#
# 簡易的な改ざん検知からのSlack投稿
#

# 対象ページ
TARGET_URL='https://blog.katsubemakito.net/'

# 投稿先のSlack URL
WEB_HOOK_URL='https://hooks.slack.com/services/xxxxxxxx/xxxxxxxx/xxxxxxxxxxxxxxxxxx'

# 保存先ディレクトリ
STORE_DIR='/home/katsube/'


#-----------------------------------
# 最新のHTMLを取得
#-----------------------------------
cd $STORE_DIR
curl -s $TARGET_URL -o current.html

if [ $? -ne 0 ]; then
  echo "Can not get TARGET_URL: $TARGET_URL" >&2
  exit 1
fi

#-----------------------------------
# 前回のファイルと比較する
#-----------------------------------
if [ -f ./prev1.html ]; then
  result=`diff prev1.html current.html`

  if [ -z ${result} ]; then
    text="変化はありません"
  else
    text="<!channel> 変化がありました"
  fi


  # Slackに投げる
  curl -X POST --data-urlencode "payload={\"text\": \"${text}\"}" $WEB_HOOK_URL

  if [ $? -ne 0 ]; then
    echo "Can not post Slack, diff is ${result}" >&2
    exit 1
  fi
fi

#-----------------------------------
# 今回取得したファイルの名称変更
#-----------------------------------
# 1世代残す
if [ -f ./prev1.html ]; then
  mv prev1.html prev2.html
fi
mv current.html prev1.html

非常に簡易的な物ですので、実際に利用する場合は要件に応じてカスタマイズしてください。

準備

SlackのWebHookURLを取得

ちょっと前の記事ですが、以下を参照ください。 blog.katsubemakito.net

初回実行

実行権を設定し、初回の実行を行います。

$ chmod 0755 check.sh
$ ./check.sh

lsをしてprev1.htmlが作成されていれば成功です。

$ ls
check.sh prev1.html

cronに登録

毎朝5:00に自動起動するようcronにセットしておきます。crontab.txtに内容を記述したあとでcrontabコマンドに食べさせています。

$ cat crontab.txt 
0 5 * * * /home/katsube/check.sh

$ crontab < crontab.txt 

注意点

動的なページには適さない

ページを表示する度に情報が書き換わるようなページには向いていません。何度実行しても同じ情報を返さないようなページでご利用ください。

では毎回情報が変わるような場合にどうすれば良いか? 例えば以下のようにHTML上に動的に変化する箇所に印をつけ、改ざん検知側でHTMLをパースした際に印が付いている箇所は無視するといった処理を書いてあげるのが(実装側は)お手軽です。

<div class="not-static">
  ここは動的に情報が書き換わるよ
</div>

もしくはある程度のパターンが決まっていると行った場合には、正規表現などでパターンマッチを行う形になります。

監視対象のサーバで動かさない

改ざんがすでに実行されている場合、サーバが乗っ取られている可能性があります。また高負荷状態にあるとそもそもチェックスクリプトが正常に起動/動作しない可能性も考えられます。

必ずもう一つ別にサーバを建てるなどし、対象とは別のサーバ上で検知を行う必要があります。

対象ページから呼び出されているファイルの改ざん

例えば対象のページから参照しているJavaScriptや、ajaxなどで読み込んでいる外部のHTMLファイルが改ざんされる可能性もあります。

実際にはチェック対象が1ページであったとしても以下のように関連するファイルに対してもどうようにチェックを行う必要があります。

list=(
  'https://example.com/'
  'https://example.com/js/util.js'
  'https://example.com/css/style.css'
);

for url in ${list[@]}; do
  # ここでURLを1つずつチェックする
done

もしくはwgetなどでまるっと取得し、一気にチェックするやり方も良さそうですね。

画像ファイルに埋め込まれるケースも

以前にも別の記事で書きましたが、画像の中にマルウェアを仕込むことができる「ステガノグラフィー」という攻撃手法があります。 blog.kaspersky.co.jp

フリーのウイルス対策ソフトを利用しサーバ上でチェックすることも可能ですが、ここまで懸念する場合は本格的にツールの導入を考えた方が良いかもしれません。

参考ページ