スマートフォン解析 top

TOP > タイガーチームセキュリティレポート > Windows Telnet Service Buffer Overflow (CVE-2015-0014)

タイガーチームセキュリティレポート

Windows Telnet Service Buffer Overflow (CVE-2015-0014)

WindowsのTelnetサービスで見つかったbuffer overflowの脆弱性(CVE-2015-0014)を検証しました。

いまどきTelnetなんて誰が使ってるの?と思われるかもしれませんが、業務でネットワーク診断をしているとTelnetサービスが稼働しているホストに出会うことは以外と珍しくありません。

多くのWindowsシステムがこの脆弱性の影響を受けます。パッチを当てていない状態でTelnetサービスを立ち上げているとリモートコード実行、DoS等の被害を受ける可能性があります。


32bitのWindows 7 SP1で検証しました。デフォルトでTelnetサービスが無効化されているので、今回は検証のためにTelnetサービスを有効化しました。

検証に入る前に、まずはRFCをひもといて古き良きTelnetプロトコルについてお勉強することにします。特に興味があるのはコマンドのデータ構造です。

TELNET COMMAND STRUCTURE

   All TELNET commands consist of at least a two byte sequence:  the
   "Interpret as Command" (IAC) escape character followed by the code
   for the command.  The commands dealing with option negotiation are
   three byte sequences, the third byte being the code for the option
   referenced.

... snip ...

   The following are the defined TELNET commands.  Note that these codes
   and code sequences have the indicated meaning only when immediately
   preceded by an IAC.

      NAME               CODE              MEANING

      SE                  240    End of subnegotiation parameters.
      NOP                 241    No operation.
      Data Mark           242    The data stream portion of a Synch.
                                 This should always be accompanied
                                 by a TCP Urgent notification.
      Break               243    NVT character BRK.
      Interrupt Process   244    The function IP.
      Abort output        245    The function AO.
      Are You There       246    The function AYT.
      Erase character     247    The function EC.
      Erase Line          248    The function EL.
      Go ahead            249    The GA signal.
      SB                  250    Indicates that what follows is
                                 subnegotiation of the indicated
                                 option.
      WILL (option code)  251    Indicates the desire to begin
                                 performing, or confirmation that
                                 you are now performing, the
                                 indicated option.
      WON'T (option code) 252    Indicates the refusal to perform,
                                 or continue performing, the
                                 indicated option.
      DO (option code)    253    Indicates the request that the
                                 other party perform, or
                                 confirmation that you are expecting
                                 the other party to perform, the
                                 indicated option.
      DON'T (option code) 254    Indicates the demand that the
                                 other party stop performing,
                                 or confirmation that you are no
                                 longer expecting the other party
                                 to perform, the indicated option.
      IAC                 255    Data Byte 255.
rfc854

今回のPoCで使われるのは"Are You There"です。オプションのないコマンドなので2バイトのシーケンス0xff + 0xf6でが1つのコマンドになります。Terminalから実際にこのコマンドを使ってみましょう。

$ telnet
telnet> open 192.168.1.110
Trying 192.168.1.110...
Connected to 192.168.1.110.
Escape character is '^]'.
Welcome to Microsoft Telnet Service 

password: 
telnet> send ayt

[Yes]

telnet> quit
Connection closed.
$ 
$ printf "\xff\xf6" | nc 192.168.1.110 23
??%??????'??????
[Yes]
$

2通りの方法で"Are You There"を実行してみましたが、想定通り同じ結果になりました。これで"Are You There"コマンドはマスターしました 複数のコマンドを一度にまとめて実行することもできます。

$ printf "\xff\xf6\xff\xf6\xff\xf6" | nc 192.168.1.110 23
??%??????'??????
[Yes]

[Yes]

[Yes]
$

もし"Are You There"をもっと大量に送り込んだら何が起こるでしょう?というのが今回のポイントです。


中国のとあるハッカーが脆弱性を分析しています。

脆弱性のあるファイルはTelnetサービス本体のtlntsvr.exeではなく、Telnetサービスへの接続時に実行されるtlntsess.exeです。

さらに、tlntsess.exeの中のCRFCProtocol::ProcessDataReceivedOnSocket()から脆弱性の原因となっている箇所を疑似コードで示したものが以下です。

ここは何をしているかというと、入力バッファから1バイトずつ読み込み、値に応じた処理を実行して、処理結果を出力バッファに格納するという処理をループで実行しているところです。

v6が入力バッファの1バイトを指すポインタで、v6の値に応じて処理内容が決まります。v13が出力バッファの1バイトを指すポインタで、次に処理結果を書き込むべき場所を指しています。

v6の値に応じて処理を行っている箇所が(*(&off_1011008 + 3 * v7))(v3, &v14, &v13, *v6)です。ここでoff_1011008はそれぞれの処理ルーチンを格納したテーブル(telnetTransTable)で、そのオフセットである3 * v7はv6の値により決定します。例えばv6の指す値が0xf6の場合はAreYouThere()が呼ばれます。

v13は1ループごとに値が大きくなっていきます。v13が2048バイトの境界値をまたがないように毎回バッファの先頭&Srcと比較されていますが、この条件設定では大量のコマンドを処理した際にバッファがあふれるまでループが止まらないはずです。本来はあふれる直前で止めるべきでしょう。

そこでオーバーフローを発生させるためには、大量のコマンドでv13の値を増加させればよいこともわかりました。例えばすでにわたしたちが良く知っている"Are You There"コマンドを実行した場合は何が起こるでしょうか。以下はAreYouThere()の疑似コードです。

出力バッファに9バイトの文字列(改行 + [Yes] + 改行)を書き込み、ポインタを9増やしています。つまり"Are You There"コマンドを実行することでv13は9だけ増加することになります。

電卓で計算してみると228個の"Are You There"コマンドで最後のNULLを含め5バイト分のオーバーフローが発生する計算になります。デバッガでtlntsess.exeにアタッチして確認してみます。

$ perl -e 'print "\xff\xf6" x 228' | nc 192.168.1.110 23
??%??????'??????

returnする直前のsecurity cookieをチェックする箇所でブレークしてスタックの状態をチェックすると、ちょうど5バイトあふれてsecurity cookieが上書きされていることがわかります


以上、Telnetサービスのstack buffer overflowを検証しましたが、書き込めるデータは限定されるためこの脆弱性を利用してリモートコード実行を達成するのは難しい気がします。ただし、容易にDoSになります。

実際に上で説明した方法で攻撃してみると、Telnetで許可された接続数と同じ数だけ攻撃した後はTelnetでログインできない状態になりました。(おそらくセッションが残ってしまうためかと)


参考情報:
[1] Microsoft Security Bulletin MS15-002 - Critical
https://technet.microsoft.com/en-us/library/security/ms15-002
[2] MS15-002 telnet服??冲区溢出漏洞分析与POC?造
http://drops.wooyun.org/papers/4621
[3] JVNDB-2015-001035 複数の Microsoft Windows 製品の Telnet サービスにおけるバッファオーバーフローの脆弱性
http://jvndb.jvn.jp/ja/contents/2015/JVNDB-2015-001035.html


タイガーチームメンバー 塚本 泰三