internet-explorerinternet-explorer-11bhoappcontainer

Accessing named pipe servers from within IE EPM BHO


I am trying to make some changes to our legacy product to support IE EPM on the BHO. I have managed to get it to load and the various methods - SetSite, DocumentComplete etc. - get invoked.

I seem to be hitting a snag when trying to connect to the named pipe server running inside a Windows Service.

Previously, we had already made changes to allow IE BHO in protected mode to access the named pipe server - using LOW_INTEGRITY_SDDL_SACL ("S:(ML;;NW;;;LW)"). Within the code, we were using creating the security descriptor using the ConvertStringSecurityDescriptorToSecurityDescriptor method, then performing a SetSecurityDescriptorSacl on the actual SD or the SECURITY_ATTRIBUTES object. This allowed the BHO code to access named pipe servers hosted in the SYSTEM service.

I referred to a few articles and probably the most useful one was this post - Is there a way to create a named pipe from an AppContainer BHO on IE11?

I made some changes to SDDL so it now looks like -

#define EPM_INTEGRITY_SDDL L"S:(ML;;NW;;;LW)D:(A;;FA;;;SY)(A;;FA;;;WD)(A;;FA;;;AC)"

This basically gives full file access to Everyone, ALL APPLICATION PACKAGES and SYSTEM in the DACL part. I know it's way too permissive, but I expected this should at least work once I used SetSecurityDescriptorDacl :-)

Anyway, the code that sets the SD now looks as below. Am I missing something here?

if (!ConvertStringSecurityDescriptorToSecurityDescriptor(EPM_INTEGRITY_SDDL, SDDL_REVISION_1, &pLISD, NULL))
{
    OutputDebugString(L"Unable to get the app-container integrity security descriptor");
    return false;
}

PACL pAcl = 0;
BOOL bAclPresent   = FALSE;
BOOL bAclDefaulted = FALSE;             
if (!GetSecurityDescriptorSacl(pLISD, &bAclPresent, &pAcl, &bAclDefaulted) || !bAclPresent)
{
    return false;
}

if (!SetSecurityDescriptorSacl(pSecurityDesc, TRUE, pAcl, FALSE))
{
    return false;
}

pAcl = 0;
bAclPresent = FALSE;
bAclDefaulted = FALSE;
if (!GetSecurityDescriptorDacl(pLISD, &bAclPresent, &pAcl, &bAclDefaulted) || !bAclPresent)
{
    OutputDebugString(L"Setting to low integrity : No DACL Available");
            return false;
}

if (!SetSecurityDescriptorDacl(pSecurityDesc, TRUE, pAcl, FALSE))
{
    OutputDebugString(L"Setting to low integrity : Unable to set the DACL");
    return false;
}

Solution

  • I did some research and managed to figure out an approach that works.

    First, it appears that the BHO inside the AppContainer cannot access named pipes etc. created in a Windows session other than its own. Since I was creating my named pipe server in a Windows Service, it doesn't matter what security descriptor I specify. It won't work.

    Second, use the medium-integrity broker process to create the named pipe with the same attempted SD and it will be accessible. So, the approach I took was to create a proxy to my BHO that forwards these messages to the Windows Service. So, my "server" logic did not need to move.

    I am not thrilled with the approach, but it isn't too bad, because I can reuse this code for the JS-based extensions too without completely re-writing the core code.

    Third, I needed some way to call back into the BHO to ask it to take some action based on external stimuli. I managed to achieve this by creating a HWND_MESSAGE window in the SetSite of the BHO and calling to it using SendMessage from the Broker process. Since this is cross-process, you would need to use WM_COPYDATA.