2024/07/02
筆者が管理してるメールサーバーのユーザーがパスワード抜かれてPhishing Mailを転送しそうになってた。88通。
顛末
今回は「転送失敗」メールが88件、転送成功メールは0件で、他人に被害出さなくて済んだから良かったけどちょっと怖い思いをした。なお、転送に失敗していたのは、受信側の「携帯キャリア」のMail ServerがSMTPUTF8拡張をサポートしていなかったからだった。正直運良く転送されなかっただけで、一歩間違えたら大惨事(88通は決して少なくない)だった。
というわけで、せめてもの被害軽減策としてblacklistdを導入して、SMTPAUTHとIMAPへの接続を監視し、パスワードチェック攻撃を少しでもreduceしようとしてみた。パスワード破られたら、DKIMもDMARKもSPFも関係なく全部送れてしまうわけで…
なお、新しいパスワードは、強制的に16桁にしたから、しばらくは大丈夫。大丈夫だと思う。大丈であって欲しい。 (元のパスワード、6桁だったらしい。よく10年以上抜かれなかったなぁ…)
(Event Driven…)
根本的には、
/usr/libexec/blacklistd-helper
を用いて、pfに登録することで、攻撃を緩和するという考察をした。もちろん、blacklistdで対応できる範囲はそれほど大きくないが、それでも何もしないよりは大きく改善することが期待できる。
FreeBSDだと、portsを使ってPostfixをCompileして導入すればblacklistdに対応できる。Option設定画面でblacklistdをOnにしておくこと。
あとは、SMTP関連の設定だが、これはあまりにも重い話なので割愛。
blacklistdへの対応済みpostfixをblacklistdが動いていない状況で稼働させると、認証失敗時に/var/log/debug.log
に
Jun 9 15:11:24 mta postfix/smtpd[95847]: bl_init: connect failed for `/var/run/blacklistd.sock' (No such file or directory)
のようにErrorが記載される。(logファイルが /var/log/debug.log
になるかどうかはsyslogdの設定に依存する)
この状態で、blacklistd及びpfの設定を行う。
本記事においては、
というポリシーでpf(Firewall)を設定する。
当然、自分の環境に合わせてしっかり確認してください。違いはせいぜい、pfのfilter ruleくらいしかないでしょう。
と言うわけで、Configは以下の通り。
############################################################################## # pf.conf for mta ############################################################################## ##### Macros # Interfaces IFextn="xn1" ##### Tables table <rfc1918> const { 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, fc00::/7 } table <rfc6890> const { 192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24, 2001:0db8::/32 } table <rfc6598> const { 100.64.0.0/10 } # ISP CGN # need to create /etc/pf.rej (Empty file permitted) table <reject> persist file "/etc/pf.rej" ##### pf Options set block-policy drop ##### Normarization scrub in on $IFextn random-id fragment reassemble scrub on $IFextn random-id ##### Filtering ruleset set skip on lo0 pass all anchor "blacklistd/*" in on $IFextn
ポイントは、最後にあるanchor “blacklistd/*” in on $IFextn
である。
この行が意味するのは、
ということになる。
ここまで設定したら、/etc/rc.confに
# pf pf_enable="YES" pflog_enable="YES"
を記載し、service pf start && service pflog start
を実行する。
blacklistdの設定は、rc.confで設定するblacklistd_flags
に設定された引数と/etc/blacklistd.conf
によって行う。
このほかに、
というファイルが利用される。
以下、blacklistd.confのサンプル
# $FreeBSD$ # # Blacklist rule # adr/mask:port type proto owner name nfail disable [local] ssh stream * * * 3 24h smtp stream * * * 3 24h smtps stream * * * 3 24h submission stream * * * 3 24h imaps stream * * * 3 24h * * * * * 3 60 # WhiteLists # adr/mask:port type proto owner name nfail disable [remote] # Never block localhost 127.0.0.1/32 * * * * * * [::1]/128 * * * * * *
ここまで設定が終わったら、Blacklistdを起動する。
blacklistd_enable="YES" blacklistd_flags="-r"
service blacklistd start
を実行するservice blacklistd restart
すれば良いpfctl -sr
anchor "blacklistd/*" in on xn1 all
pfctl -a “*” -sr
anchor "blacklistd/*" in on xn1 all { anchor "25" all { block drop in quick proto tcp from <port25> to any port = smtp } anchor "587" all { block drop in quick proto tcp from <port587> to any port = submission } }
pfctl -a “blacklistd/25” -sr
とpfctl -a “blacklistd/587” -sr
# pfctl -a "blacklistd/25" -sr block drop in quick proto tcp from <port25> to any port = smtp # pfctl -a "blacklistd/587" -sr block drop in quick proto tcp from <port587> to any port = submission
# pfctl -a "blacklistd/25" -sT port25 # pfctl -a "blacklistd/587" -sT port587
pfctl -a “blacklistd/587” -t port25 -Ts
とpfctl -a “blacklistd/587” -t port587 -Ts
# pfctl -a "blacklistd/587" -t port25 -Ts 92.118.39.119 178.215.236.46 178.215.236.175 178.215.236.209 188.166.90.155 193.32.162.75 193.32.162.80 # pfctl -a "blacklistd/587" -t port587 -Ts 156.224.20.135
blacklistctl dump -a
# blacklistctl dump -a address/ma:port id nfail last access 185.208.158.235/32:25 2/3 2024/07/02 02:07:28 178.215.236.46/32:25 OK 3/3 2024/07/01 22:45:59 193.32.162.80/32:25 OK 3/3 2024/07/02 00:10:59 178.215.236.175/32:25 OK 3/3 2024/07/01 22:37:48 93.123.39.205/32:25 1/3 2024/07/02 03:04:55 193.32.162.75/32:25 OK 3/3 2024/07/01 22:30:08 178.215.236.209/32:25 OK 3/3 2024/07/01 23:04:36 188.166.90.155/32:25 OK 3/3 2024/07/02 01:22:29 156.224.20.135/32:587 OK 3/3 2024/07/02 02:30:43 92.118.39.119/32:25 OK 3/3 2024/07/01 23:15:31
blacklistctl dump -b
# blacklistctl dump -b address/ma:port id nfail last access 178.215.236.46/32:25 OK 3/3 2024/07/01 22:45:59 193.32.162.80/32:25 OK 3/3 2024/07/02 00:10:59 178.215.236.175/32:25 OK 3/3 2024/07/01 22:37:48 193.32.162.75/32:25 OK 3/3 2024/07/01 22:30:08 178.215.236.209/32:25 OK 3/3 2024/07/01 23:04:36 188.166.90.155/32:25 OK 3/3 2024/07/02 01:22:29 156.224.20.135/32:587 OK 3/3 2024/07/02 02:30:43 92.118.39.119/32:25 OK 3/3 2024/07/01 23:15:31
blacklistctl dump -r
# blacklistctl dump -r address/ma:port id nfail remaining time 185.208.158.235/32:25 2/3 22h43m15s 93.123.39.205/32:25 1/3 23h40m42s
/etc/blacklistd.conf
にsshのエントリーを作成(defaultで記述されているはず)/etc/rc.d
にsshd_flags=“-o UseBlackList=yes”
を追加/etc/ssh/sshd_config
に反映させても良いservice blacklistd restart
と service sshd restart
を実行これでsshdもblacklistd対応になる。
nameフィールドは、使用するパケットフィルタールールの名前である。
名前が “-” で始まる場合、デフォルトのルール名がその名前の前に付加される。
名前に “/” が含まれる場合、名前の残りの部分はルールで指定されたアドレスに適用されるマスクとして解釈され、1つのルール違反で設定されたプレフィックス全体のサブネットがブロックされる
nameに/29
と書くと、そのRuleでMatchしたSrcAddressに対して/29
のNetmaskを付加した上で、その範囲のアドレスがBlockされるという挙動になる。
このフィールドには 最後のアクセスからブロッキングルールが有効であるべき時間を指定する。デフォルトは “” で、これは「永久に」を意味する。disableのデフォルト単位は秒だが、異なる単位を示す接尾辞を指定することができる。例えば、“m” は分、“h” は時間、“d” は日を表す。
source codeを読む限り、このフィールドに、例えば1d12h30m59s
のように指定できるように見える。こう指定した場合、一度drop listに入ったら、1日12時間30分59秒の間Blacklistに登録される(すなわち、pfのdropテーブルに載り、filterout される)ように見える。
また、Source codeとdebug logを見る限り、Disable / Durationフィールドの値は以下のような動作に利用されるように見える。
したがって、disable/Durationの値は慎重に検討する必要がある。これを短くとるか長く取るかで、利便性と件出力のバランスを取る必要がある。
現在 blocklistctl には登録されているアドレスを削除する機能が無い。(というよりdumpしかできない)
したがって、pfctl -a * -t port25 -T delete [Address]
を実行して、一時的にTableから削除する必要がある。
なお拒否期限までの時間が残ってる間は blacklistd を再起動する度にpfに登録される
blacklistdは、/var/db/blacklistd.db
にデータを記録している。このdbに記載されたデータをblacklistd起動時に読み出してpfに登録している。
このblacklistd.dbはBerklay DBファイルで、blacklistctl dump -a
でDataをdump できる。
Blacklistdは、sourcecodeを見る限り、DBファイルに対してLockなどの操作を行っていないように見える。 したがって、これを見る限りでは、このDBのデータファイルを複数台のマシンで共有すると、Dataを破損する可能性があると考えられる。
本文中におまけはあるんだけど、こっちにやられた時の顛末とかのおまけを記載します。
全てはmaillogからの解析。
という挙動だった
今回は、送付先のメールサーバーがSMTPUTF8受け付けなかったからエラーメールになって帰ってきて、だから気づけたけど、はっきり言って、これは運がよかっただけ。 転送失敗してなかったら気づかなかったまであるわけで。
問題は、
というあたりにある。
結局、DKIMやDMARC、SPFは、いわゆるOpenRelayに近いメールへの対策としてはそれなりに効果はあるんだろうけど、パスワード抜かれたら終わりというのは変わらない。まぁ、パスワード認証を利用する限りそうなるのは自明なんだけど…。SMTP捨てられればいいんだけど、なかなかそういうわけにも行かないし。
パスワード認証の代わりに個人証明書を使うといのはないわけじゃない。設定や利用に関しては、まぁ、面倒なだけでやれなくはないし。 ただ、この手を採用した場合の問題は、「個人証明書の発行」にある。 今時オレオレ証明書ってのは面倒が過ぎる(client側の設定も鯖側の設定も面倒)だし、自分がsubsidiary CAになるのは大変が過ぎるし… でもまぁ、いうて、弱いパスワードが何よりも悪いのは事実だな。こいつをまず何とかするか。
今回blacklistdを導入するにあたって、pfで対応するサンプルが非常に少なかった。なので、結局source codeまで見ないとわからないところがたくさんあった。
FreeBSDにおけるFirewall実装を選ぶなら、スピードの点でipfwが一番良い。特にCiscoとかの昔ながらRouterでFirewall設定したことがある人はipfwの方がわかりやすいとおもう。ただ、筆者は今時のPacket Filter Firewallでは設定はある程度抽象化されていて欲しい。その意味で、OpenBSD由来のpfは非常に気に入っている。
ただ、FreeBSDに移植されているpfは、OpenBSDのpfよりも常に古いのがやはり辛い。NAT64はOpenBSDならpfでできるんだけど、FreeBSDだとipfwでやるしか今のところないし。
うーん、やっぱり色々難しいなぁ…