脆弱性 | |
2012年10月、Core Security Technologies が Broadcom 製チップセット「BCM4325」と「BCM4329」のファームウェアにおける DoS の脆弱性(CVE-2012-2619)を公表しました。この脆弱性は、「Nexus S」や「iPhone 4」、「iPad 2」など多くのデバイスが影響を受けました。「iPad 2」に対して、この脆弱性の実証コード*1を試してみました。
なお、iOS では iOS 6.1 でこの脆弱性が修正されており、最新バージョンを使用していれば「iPhone 4」や「iPad 2」は影響を受けません。
実証コードの実行環境は、下図の通りです。「Pocket Wifi GP02」を介して、「iPad2」がインターネットにアクセスできる状態で、BackTrack 5 上で CVE-2012-2619 の実証コードを実行しました。実証コードを実行するため、BackTrack 5 では Lorcon と PyLorcon2 をインストールしました。
この実証コードを実行すると、無線 LAN(IEEE 802.11)の電波圏内に問題のある Beacon フレームを送信します。この性質から、無線 LAN の電波圏内に僕の「iPad 2」以外に影響を受けるデバイスがあった場合、それらにも影響を与えてしまいます。そのため、実証コードを実行する場所では影響を受けそうなデバイスが他にないことをあらかじめ確認しました。
まず、「airodump-ng」を 10 数分程度実行して、無線 LAN インターフェイス「wan1mon*2」が受信する無線 LAN フレームから周囲にあるデバイスの MAC アドレスを収集しました(下記 1 行目)。続いて、収集した MAC アドレスから製造メーカを示す OUI(Organizationally Unique Identifier) を取り出しました(下記 2 行目)。
# airodump-ng -w airodump-ng_result --output-format csv wlan1mon # grep -E "^([0-9a-fA-F]{2}\:){5}[0-9a-fA-F]" airodump-ng_result-01.csv | cut -c -8 | sort | uniq > oui.csv
最後に、取り出した OUI の一覧を Wireshark の「OUI Lookup Tool」 に入力して、製造メーカを特定しました。「OUI Lookup Tool」の結果は下記となります。
OUI「1C:1D:67」、「28:6A:BA」、「A0:0B:BA」は、「Pocket Wifi GP02」、「iPad2」、「Galaxy Nexus(SC-04D)」の MAC アドレスから得られたものでした。その他の 4 つの OUI が周囲にあるデバイスから得られたものでした。これら 4 つの製造メーカと、アドバイザリの [4. VULNERABLE PACKAGES] に掲載されているデバイスを照らし合わせました。この結果、周囲に影響を受けそうなデバイスがおそらくないだろうと判断して、実証コードを実行しました。
00:1B:77 Intel Corporate 00:1D:73 Buffalo Inc. 00:24:A5 Buffalo Inc. 00:26:87 ALLIED TELESIS, K.K corega division. 1C:1D:67 Huawei Device Co., Ltd 28:6A:BA Apple, Inc. A0:0B:BA SAMSUNG ELECTRO-MECHANICS
実証コードを実行すると、1 秒間あたり 20 フレームの問題のある Beacon フレームが送信されました(CloudShark)。Wireshark でこの Beacon フレームを確認したところ、802.11 の Information Element「RSN Informaition」の「Auth Key Management (AKM) Suite Count」に 0xff 0xff が設定されていました。
CVE-2012-2619 の実証コードを実行したときに、「iPad 2」にて次の 3 つの事象を確認しました。これらの事象から、CVE-2012-2619 の実証コードを実行していると、影響を受けるデバイスでは無線 LAN 接続が切断され、無線 LAN を介してインターネットに接続できなくなることが分かります。
実証コードを実行したときの「iPad 2」の様子については、下記の動画*3をご覧ください。
この脆弱性による影響は「無線 LAN を介した通信の妨害」のみ(確認した限り)のようですが、実証コードが悪用される場所によっては影響力が大きくなるように感じました。Wifi 版「iPad 2」を使っている身としては、自宅近辺でこの実証コードを実行され続けたら、「iPad 2」でのネットワーク接続ができなくなるので嫌ですね...
メモ | |
2013年2月11日の日記を書いたあとも、Nmap の NSE スクリプト「upnp-info」を使い、「upnp.lua*1」(「upnp-info」が読み込む lua スクリプト)で次の 2 点を変更しました。このとき「upnp-info」を実行すると、次のような結果が得られます。この日記では、この 2 点の変更についてメモします。
$>nmap -sU -p1900 --script=upnp-info -n 192.168.0.106 Starting Nmap 6.25 ( http://nmap.org ) at 2013-03-03 23:35 東京 (標準時) Nmap scan report for 192.168.0.106 Host is up (0.00s latency). PORT STATE SERVICE 1900/udp open upnp | upnp-info: | 192.168.0.106 | Server: Linux/2.6 UPnP/1.0 nasne/1.0 | Location: http://192.168.0.106:58888/ | Webserver: Linux/2.6 UPnP/1.0 nasne/1.0 | Name: nasne | Manufacturer: Sony Computer Entertainment Inc. | Model Descr: nasne | Model Name: nasne | serviceId: urn:upnp-org:serviceId:ConnectionManager | SCPDURL : http://192.168.0.106:58888/MediaServer_ConnectionManager/scpd.xml | controlURL: http://192.168.0.106:58888/MediaServer_ConnectionManager/control | serviceId: urn:upnp-org:serviceId:ContentDirectory | SCPDURL : http://192.168.0.106:58888/MediaServer_ContentDirectory/scpd.xml | controlURL: http://192.168.0.106:58888/MediaServer_ContentDirectory/control | serviceId: urn:s-bras-org:serviceId:X_PvrControl | SCPDURL : http://192.168.0.106:64230/X_PvrControl.xml | controlURL: http://192.168.0.106:64230/X_PvrControl | serviceId: urn:xsrs-org:serviceId:X_ScheduledRecording | SCPDURL : http://192.168.0.106:64230/XSRS.xml |_ controlURL: http://192.168.0.106:64230/XSRS MAC Address: 12:34:56:78:9a:bc (XXXXXXXXXXXXXXXX) Nmap done: 1 IP address (1 host up) scanned in 6.72 seconds
2013年2月11日の日記を書いたときには、nasne に対する「upnp-info」の実行結果に Device description*2 の friendlyName 要素や manufacturer 要素が出力されていませんでした。他の機器に実行した場合、それらが出力されていました。
そこで、nasne に対する「upnp-info」が送信するパケットをキャプチャして確認したところ、GET リクエストの URI が「0x2f 0x0d」(/<CR>)となっていました。このため、nasne の 58888/tcp から HTTP レスポンスコード 404(Not Found)が応答され、「Device description」が取得できていなかったと判断しました。
「upnp.lua」を調べてみると、Location ヘッダから URL を取得するときに「0x0d」を含む文字列(改行コードとして「0x0a」だけを含まない文字列)に一致する正規表現が書かれており、この部分に問題がありました。
この問題を修正するため、次のようなパッチを作成してみました。改めて読み返すと適当すぎますね...この正規表現(x。このパッチをメーリングリスト「nmap-dev」に投稿したところ、(きちんとした正規表現に修正されたうえで)upnp.lua に反映されたようです:)
--- upnp.lua 2013-02-16 17:49:50.745090000 +0900 +++ upnp_edited.lua 2013-02-16 18:28:38.307590000 +0900 @@ -183,7 +183,7 @@ local server, location server = string.match(response, "[Ss][Ee][Rr][Vv][Ee][Rr]:%s*(.-)\010") if server ~= nil then table.insert(output, "Server: " .. server ) end - location = string.match(response, "[Ll][Oo][Cc][Aa][Tt][Ii][Oo][Nn]:%s*(.-)\010") + location = string.match(response, "[Ll][Oo][Cc][Aa][Tt][Ii][Oo][Nn]:%s*(.-)[\010\013]+") if location ~= nil then table.insert(output, "Location: " .. location )
どうせなら Service description*3 の URL(SCPDURL 要素)なども出力したいと思い、さらに次のようなパッチを作成しました。このパッチを upnp.lua に適用すると、冒頭にある出力結果が得られます。
--- upnp.lua 2012-11-30 04:39:54.000000000 +0900 +++ upnp-edited.lua 2013-03-12 23:40:17.140625000 +0900 @@ -183,7 +183,7 @@ local server, location server = string.match(response, "[Ss][Ee][Rr][Vv][Ee][Rr]:%s*(.-)\010") if server ~= nil then table.insert(output, "Server: " .. server ) end - location = string.match(response, "[Ll][Oo][Cc][Aa][Tt][Ii][Oo][Nn]:%s*(.-)\010") + location = string.match(response, "[Ll][Oo][Cc][Aa][Tt][Ii][Oo][Nn]:%s*(.-)[\010\013]+") if location ~= nil then table.insert(output, "Location: " .. location ) @@ -271,6 +271,19 @@ if nm ~= nil then table.insert(output,"Model Name: " .. nm) end if ver ~= nil then table.insert(output,"Model Version: " .. ver) end end + + for service in string.gmatch(response['body'], "<service>(.-)</service>") do + local serviceId, SCPDURL, controlURL + + serviceId = string.match(service, "<serviceId>(.-)</serviceId>") + SCPDURL = string.match(service, "<SCPDURL>(.-)</SCPDURL>") + controlURL = string.match(service, "<controlURL>(.-)</controlURL>") + + if serviceId ~= nil then table.insert(output, "serviceId: " .. serviceId) end + if SCPDURL ~= nil then table.insert(output, " SCPDURL : " .. SCPDURL) end + if controlURL ~= nil then table.insert(output, " controlURL: " .. controlURL) end + + end return true, output else return false, "Could not retrieve XML file"
*1:Nmap インストールディレクトリ\nselib\ 以下にあります。
*2:pp.43-48 2.3 Device description, "UPnP Device Architecture 1.1"
*3:pp.48-55 2.5 Service description, "UPnP Device Architecture 1.1"
メモ | |
Nmap の NSE(Nmap Scripting Engine)スクリプト「upnp-info」を使ってみたところ、使用前に思っていた実行結果と異なっていたため、スクリプトを一部編集してみました。この日記では、「upnp-info」の実行結果と編集したスクリプトについて書きます。
まず「upnp-info」の実行環境は下表の通りです。
| IPアドレス | デバイス | 説明 |
|---|---|---|
| 192.168.0.101 | Windows XP SP3 マシン | 「upnp-info」を実行するデバイス |
| 192.168.0.106 | nasne | 「upnp-info」の実行対象デバイス |
この実行環境で「upnp-info」を実行してみると、nasne の UPnP に関する情報が実行結果に出力されませんでした。なお、Nmap の実行結果のうち、MAC アドレスおよび OUI 情報については「12:34:56:78:9a:bc」、「XXXXXXXXXXXXXXXX」に置換しています。
$>nmap -V Nmap version 6.25 ( http://nmap.org ) Platform: i686-pc-windows-windows Compiled with: nmap-liblua-5.2.1 openssl-1.0.1c nmap-libpcre-7.6 libpcap-4.1.2 nmap-libdnet-1.12 ipv6 Compiled without: Available nsock engines: select $>nmap -sU -p1900 --script=upnp-info -n 192.168.0.106 Starting Nmap 6.25 ( http://nmap.org ) at 2013-02-10 22:40 東京 (標準時) Nmap scan report for 192.168.0.106 Host is up (0.00s latency). PORT STATE SERVICE 1900/udp open|filtered upnp MAC Address: 12:34:56:78:9a:bc (XXXXXXXXXXXXXXXX) Nmap done: 1 IP address (1 host up) scanned in 6.92 seconds
一方で、UPnP を実装しているデバイスを探す NSE スクリプト「broadcast-upnp-info」の実行結果には、nasne の UPnP に関する情報が出力されました。「upnp-info」を使用する前には、このような出力を思い描いていました。
$>nmap -sU -p1900 --script=broadcast-upnp-info -n 192.168.0.106 Starting Nmap 6.25 ( http://nmap.org ) at 2013-02-10 23:37 東京 (標準時) Pre-scan script results: | broadcast-upnp-info: | 192.168.0.106 | Server: Linux/2.6 UPnP/1.0 nasne/1.0 | Location: http://192.168.0.106:58888/ |_ Webserver: Linux/2.6 UPnP/1.0 nasne/1.0 Nmap scan report for 192.168.0.106 Host is up (0.00s latency). PORT STATE SERVICE 1900/udp open|filtered upnp MAC Address: 12:34:56:78:9a:bc (XXXXXXXXXXXXXXXX) Nmap done: 1 IP address (1 host up) scanned in 8.86 seconds
「upnp-info」と「broadcast-upnp-info」のパケットキャプチャデータを確認したところ、UPnP の M-SEARCH リクエスト(後述)の送信方法に違いがありました。「upnp-info」の場合、この違いによって nasne が M-SEARCH リクエストに応答していないと考えました。
「upnp-info」の場合、Nmap で指定した 192.168.0.106 に M-SEARCH リクエストを送信していましたが、「broadcast-upnp-info」の場合、マルチキャストアドレス 239.255.255.250 に送信していました。
「upnp-info」および「broadcast-upnp-info」ともに、下記の M-SEARCH リクエストを送信します。それぞれのパケットキャプチャデータを確認すると、宛先 IP アドレスおよび宛先 MAC アドレスが異なること*1が分かります。なお、「192.168.0.101」および「192.168.0.106」の MAC アドレスについては、それぞれ「bc:9a:78:56:34:12」、「12:34:56:78:9a:bc」に置換しています。
M-SEARCH * HTTP/1.1 Host:239.255.255.250:1900 ST:upnp:rootdevice Man:"ssdp:discover" MX:3
「UPnP Device Architecture 1.1」の「1.3 Search」では、M-SEARCH リクエストが「ネットワーク上の UPnP を実装しているデバイスを探すリクエスト」である旨が記述されています。この仕様書によると、マルチキャストアドレス宛てにM-SEARCH リクエストを送信する以外にも、ユニキャストアドレス宛てに送信できます*2。
「upnp-info」の場合、192.168.0.106 宛てにも関わらず、Host ヘッダを「239.255.255.250:1900」としていることが原因かと推測しましたが、違いました。Host ヘッダを「192.168.0.106:1900」に修正して ncatで送信してみましたが*3、やはり応答がありませんでした。結論としては、UPnP を実装したデバイスの中には、ユニキャスト宛て M-SEARCH リクエストに応答しないものもある、と理解しました。
「broadcast-upnp-info」スクリプト broadcast-upnp-info.lua や upnp.lua を読みながら、「upnp-info」スクリプト upnp-info.lua を次のように編集してみました。
編集した upnp-info.lua は下記の通りとなります。僕が追加したコードは「-----追加 ここから」と「-----追加 ここまで」に囲まれたコード部分です。M-SEARCH リクエストに対して複数の応答が得られる環境で、簡単な動作確認のみ実施しています。
local nmap = require "nmap" local shortport = require "shortport" local stdnse = require "stdnse" local string = require "string" local upnp = require "upnp" -----追加 ここから local table = require "table" -----追加 ここまで description = [[ Attempts to extract system information from the UPnP service. ]] --- -- @output -- | upnp-info: System/1.0 UPnP/1.0 IGD/1.0 -- |_ Location: http://192.168.1.1:80/UPnP/IGD.xml -- -- @args upnp-info.override Controls whether we override the IP address information -- returned by the UPNP service for the location of the XML -- file that describes the device. Defaults to true for -- unicast hosts. -- 2010-10-05 - add prerule support <patrik@cqure.net> -- 2010-10-10 - add newtarget support <patrik@cqure.net> -- 2010-10-29 - factored out all of the code to upnp.lua <patrik@cqure.net> -- 2013-02-11 - call helper:setMulticast(true), and filter only result of target ip <kaito834@gmail.com> author = "Thomas Buchanan" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"default", "discovery", "safe"} --- -- Runs on UDP port 1900 portrule = shortport.portnumber(1900, "udp", {"open", "open|filtered"}) --- -- Sends UPnP discovery packet to host, -- and extracts service information from results action = function(host, port) local override = stdnse.get_script_args("upnp-info.override") local helper = upnp.Helper:new( host, port ) if ( override ~= nil ) and ( string.lower(override) == "false" ) then helper:setOverride( false ) else helper:setOverride( true ) end -----追加 ここから helper:setMulticast(true) -----追加 ここまで local status, result = helper:queryServices() -----追加 ここから for key, value in ipairs(result) do if(not(value['name'] == host['ip'])) then table.remove(result, key) end end -----追加 ここまで if ( status ) then nmap.set_port_state(host, port, "open") return stdnse.format_output(true, result) end end
編集した「upnp-info」を実行すると、下記のように「broadcast-upnp-info」と同様の出力が得られました。
$>nmap -sU -p1900 --script=upnp-info -n 192.168.0.106 Starting Nmap 6.25 ( http://nmap.org ) at 2013-02-11 09:46 東京 (標準時) Nmap scan report for 192.168.0.106 Host is up (0.00s latency). PORT STATE SERVICE 1900/udp open upnp | upnp-info: | 192.168.0.106 | Server: Linux/2.6 UPnP/1.0 nasne/1.0 | Location: http://192.168.0.106:58888/ |_ Webserver: Linux/2.6 UPnP/1.0 nasne/1.0 MAC Address: 12:34:56:78:9a:bc (XXXXXXXXXXXXXXXX) Nmap done: 1 IP address (1 host up) scanned in 8.11 seconds
*1:「broadcast-upnp-info」では、宛先 MAC アドレスが 01:00:5e:7f:ff:fa となります。参考:http://d.hatena.ne.jp/naablaa/20061129#p1
*2:「Control points can also send a unicast search message to a known IP address...」という記述が該当します
*3:ncat -u --send-only 239.255.255.250 1900 < msearch.txt
メモ | |
Bluetooth デバイス間を流れるトラフィックをキャプチャしたいと思い、関連する情報を調べてました。その調べた結果を整理するために、日記にまとめてみました。
ノート PC 等に内蔵されている Bluetooth デバイスなどを使用する場合、「そのデバイスが送信する HCI データ」または「そのデバイスに向けて送信される HCI データ」しかキャプチャできません。Wireshark Wiki における「Bluetooth traffic to or from your machine」という記述、および hcidump の man マニュアルにおける「raw HCI data coming from and going to a Bluetooth device」という記述が、このことを裏付けています。
Bluetooth デバイス間を流れるトラフィックを無作為にキャプチャする場合*1、商用製品または Ubertooth One などの特殊な Bluetooth デバイスが必要となるようです。neko氏のブログ記事によると、商用製品には Frontline 社の製品(FTS4BT?)があるようです。「Ubertooth One」を使うと、Bluetooth トラフィックのキャプチャやインジェクションが実現できるようです。
試しに Linux の Bluetooth スタック「BlueZ」の「hcidump」を使って、Buffalo 製 Bluetooth デバイスが送受信する HCI データをキャプチャしてみました。
下図の通りです。BackTrack 5R3 を起動した「ノート PC」から「l2ping」コマンドを実行して、「ノート PC」と「Galaxy Nexus(SC-04D)」でやり取りされる HCI データを「hcidump」コマンドでキャプチャします。
BackTrack 5R3 に同梱されている「hcidump」コマンドのバージョンを確認した後、Bluetooth 論理インターフェイス hci0 で HCI データをキャプチャしました。キャプチャした HCI データを bt.pcap に保存しました(下記参照)。
root@bt:/tmp# hcidump -version 2.3 root@bt:/tmp# hcidump -i hci0 -w bt.pcap HCI sniffer - Bluetooth packet analyzer ver 2.3 btsnoop version: 1 datalink type: 1002 device: hci0 snap_len: 1028 filter: 0x0
「hcidump」コマンドを実行しているときに、「l2ping」コマンドを「Galaxy Nexus(SC-04D)」の MAC アドレス宛に実行しました(下記参照)。「l2ping」コマンドの実行結果では、Buffalo 製 Bluetooth デバイスの MAC アドレスを「aa:bb:cc:dd:ee:ff」、「Galaxy Nexus(SC-04D)」の MAC アドレスを「00:11:22:33:44:55」に置換しています。
root@bt:~# l2ping -i hci0 -c 5 00:11:22:33:44:55 Ping: 00:11:22:33:44:55 from aa:bb:cc:dd:ee:ff (data size 44) ... 44 bytes from 00:11:22:33:44:55 id 0 time 6.85ms 44 bytes from 00:11:22:33:44:55 id 1 time 25.81ms 44 bytes from 00:11:22:33:44:55 id 2 time 4.82ms 44 bytes from 00:11:22:33:44:55 id 3 time 27.81ms 44 bytes from 00:11:22:33:44:55 id 4 time 28.83ms 5 sent, 5 received, 0% loss
「l2ping」コマンドを実行したあと、「hcidump」コマンドを終了しました。bt.pcap を Wireshark で開くと、下図のようになります。bt.pcap ファイルから「l2ping」コマンドの実行結果(リクエストおよびレスポンス)のみ抽出して、CloudShark にアップしました。
「hcidump」コマンドで取得した bt.pcap のファイルタイプを「file」コマンドで確認したところ、「BTSnoop」のファイルタイプに該当していました。この「BTsnoop」は、Symbian OS における Bluetooth HCI layer のログフォーマットに該当します。
root@bt:/tmp# file bt.pcap bt.pcap: BTSnoop version 1, HCI UART (H4)
「Ubertooth One」で Bluetooth トラフィックをキャプチャする場合、libbtbb のデータ形式で保存されるようなので、「hcidump」のデータ形式と異なるようです。このブログ記事で Wireshark のスクリーンショットをみてみると、確かに違う... とはいえ、「Bluetooth デバイス間をどんなデータが流れるか」を知る目的であれば、「hcidump」のキャプチャデータでも参考になります。
Bluetooth トラフィックをキャプチャすることは難しい。
*1:Ehternet(802.3) の Network Interface Card(NIC) における promiscous モードや、無線 LAN(802.11) の NIC における Monitor モードに該当します。
メモ | |
2012年12月2日の日記で書いた方法で、Scapy による無線LAN(802.11)frame injection を実践していたところ、「WARNING: Mac address to reach destination not found」という警告メッセージが出力されました(下記参照)。このとき、Wireshark でパケットキャプチャしていも、802.11 フレームが送信されていませんでした。
root@bt:~# scapy WARNING: No route found for IPv6 destination :: (no default route?) Welcome to Scapy (2.0.1) >>> send(RadioTap()/Dot11(addr1="ff:ff:ff:ff:ff",addr2="00:11:22:33:44:55",addr3="00:11:22:33:44:55")/Dot11Beacon(cap="ESS")/Dot11Elt(ID="SSID",info="scapy-frame-injection")/Dot11Elt(ID="Rates",info="\x82\x84\x0b\x16")/Dot11Elt(ID="DSset",info="\x06")/Dot11Elt(ID="TIM",info="\x00\x01\x00\x00"),iface="wlan1mon",loop=1,inter=1) WARNING: Mac address to reach destination not found. Using broadcast. .WARNING: Mac address to reach destination not found. Using broadcast. .WARNING: more Mac address to reach destination not found. Using broadcast. ...WARNING: Mac address to reach destination not found. Using broadcast. (snip)
この警告メッセージが出力された原因は、OSI 参照モデルにおける Layer 2 のプロトコルを編集したフレームを送信するために send() 関数を使用したことにありました。Layer 2 のプロトコルを編集したフレームを送信する場合、sendp() 関数を使用する必要があります。下記がマニュアルの該当部分の記述です。
The send() function will send packets at layer 3. That is to say it will handle routing and layer 2 for you. The sendp() function will work at layer 2.
Sending packets, Usage ― Scapy v2.1.1-dev documentation