こんにちは、cloudpack津村 です。

このはちゃんからお手紙着いた♪
【事例から学ぶ】ConoHaの仕様変更からのセキュリティの話: サーバーリスト画面

ConoHaの仕様変更からのセキュリティの話

注)これ以降の萌えはありません。
あんずちゃんが良い人はこちら→もう怖くない!ファイアーウォール(iptables)(このはとあんずのVPS勉強室)
【事例から学ぶ】ConoHaの仕様変更からのセキュリティの話: あんずさん
事は、2015年3月20日 18:28にGMOインターネット社よりユーザへ送信された、緊急メンテナンスのアナウンスになります。

日ごろはConoHaをご愛顧いただきありがとうございます。

ConoHaのサービスにおきまして、セキュリティ対策の一環として、
下記のとおり通信制御の設定を追加いたします。

変更日  :2015年03月20日(金) 19時00分頃
作業内容 :以下の作業を実施します。

      1.内部から外部、外部から内部の通信を制限。
        22番ポート/UDP
        80番ポート/UDP
       1900番ポート/UDP

      2.内部からのブロードキャスト通信を制限。

解釈として、

  1. インターネットからインスタンスへのinboundの強制的な制限。
  2. インスタンスからインターネットへのoutgointの強制的な制限。

上記のように解釈する事ができます。

しかし、2.に関しては情報が不足しており、インスタンスからインスタンスへのローカルネットワークにおいてもブロードキャストパケットが制限されたとも受け取る事が出来ます。(一般的にL2 over L3では、実装上の仕様により、ブロードキャストパケット及びマルチキャストパケットが制限されます。)

今回は1.についてピックアップし、 LinuxBoxの必要最小限のセキュリティについて考えてみたいと思います。

今回の緊急メンテナンスの目的と背景

今回、1.のメンテナンスでは、以下の3つのポートを上位ルータでブロックしています。

  • 22/udp
  • 80/udp
  • 1900/udp

このうち、22/udp及び80/udpについては、一般的には使用されていませんが、公式のウェルノンポートとして定義されており、Apache等のhttpd及びsshdがlistenしてもおかしくありません。(尚、手持ちの環境ではApache, sshd共にudpはLISTENしていませんでした。)

udpの場合、tcpのようにいちいちハンドシェークをする必要が無い為、攻撃者にとってはポートスキャンの次に有利な方法です。

1900/udpについては、別途解説します。

例えば、以下のようにLISTENしているポートを調べる事ができます。

また、併せて、これらのポートへの通信をOSレイヤーでコントロールする機能が、iptables(Linux)であり、ipfw(FreeBSD)であり、WindowsFireWall(Windows)です。

# netstat -anp
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address               Foreign Address             State       PID/Program name
tcp        0      0 0.0.0.0:22                  0.0.0.0:*                   LISTEN      779/sshd
tcp        0      0 0.0.0.0:3306                0.0.0.0:*                   LISTEN      2691/mysqld
tcp        0      0 172.31.xxx.xxx:22             xxx.xxx.xxx.xxx:49286         ESTABLISHED 2289/sshd
tcp        0      0 172.31.xxx.xxx:22             xxx.xxx.xxx.xxx:45029         ESTABLISHED 2341/sshd
tcp        0      0 :::80                       :::*                        LISTEN      2763/httpd
※一部省略、WebServerとして稼働中のCentOS機より取得。

UPnP対応機器を踏み台にされる事の停止(1900/udp)

1900/udpは、ウェルノンポートの1つで、「Microsoft SSDP Enables discovery of UPnP devices」とMicrosoftが定義・実装しています。
TCPやUDPにおけるポート番号の一覧(WikiPedia)

UPnPとは、簡単に言うと対応ルータへパケットを送信する事により、ポートフォワーディングを設定する事が可能な機能です。
UPnPに対応したネットワーク機器を踏み台としたSSDPリフレクター攻撃に対する注意喚起について(CyberPolice)

ここで言うUPnP対応ルータとは、ConoHaの上位ルータではなく、インスタンスに実装されているUPnPプロトコルの実装がターゲットとなります。これは、一般的には設定が施されたWindowsFirewallがターゲットとなります。

