小ネタが続いてますが、今回も小ネタです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
フリーのウイルス対策ソフトを利用しサーバ上でチェックすることも可能ですが、ここまで懸念する場合は本格的にツールの導入を考えた方が良いかもしれません。