memcachedの開放ポート(11211/tcp, 11211/udp)をサクっと確認する
昨日(2018/02/27)に、JPCERTからmemcached のアクセス制御に関する注意喚起が出ていました。
ということでmemcachedのポート(11211/tcp, 11211/udp)が開放されていないかの確認方法についてメモしておきます。
memcached開放により起きる問題
はじめに、memcachedのポートを外部から接続可能にしてしまうと何が問題か整理しましょう。
内部情報の漏洩
1つはすぐに思い付くことですが、内部情報の漏洩です。memcachedは認証の無いプロトコルであるため(正確にはあるけど、誰も(?)使ってない)、外部から接続できれば即キャッシュ上の値を取得することができます。
たとえばphp.iniで以下のように設定していれば、
session.save_handler = memcached session.save_path = "localhost:11211”
セッション情報を外部から取得可能となってしまいます。その他、キャッシュに乗っている値を根こそぎ取得できてしまいます。
UDP Reflection Attackの踏み台となる
2018年2月現在は、情報漏洩よりもこちらの被害が問題視されています。
UDPはコネクションレスであり送信元偽装が容易なため、リクエストに対してレスポンスが大きいプロトコルは、偽装した送信元(=攻撃先)への「跳ね返り」によりDDoS攻撃に利用できます。
たとえば数年前には、ntpのmonlist機能でこのようなDDoSが指摘され、攻撃者に利用されてしまいました。(参考:ntpd の monlist 機能を使った DDoS 攻撃に関する注意喚起)
memcachedで「リクエストに対してレスポンスが大きい」ことですぐ思いつくのは、状態表示をおこなうstatsコマンドでしょう。
# printf "stats\r\n" | nc 192.168.2.67 11211 STAT pid 10330 STAT uptime 5559 STAT time 1519825560 STAT version 1.4.15 STAT libevent 2.0.21-stable STAT pointer_size 64 STAT rusage_user 0.055732 STAT rusage_system 0.057469 STAT curr_connections 10 STAT total_connections 37 STAT connection_structures 11 STAT reserved_fds 20 STAT cmd_get 11 STAT cmd_set 6 ...(略)... END
上記の例のように、statsというコマンドだけで大量のレスポンスが得られます。なおmemcachedはCRLFを改行とみなすので、この例は律儀にprintfで"\r\n"を付けてます。
さらに、(詳しい操作は念のため伏せますが)外部からmemcachedが操作可能ならば、適当なkeyにとても長い値をsetして、送信元を偽装したUDP通信でgetするだけで、大きいレスポンスを偽装先へ送りつけることができます。このため memcachedのUDPポートを外部に開放していると、UDP Reflection AttackによるDDoSへ踏み台として荷担してしまうことになります。
memchacedでUDPをoffにするには、「-U 0」というオプションを付加します。CentOS 7のパッケージならば、以下のように /etc/sysconfig/memcached ファイルの「OPTIONS」に記述します。
PORT="11211" USER="memcached" MAXCONN="1024" CACHESIZE="64" OPTIONS="-U 0"
この「-U」は本来はUDPの待ち受けポートを指定するオプションなのですが、manに記載の通り、ゼロを指定するとUDPのLISTEN自体をOFFにします。
ポート開放の確認
memcachedは、TCP・UDPともに11211ポートがデフォルトで利用されます。通常はTCPしか使われないため、UDPは明示的に意識しない限り使うことはないでしょう。
しかしmemcachedデフォルトではTCPだけでなくUDPも開放されるため(memcached 1.5.6からはUDPはデフォルトでは無効らしい)、特にUDPのフィルタは見落としがちです。
ここからは、外部へ本当にポート開放していないかを確認する方法を記述します。なおこちらに書いた手法はポートスキャンに当たるため、必ず自らが管理するホストのみに行い、第三者のホスト・ネットワークをスキャンすることの無いようにしてください。
nmapを利用
ポート確認ならば、まず思いつくのはnmapでしょう。
TCPポートがopenしているか確認するだけならば、SYNスキャン(-sS)するだけで十分です。出力は-oNオプションでテキストに落としておくと良いでしょう。ここでは192.168.2.0/24をスキャンし、オプションには-nを付けて逆引きしないようにしています。
# nmap -n -sS -p11211 -oN output.txt 192.168.2.0/24
出力にはclosedやfilteredのものも混じるので、openを検索します。
...(略)... Nmap scan report for 192.168.2.65 Host is up (0.000091s latency). PORT STATE SERVICE 11211/tcp filtered memcache MAC Address: E0:3F:49:XX:XX:XX (Asustek Computer) Nmap scan report for 192.168.2.67 Host is up (0.00014s latency). PORT STATE SERVICE 11211/tcp open memcache MAC Address: 00:0C:29:CC:C7:B0 (VMware) Nmap scan report for 192.168.2.99 Host is up (0.00022s latency). ...(略)...
TCPを1ポートだけのポートスキャンならば、相当広いネットワーク帯であっても数秒〜数分で終わるでしょう。
さて11211/tcpの開放チェックは簡単ですが、UDPとなると少々やっかいです。周知の通り、UDPのポートスキャンは往々にして不正確で、nmapのUDPスキャンオプションである-sUしただけでは次のように「open|filtered」となり見逃してしまいます。
# nmap -n -sU -p11211 192.168.2.67 Starting Nmap 7.60 ( https://nmap.org ) at 2018-02-28 22:58 JST Nmap scan report for 192.168.2.67 Host is up (0.00018s latency). PORT STATE SERVICE 11211/udp open|filtered memcache MAC Address: 00:0C:29:CC:C7:B0 (VMware) Nmap done: 1 IP address (1 host up) scanned in 0.24 seconds
このためnmapによるUDPスキャンの場合は、少々応答時間が増えますが、-sVでバージョン検出を付加すると正しくOpenを判断してくれます。
# nmap -n -sU -sV -p11211 192.168.2.67 Starting Nmap 7.60 ( https://nmap.org ) at 2018-02-28 23:01 JST Nmap scan report for 192.168.2.67 Host is up (0.00018s latency). PORT STATE SERVICE VERSION 11211/udp open memcached Memcached 1.4.15 MAC Address: 00:0C:29:CC:C7:B0 (VMware) Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 0.48 seconds
この際、パケットキャプチャしてみると、以下のようにUDP上で「stats」コマンドを打っていることが分かります。
なお、UDPスキャンはとても遅いスキャンです。特に対象UDPポートから応答が無い場合、上記のオプションのままではタイムアウト待ちとなり1分以上かかるのが普通です。現場では次のように、-Pn(ICMPなどによるhost discoveryを行わない)、--host-timeout(何秒であきらめるか)を同時に指定して高速化を図ると良いでしょう。
# nmap -n -Pn --host-timeout 3 -sU -sV -p11211 192.168.2.67
日本語のmanではhost-timeoutの引数は「ミリ秒」と書かれていますが、この記述は古く、現在の単位は「秒」です。3秒というのはアグレッシブすぎる気もしますが、元々memcachedは高速応答しないと意味がないプロトコルのため、こんなもんでしょう。異論は認める。
ちなみにnmapでもっと詳細情報を得たい場合、memcached-infoというnseスクリプトが利用できます。
# nmap -p11211 --script memcached-info 192.168.2.67 Starting Nmap 7.60 ( https://nmap.org ) at 2018-02-28 23:12 JST Nmap scan report for 192.168.2.67 Host is up (0.00020s latency). PORT STATE SERVICE 11211/tcp open memcache | memcached-info: | Process ID 10330 | Uptime 7147 seconds | Server time 2018-02-28T14:12:28 | Architecture 64 bit | Used CPU (user) 0.077393 | Used CPU (system) 0.066839 | Current connections 10 | Total connections 42 | Maximum connections 1024 | TCP Port 11211 | UDP Port 11211 |_ Authentication no MAC Address: 00:0C:29:CC:C7:B0 (VMware) Nmap done: 1 IP address (1 host up) scanned in 1.19 seconds
nc(netcat)を利用
本当にちょこっと確認したいだけならば、nc(netcat)が便利です。以下のように11211に接続できるかどうかで、ポート開放を判断できます。
$ nc 192.168.2.67 11211 stats ← コマンドを打つ STAT pid 10330 ← 結果が返る STAT uptime 7382 STAT time 1519827383 STAT version 1.4.15 STAT libevent 2.0.21-stable ...(略)...
なおnc(netcat)にはUDPモードもありますが、コマンドラインからUDPで接続してTCP同様に手でコマンドを打っても正しく動作しません。次のようにstatsコマンドを組み立てる必要があります。
# echo -en "\x00\x00\x00\x00\x00\x01\x00\x00stats\r\n" | nc -u 192.168.2.67 11211
※上記コマンドはCloudflareのブログ記事、Memcrashed - Major amplification attacks from UDP port 11211を参考にさせて頂きました。
その他のツール類
memcached-toolを利用
memcached-toolは、Perlで書かれたmemcached操作ツールです。
単独のスクリプトなので、このファイル1つをダウンロードしてPerlで実行するだけで気軽に試せます。ただし、接続はTCPのみサポートしているため、UDPの確認はできません。
引数なしで実行するとヘルプが出ます。
# perl memcached-tool Usage: memcached-tool <host[:port] | /path/to/socket> [mode] memcached-tool 10.0.0.5:11211 display # shows slabs memcached-tool 10.0.0.5:11211 # same. (default is display) memcached-tool 10.0.0.5:11211 stats # shows general stats memcached-tool 10.0.0.5:11211 settings # shows settings stats memcached-tool 10.0.0.5:11211 sizes # shows sizes stats memcached-tool 10.0.0.5:11211 dump # dumps keys and values ...(略)...
便利なのは、dumpコマンドです。これを実行すると現在キャッシュされている全てのkeyと値を出力してくれます。
# perl memcached-tool 192.168.2.67:11211 dump Dumping memcache contents Number of buckets: 3 Number of items : 3 Dumping bucket 1 - 1 total items add key1 0 1519820001 3 100 Dumping bucket 12 - 1 total items add key3 0 1519820001 1000 012345678901234567890...(省略)...0123456789012345678901234567890123456789012345678901234567890123456789 Dumping bucket 4 - 1 total items add key2 0 1519820001 100 0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 root@kali:~#
shodan
個別のホスト探索にはあまり適しませんが、世界中のホストがどの程度11211/tcpを開放しているかは、shodanで確認できます。
「port:11211」というクエリで検索できます。なおこのクエリはログインしていないと利用できませんが、アカウント作成自体は無料です。
参考文献・リンク
- Memcrashed - Major amplification attacks from UDP port 11211
- memcached のアクセス制御に関する注意喚起
- Nmapの真実
- Software Design 2016年5月号「フリーで始めるセキュリティチェック【前編】 Nmapによるポートスキャン」