ConoHaの上位ルータは、インスタンスから観えるARPテーブルより、CiscoSystemsの機器がインストールされている事と推測します。
(http://www.coffer.com/mac_find/?string=00%3A00%3A0c)
Cisco IOSの場合、UPnPは実装されていません。

これらの背景を基に、Linuxのセキュリティ対策を施す。

先に幾つかOSレイヤーでのファイヤウォールを挙げましたが、今回はLinux上での実装であるiptablesを用いて、容易にファイヤーウォールを構築してみたいと思います。

セキュリティ対策のキホンのキホン

さて、たまにインスタンスやサーバを乗っ取られてしまい、Abuse(迷惑行為)レポートがホスティング業者から送付される場合があります。
この場合、既に後の祭りであり、おおよそ以下の事が進行した後です。

  1. SSHのパスワード認証が破られる。
  2. Perl・Python等標準インストールされやすいプログラミング言語を用いて、Botが設置される。
  3. Botがインターネット上に対し、22/tcp等へディクショナリーアタックを行う。

また、Apache等が動いていてrootに昇格できてしまった場合、サイトの改ざん・ログの改ざん等も攻撃者は可能です。

たとえば、パケットc…(ごふごふ)、桜h…(ごふごふ)、SAKURAインターネット社の場合、ユーザがOS再インストールの上、再度セキュリティ対策を施す事をAbuse対策の上でマストとしています。
また、クラウド忍j…(げふんげふん)、AWSも対策内容をリポートする事をマストとしています。

では、必要最小限の対策とはなにか。

  1. 必要ではないデーモンは動作させない。
  2. 必要ではないポートを公開しない。
  3. パスワード認証を廃止し、公開鍵認証を用いる。(例:パスワードログイン・BASIC認証→SSH公開鍵/秘密鍵・クライアントSSL証明書)
  4. OS・デーモン・アプリケーションをアップデートし、必要なセキュリティ対策を採る。

難しいように想えますが、基本は1つです。『とにかく攻撃者に攻撃を面倒にさせる』という事です。

先にも書きましたが、一般的なインターネット上でのUnixHostの乗っ取りには、「デフォルトのパスワード認証のままだった」「つい社内公開と思ってファイヤーウォールを設定していなかった」といった場合が多いのです。

また特に、3.(SSH公開鍵認証)については原理がわかりにくく、「めんどくさい」「よくわからない」という声が途絶えないのが現状ですが、ConoHaの他、AWSでも鍵認証を標準で採用しており、必要最小限の設定の一部がホスティングベンダーにより施されていることになります。

僕の場合、新規に環境を作る時には、下記をセットにして行います。

  1. OSのインストールはminimal(最小限)のみ。
  2. sudo権限を、普段使いする一般ユーザ(=自分)のみに。(※絶対にrootで運用しない!)
  3. sshd_configのテンプレート化、公開鍵の設置
  4. iptablesのテンプレート設置・カスタマイズ

本当は相互監視やログ管理も盛り込みたいのですが、そろそろ初期セットアップにAnsibleを使わないとキツいですw

iptablesの初期設定をしてみる。

CentOSの標準インストール状態を基準に、以下のコマンドをコピペで実行する事で、eth0(Internet)からのsshのみを受け付けるようになります。

# cat <<_EOF_ > /etc/sysconfig/iptables
*filter
:INPUT DROP [12:1740]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [113:15743]
 
-A INPUT -i lo -j ACCEPT
-A INPUT -i eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i eth0 -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
 
COMMIT
_EOF_
# /etc/init.d/iptables restart
# chkconfig iptables on

【解説】

:INPUT DROP [12:1740] // デフォルト動作:外部から入ってくるパケットを全て捨てる
:FORWARD DROP [0:0] // デフォルト動作:ルータ動作として転送するパケットを全て捨てる
:OUTPUT ACCEPT [113:15743] // デフォルト動作:外部へ出て行くパケットを全て許可する
 
-A INPUT -i lo -j ACCEPT // ループバックインターフェースの通信を全て許可
-A INPUT -i eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT // ハンドシェークが終わったtcpセッションを維持
-A INPUT -i eth0 -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT // SSHの新規セッションを許可

また、特定IPアドレスからのみアクセスを許可する場合は、たとえば22/tcpの部分を以下のように書き換えます。

-A INPUT -i eth0 -p tcp -m state --state NEW -m tcp --dport 22 -s 8.8.8.8/32 -j ACCEPT

-s」とは、ソースIPアドレス、つまりアクセス元のIPアドレスを示します。

8.8.8.8」はIPアドレス。/32の場合はIPアドレスそのものを、/30より短い場合はネットワークアドレスを示します。

/32」とは、サブネット、つまりIPアドレスの範囲を示します。ここでは割愛しますが、1個の場合は「/32」と記述します。

icmpプロトコル(Ping)を通す・通さないは正直難しいところですが、自分はトラブルシュートの時の足掛かりにするため、意図的に開けています。(今回は記述していません。)

その他、iptablesの設定をしていく事で、アタックを学習して動的にフィルタしたり、任意の設定のルータを構築する事も出来るようになります。

おわりに

お姉さま、昨今容易にLinuxホストを建てる輩が…(げふげふ)、
もとい、クラウドやVPSなどで容易にLinuxホストを手に入れられる時代になりましたが、残念ながらインターネットは自由の世界、言い換えれば無法地帯です。
Linuxホストをインターネットに晒せばすぐに攻撃されてしまいます。
今回のように、上位のファイヤーウォールで事前に対策してくれるのは、とても有り難い事です。

実は数年前、データセンタに新規のラックを借りて新規のグローバルIPをアサインして貰った事があるのですが(もちろん仕事ですよ!)、ファイヤーウォールが稼働した30分後にログを観ると、既に外部からの攻撃が始まっていました。(もちろん、最初から塞いでいましたが…)

TrendMicro DeepSecurity等の商用製品を使ってアプリケーションレイヤーで防御する事も可能ですが、それ以前に基本的なスキルとして、このエントリ程度のスキルは身につけて欲しいものです、はい。

p.s.
社内でロシエルさんファンと出会えました!ちょっと嬉しいです。

元記事はこちらです。
ConoHaの仕様変更からのセキュリティの話