Axessh 4.2 - Denial Of Service

2017-02-23T00:00:00
ID SSV:92699
Type seebug
Reporter k0shl
Modified 2017-02-23T00:00:00

Description

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

这里要提的一点是,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&gt; 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 &gt;&gt;= 8; ++v1; } while ( v1 &lt; 8 ); sub_41BC20(2); v2 = 0; do sub_41BC70(v42[v2++]); while ( v2 &lt; 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&gt; bp 432796 *** ERROR: Symbol file could not be found. Defaulted to export symbols for wsshd.exe - 0:004&gt; bp 00402bf8 0:004&gt; 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,也就是结构体没有赋初值,从而导致了空指针引用,引发拒绝服务漏洞。