CVE-2018-6687
An exploitable Denial of Service vulnerability exists in the file scanning functionality of McAfee GetSusp 3.0.0.461. A specially crafted executable can cause an infinite loop resulting in a Denial of Service. An attacker can scan this executable to trigger this vulnerability.
McAfee GetSusp 3.0.0.461
https://www.mcafee.com/us/downloads/free-tools/getsusp.aspx
6.5 - CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H
CWE-835: Loop with Unreachable Exit Condition (‘Infinite Loop’)
McAfee getsusp.exe is a portable malware scanning and removal tool that can isolate malware samples found on a given computer. Classification is done via heuristics and also by talking with the McAfee GTI (Global Threat Intelligence) service. After files have been scanned and classified, unless opted out, getsusp.exe will then submit all the samples to McAfee labs.
When loading in a PE (portable executable) file, getsusp.exe will parse out different sections of the file, in search of suspect attributes, as is typical for all anti-virus. One of the sections specifically looked at is the file version information of the executable, i.e. the information that is displayed when you right click an .exe, and then navigate to ‘Properties’->’Details’ tab. Such information might contain the file version or copyright information and so forth as a collection of strings. This information is stored as such inside of an exe:
\x00\x00\x00\x00 + <Little Endian Size (4-bytes)> + Unicode String Data
00 00 00 00 DA 02 00 00 01 00 53 00 74 00 72 00 ….............S.t.
69 00 6E 00 67 00 46 00 69 00 6C 00 65 00 49 00 r.i.n.g.F.i.l.e.I.
6E 00 66 00 6F 00 00 00 n.f.o...
After this, more size information and language information is included, which denotes charset and language:
B6 02 00 00 01 00 30 00 34 00 30 00 39 00 30 00 ......0.4.0.9.0
34 00 42 00 4C 00 16 00 01 00 43 00 .4.B.0...L
And finally, the actual variable names and data pairs:
69 00 6C 00 65 00 6E 00 61 00 6D 00 65 00 00 00 i.l.e.n.a.m.e...
43 00 41 00 4C 00 43 00 2E 00 45 00 58 00 45 00 C.A.L.C...E.X.E
Back to getsusp.exe, in order to grab this version information for parsing, the program calls the Windows API calls GetFileVersionInfoSize:
DWORD WINAPI GetFileVersionInfoSize(
_In_ LPCTSTR lptstrFilename,
_Out_opt_ LPDWORD lpdwHandle
);
Which takes the return value and feeds it into GetFileVersionInfoW, which outputs the complete version data in a buffer pointed to by lpData:
BOOL WINAPI GetFileVersionInfo(
_In_ LPCTSTR lptstrFilename,
_Reserved_ DWORD dwHandle,
_In_ DWORD dwLen,
_Out_ LPVOID lpData
);
After this, the program queries the Version information struct for the VarFileInfo struct, by using VerQueryValue function::
BOOL WINAPI VerQueryValue(
In LPCVOID pBlock, // Ptr to raw ver info data from GetFileVersionInfoW
In LPCTSTR lpSubBlock, // Value to be retrieved: “VarFileInfo”
Out LPVOID *lplpBuffer,
Out PUINT puLen
);
Unfortunately, this call fails, and the program branches accordingly to the function in which the bug occurs. This function seems to skip over the VS_VERSION_INFO header, and search for any StringFileInfo type variables within the FileVerisionInfo buffer manually. It does this with the following loop:
loc_43E4E0:
; esi == part after StringVersionInfo
024 lea eax, [esi+6] ; ......S.t.r.i.n.
024 push offset StringFileInfo ; unicode(StringFileInfo)
push eax
call manual_str_cmp? ; returns 0xffffff8d
add esp, 8
test eax, eax
jz short loc_43E509 ; branch not hit
movzx eax, word ptr [esi] // [1]
add esi, 3
add esi, eax
and esi, 0FFFFFFFCh // [2]
cmp esi, edi
jb short loc_43E4E0 ; Loop back up to top
The loop does a manual search for any StringFileInfo variables by jumping over each variable, if it does not match the correct type. Since each variable has the length of the variable name and variable data (\x00\x00\x00\x00 + <Little Endian Size (4-bytes)> + Unicode String Data), the loop just increments it’s pointer by the value found in the file [1] added with three, and then aligns it at [2]. Unfortunately, if the value pointed to by esi is ever 0x0, then ((0x0 + 0x3) & 0xFFFFFFFC) = 0x0, and the pointer, esi, never actually increments. And since esi is used to break out of the loop, by comparing it to a pointer at the end of the FileVersionInfo Buffer, the loop happens indefinitely, causing the getsusp.exe to become stuck, and needing to be forcibly killed.
Disassembly:
getsusp!RetrieveSingleExtensionList+0x2fed5a:
000000000073f20a 55 push rbp
00000000
0073f20b 8bec mov ebp,esp
000000000073f20d 833dac32830000 cmp dword ptr [00000000
00f724c0],0
000000000073f214 7575 jne getsusp!RetrieveSingleExtensionList+0x2feddb (00000000
0073f28b)
000000000073f216 8b5508 mov edx,dword ptr [rbp+8]
00000000
0073f219 85d2 test edx,edx
000000000073f21b 7517 jne getsusp!RetrieveSingleExtensionList+0x2fed84 (00000000
0073f234)
000000000073f21d e85d540000 call getsusp!RetrieveSingleExtensionList+0x3041cf (00000000
0074467f)
Stack Dump:
0000000003c2fcc4 0043e4ee getsusp+0x3e4ee
00000000
03c2fcc8 03267c36
0000000003c2fccc 0077d500 getsusp!RetrieveSingleExtensionList+0x33d050
00000000
03c2fcd0 03c2fd64
0000000003c2fcd4 031cda74
00000000
03c2fcd8 0000084c
0000000003c2fcdc 00000000
00000000
03c2fce0 03c2fd30
0000000003c2fce4 0043dfb1 getsusp+0x3dfb1
00000000
03c2fce8 03267850
0000000003c2fcec 6c2d95ae
00000000
03c2fcf0 03c2fd30
00000000`03c2fcf4 0043dfc6 getsusp+0x3dfc6
2018-03-06 - Vendor Disclosure
2018-04-10 – 1st Follow up with vendor
2018-04-25 – 2nd Follow up with vendor
2018-04-30 – 3rd Follow up with vendor
2018-04-30 – Vendor acknowledged security report and assigned Case ID SBC1803061
2018-07-26 – 4th Follow up with vendor regarding timeline for fix
2018-08-02 – Vendor advised issue addressed in build made public on 2018-07-04 (GetSusp build 3.0.0.575)
2018-08-06 – Inquired about CVE assignment from vendor; Vendor advised will not assign since it is considered a software defect and they do not consider it a vulnerability
2018-08-15 – Talos requested CVE from Mitre; Mitre reached out and provided deadline of 2018-09-05 for McAfee to respond
2018-09-28 – Vendor acknowledged best interest to publish CVE for customers
2018-10-29 – Vendor assigned CVE< br>
2018-11-12 – Follow up with vendor for public disclosure timeline
2019-01-03 – Follow up with vendor
2019-02-08 – Vendor advised will review for any internal updates to the issue
2019-02-18 - Vendor revised CVE allocation
2019-02-20 – Public Disclosure
Discovered by Lilith of Cisco Talos