A couple of months ago I discovered 9 kernel vulnerabilities a security product called STOPzilla AntiMalware. It’s been over a month with no response from the vendor so I’m going public with this one. All of the vulnerabilities stem from output buffer address not being validated apart from ioctl 80002028 where the size of the output buffer is not validated. The table below lists the ioctls, related CVE and type of vulnerability
IOCTL | CVE ID | Vulnerability Type |
0x8000204B | CVE-2018-15729 | Denial of Service |
0x80002067 | CVE-2018-15730 | Denial of Service |
0x8000205B | CVE-2018-15731 | Denial of Service |
0x80002063 0x8000206F | CVE-2018-15732 | Arbitrary Write |
0x80002028 | CVE-2018-15733 | Null pointer dereference |
0x8000206B | CVE-2018-15734 | Arbitrary Write |
0x8000205F | CVE-2018-15735 | Arbitrary Write |
0x8000204F | CVE-2018-15736 | Denial of Service |
0x80002043 | CVE-2018-15737 | Denial of Service |
Here I’m exploiting the arbitrary write vulnerability (CVE-2018-15732) by overwriting the _SEP_TOKEN_PRIVILEGES structure to obtain the SeCreateTokenPrivilege privilege. Then it’s just a matter of calling the ZwCreateToken API to create a new privileged token. The excellent paper “Abusing Token Privileges For LPE” and source code provided needed assistance in exploiting using this privilege.
The “what” dword value starts with 1 and increments each time our ioctl is called so a number of writes needed to be done in order to obtain a useful privilege. Normal privileges would look like this
kd> dt nt!_SEP_TOKEN_PRIVILEGES fffff8a002f11060+40 +0x000 Present : 0x6`02880000 +0x008 Enabled : 0x800000 +0x010 EnabledByDefault : 0x800000 kd> !token fffff8a002f11060 . . 19 0x000000013 SeShutdownPrivilege Attributes - 23 0x000000017 SeChangeNotifyPrivilege Attributes - Enabled Default 25 0x000000019 SeUndockPrivilege Attributes - 33 0x000000021 SeIncreaseWorkingSetPrivilege Attributes - 34 0x000000022 SeTimeZonePrivilege Attributes - . .
After a few writes the SeCreateTokenPrivilege privilege has been obtained. This is one of the privileges received most of the time.
kd> dt nt!_SEP_TOKEN_PRIVILEGES fffff8a002e61a90+40 +0x000 Present : 0x6`00000015 +0x008 Enabled : 0x16 +0x010 EnabledByDefault : 0x800000 kd> !token fffff8a002e61a90 . . 00 0x000000000 Unknown Privilege Attributes - 02 0x000000002 SeCreateTokenPrivilege Attributes - Enabled 04 0x000000004 SeLockMemoryPrivilege Attributes - Enabled 33 0x000000021 SeIncreaseWorkingSetPrivilege Attributes - 34 0x000000022 SeTimeZonePrivilege Attributes - . .
For Windows 7 I’ve spawned a shell by switching to session 0 by calling WinStationSwitchToServicesSession(). The Windows Service “Interactive Services Detection” (UI0Detect) is set to manual and not started to begin with but starts when WinStationSwitchToServicesSession() is called. The first instance a prompt will be given to switch sessions, thereafter will switch automatically as the service is already started.
In Windows 10 (1803) the “Interactive Services Detection” service has been removed and doing a quick test on 1703 I realized the service can’t be started anyway so on Windows 10 I’m just adding the current user to the local administrators group.
The CreateProcessAsUser API doesn’t always behave as expected as occasionally returns 1314 error which means “A required privilege is not held by the client”. Running the exploit a few times and it ends up working so not sure exactly what is really happening here. Trying to run the exploit in another user accounts shell i.e. not logging in with the account doesn’t seem to work at all and always returns 1314 error so bear that in mind.
UPDATE: I just figured out the reason behind the 1314 error, since the CreateProcessAsUser API is still being called by our current process token so after the arbitrary writes sometimes the “SeAssignPrimaryTokenPrivilege” privilege is also obtained along with the “SeCreateTokenPrivilege” allowing the exploit to work. So even when our elevated token is successfully created we’ll need an added privilege “SeAssignPrimaryTokenPrivilege” for the CreateProcessAsUser API to succeed.
The current vulnerable version of STOPzilla AntiMalware is 6.5.2.59 of which the driver version szkg64.sys is 3.0.23.0. The exploit can be downloaded from here [zip] and here is the direct link to the package on the StopZilla site if you wish to play with the exploit [msi]
Click to Open Code Editor