looking at wcf's security programming from a bug mended three times -- tencent security xuanwu laboratory

Posted by trammel at 2020-02-27

In November 2016, the author found and reported the privilege escalation vulnerability of HP support assistant (HPSA). HP product security response team (HP PSRT) responded quickly, but refused to issue security bulletins and CVE for the vulnerability because it could be automatically fixed by the automatic update function of the software. In April, after thinking about this incident, the author analyzed the HPSA after patching again, and found that HP developers made lower level errors in patching, which led to the patch being bypassed to re implement the privilege promotion. In the subsequent communication and cooperation with HP PSRT, the author once again used other techniques to bypass its subsequent repair, and finally assisted HP PSRT to complete the repair of the vulnerability.

This paper will analyze the causes of this vulnerability and the multiple patches bypassing, hoping to take this as a case to improve the developers' understanding and understanding of security, so as to reduce the security vulnerabilities caused by the lack of understanding of the technology used and the lack of awareness of security programming.

HPSA is the system management software introduced by HP, which is installed in all HP PCs by default. It is used to maintain the system and printer, and provide automatic update and other functions. HPSA uses. Net to develop, and its system service hpsupportsolutionsframeworkservice uses WCF to communicate with clients, to complete high authority sensitive operations such as system update and management. Although HPSA uses a new distributed processing technology WCF, it uses an incorrect authentication method in the process of communication between server and client. As a result, the attacker can bypass the authentication, and finally use the defects of its sensitive service interface to realize the privilege promotion from everyone to system.

This paper will analyze the WCF technology background, vulnerability discovery, vulnerability utilization, patch implementation and two bypass.

WCF (Windows communication foundation) is a programming framework for service-oriented applications. Services based on WCF can take two forms: 1) hosting services in IIS through IIS; 2) hosting services in ordinary applications and windows services through self hosting.

WCF uses the concept of endpoint to transfer asynchronous messages between service endpoint and customer endpoint. Endpoint is used to describe where messages are sent and how they are sent. A server endpoint consists of three parts:

1) . addrsss uniquely identifies endpoint, which is the URI describing the service interface. It can be a relative address (relative to the URI of ServiceHost (type, URI []), or an absolute address.

2) . binding specifies the interface type bound to the endpoint, and describes the protocol, message encoding method, security settings, etc. used for communication between endpoints. WCF supports: httpbindingbase, msmqbindingbase, netnamedpipebinding, netpeertcpbinding, NetTcpBinding, udpbinding, webhttpbinding, wsdualhttpbinding, wshttpbindingbase, custombinding.

3) . contract contract specifies and sets the service interface bound to the current endpoint, i.e. which methods are exported to the client, authorization status of methods, message format, etc.

HPSA's system service, hpsupportsolutionsframeworkservice, has system permission and has opened multiple namepipes that allow everyone account to read and write. This sensitive behavior has attracted the attention of the author, so the installation package under dump is further analyzed.

After de obfuscation and de compilation, code audit was carried out, and it was found that the system services of HPSA used WCF to interact with the client. It creates an endpoint bound to netnamedpipebinding (URI: "net. Pipe: / / localhost / hpsupportsolutionsframework / HPSA") and allows clients to call multiple service interfaces bound to this endpoint: HP. Supportframework. Servicemanager. Interfaces:: iserviceinterface.

HPSA authenticates the client when the connection is established to prevent sensitive interfaces from being called by malicious programs. The interaction process between server and client is shown in the following table:

During the interaction between server and client, hpsupportsolutionsframeworkservice uses a variety of ways to ensure security: verifying whether the client is signed by HP, using securestring to store guid, using rngcryptoserviceprovider to generate random number, and verifying the token of client when calling sensitive interface.

The Bank of thousands of miles is destroyed in the ant colony, but there is a security vulnerability in the seemingly meticulous authentication logic: hpsupportsolutionsframeworkservice uses process.mainmodule.filename to obtain the file path of the client, and then verifies its file signature. However, in C ා, process.mainmodule.filename gets the module path by calling PEB (process environment block) of getmodulefilename() index process. PEB is located in the user space of the process, so it can be modified and replaced by attackers. The attacker only needs to modify the PEB before connecting to the endpoint of the server, so that the module path points to an effective HP signature file, which can bypass the signature detection and finally pass the authentication.

After bypassing the authentication of HPSA server, you can call the service interface function bound to this endpoint. The next work is to find the available methods from the available service interface functions to realize the privilege promotion. The service interface function of hpsupportsolutionsframeworkservice is implemented in HP. Supportframework. Servicemanager. Servicetasks:: servicetask. After browsing the interface function roughly, it is found that the uncompresscabfile service interface can be used to write any file, and the deletefile service interface can be used to delete any file.

The implementation logic of uncompresscabfile is as follows:

public bool UncompressCabFile(string cabFilePath, string destDirectory, string token) { if (!\u0004.Instance.\u0001(SharedCommon.StringToSecureString(token))) { if (DebugLog.IsDebug) { DebugLog.LogDebugMessage("signature validation failure for UncompressCabFile", DebugLog.IndentType.None); } return false; } if (!File.Exists(cabFilePath)) { return false; } if (!Validation.VerifyHPSignature(cabFilePath)) { File.Delete(cabFilePath); return false; } string text = "\"" + cabFilePath + "\""; string text2 = "\"" + destDirectory + "\""; ProcessStartInfo processStartInfo = new ProcessStartInfo(); processStartInfo.set_WindowStyle(1); processStartInfo.set_Arguments("-qq " + text + " -d " + text2); processStartInfo.set_FileName(SupportAssistantCommon.FrameworkPath + "Modules\\unzip.exe"); Process process = new Process(); process.set_StartInfo(processStartInfo); process.Start(); process.WaitForExit(); if (File.Exists(cabFilePath)) { File.Delete(cabFilePath); } return true; }

Uncompresscabfile uses unzip.exe to unzip the compressed file cabfilepath to destdirectory. Before unzipping, the signature of the CAB file is verified first. Because there is a time difference between signature verification and decompression, there is a problem of time of check to time of use. You can use conditional competition to bypass signature detection and write files to any directory, and finally you can achieve privilege promotion.

The implementation logic of deletefile is as follows:

public void DeleteFile(string filePath, string token) { if (\u0007.Instance.\u0001(SharedCommon.StringToSecureString(token))) { try { File.Delete(filePath); return; } catch (Exception ex) { if (DebugLog.IsDebug) { DebugLog.LogDebugMessage("exception in DeleteFile: " + ex.Message, DebugLog.IndentType.None); } return; } } if (DebugLog.IsDebug) { DebugLog.LogDebugMessage("token not valid in DeleteFile", DebugLog.IndentType.None); } }

Therefore, the process is as follows: 1. Modify PEB to point the process path to a legal HP signer; 2. Obtain the get ﹐ instance() method of serviceinterface class in hp.supportframework.servicemanager.interfaces namespace through reflection mechanism; 3. Instantiate serviceinterface; 4. Call serviceinterface:: uncompresscabfile service interface, and realize privilege promotion in combination with conditional competition

HP PSRT responds quickly after the vulnerability report, and informs by email that a new version has been released to solve this security vulnerability within half a month. In early April, after re analysis, it was found that the new version of HPSA was still using everyone writable namepipe, so the author decided to re analyze the HP repair.

Through short-term reverse analysis, the location of patch repair is located. The patch adds the following logic in HP. Supportframework. Servicemanager. Interfaces:: serviceinterface:: get_instance():

StackFrame stackFrame = new StackFrame(1); MethodBase method = stackFrame.GetMethod(); Type declaringType = method.get_DeclaringType(); string name = method.get_Name(); if (name.ToLowerInvariant().Contains("invoke")) { string text2 = new \u0007().\u0001(Process.GetCurrentProcess()); text2 = Uri.UnescapeDataString(Path.GetFullPath(text2)); string text3 = Assembly.GetEntryAssembly().get_Location(); text3 = Uri.UnescapeDataString(Path.GetFullPath(text3)); if (text3.ToLowerInvariant() != text2.ToLowerInvariant()) { if (DebugLog.IsDebug) { DebugLog.LogDebugMessage(string.Concat(new string[] { "Illegal operation. Calling process (", text3, ") is not the same as process invoking method (", text2, ")" }), DebugLog.IndentType.None); } throw new Exception("Invoking methods is not allowed."); } } namespace \u0007 { // Token: 0x02000081 RID: 129 internal sealed class \u0007 { internal string \u0001(Process \u0002) { try { string result = \u0002.get_MainModule().get_FileName(); return result; } … } … } }

When instantiating the above code, first obtain the file path of the client through assembly. Getentryassembly(). Get﹐ location(), and compare it with the path of the client module obtained through the process. Mainmodule. Filename method. If it is inconsistent, an exception will be thrown.

The. Net runtime environment specifies that. Net assemblies with the same identity can only be loaded once. Because hp.supportframework.servicemanager.dll has been loaded by hpsupportsolutionsframeworkservice, HP developers believe that this can effectively prevent attackers from bypassing authentication by modifying PEB and creating serviceinterface using reflection mechanism.

However, it is clear that HP. Net developers have overlooked the security boundaries of process space. The detection done here is still located in the client process space. Just like modifying PEB, the client still has the right to modify the data and code in the process space. Before instantiation, the client can locate and modify the detection logic in hp.supportframework.servicemanager.dll; 2. Realize the interaction with server, authentication, service interface call, etc.; 3 Static patch detects the logic and modifies the identity of the assembly hp.supportframework.servicemanager.dll so that the modified file can be loaded into the client process space.

Among them, scheme 3 is the most concise. Here, you can directly use tools to modify its judgment logic as if (Text3. Tolowerinvariant() = = text2. Tolowerinvariant()), and modify the version number of the assembly (the attributes that affect the. Net executable program identity are described in the official Microsoft documents, including: assemblycultureattribute, assemblyflagsattribute, assemblyversionattribute [3]). Finally, the patch can be bypassed and the authority can be upgraded again.

Once again, after reporting the vulnerability and patching scheme to HP PSRT, HP developers have patched it from two aspects: 1. Adjust the authentication mode of the client. The server no longer uses process.mainmodule.filename to get the file path of the client, but uses getprocessimagefilename() to get the file path of the tampered client from PEB. 2. In uncompresscabfile and deletefile, check whether the file / directory path in the parameter is legal.

Check the file / directory path detection logic in uncompresscabfile and deletefile, and find that it only uses string comparison to detect whether the path is legal, rather than to detect the normalized path. The code is as follows:

internal static bool \u0001(string \u0002) { string[] array = new string[] { "AppData\\Local\\Hewlett-Packard\\HP Support Framework", Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + "\\Hewlett-Packard\\HP Support Framework", SupportAssistantCommon.MainAppPath, SupportAssistantCommon.FrameworkPath }; string[] array2 = array; for (int i = 0; i < array2.Length; i++) { string text = array2[i]; if (\u0002.ToLowerInvariant().Contains(text.ToLowerInvariant())) { return true; } } if (DebugLog.IsDebug) { DebugLog.LogDebugMessage("Invalid File detected: " + \u0002, DebugLog.IndentType.None); } return false; }

So directory traversal is used here to bypass path checking. The authentication of client is also easy to bypass. Using any program with valid signature in Hewlett Packard installation directory, inject the exploit code into it to bypass the authentication detection of client.

Finally, HP PSRT corrects the logic of path detection and increases the detection of directory traversal. The relevant codes are as follows:

internal static bool \u0002(string \u0002) { if (!Path.IsPathRooted(\u0002) || \u0002.StartsWith("\\") || \u0002.Contains("..") || \u0002.Contains(".\\")) { if (DebugLog.IsDebug) { DebugLog.LogDebugMessage("Invalid File detected: " + \u0002, DebugLog.IndentType.None); } return false; } return true; }

In the vulnerability details, the author suggests that HP PSRT thoroughly check the security of all service interfaces, and correctly check their parameters to avoid being used by attackers again.

Security vulnerabilities will be introduced in all stages of the software life cycle (requirements analysis, design, implementation, maintenance, etc.). In addition to avoiding security vulnerabilities in the design and implementation stage, researchers need to use reasonable repair programs after vulnerabilities. The problems of HPSA are introduced in design, implementation and maintenance.

1) . the design stage may be to ensure that the unsigned program can also call the non sensitive interface of the server (such as decryptfile, deletetempsession and other service interfaces that do not verify the identity of the client), or to allow the guest user to update the system. As a result, HPSA does not use the access permission checking mechanism [2] provided by the system to isolate the permission boundary, which makes the software introduce security risk from the beginning of design.

2) During the implementation phase, the developers of HPSA did not realize the insecurity of obtaining the path of client file through process.mainmodule.filename, which led to the bypass of authentication; they also did not realize the danger of sensitive service interface, and did not correctly detect the legitimacy of parameters of sensitive service interface, which could be used by attackers for privilege promotion. In fact, any attempt to check the process security through the corresponding files of the process has security risks.

3) In the maintenance phase, during the three times of patching a vulnerability, the developers of HPSA ignored the security boundary of the process and used a variety of wrong patching schemes, resulting in the patch being bypassed many times.

It can be seen from the causes of this vulnerability and multiple fixes that HP developers have problems of inadequate understanding of the technology used and lack of experience in security programming. It is hoped that this article will bring the thinking and experience of security programming to the R & D personnel, and avoid a series of errors like HPSA in the design, implementation and maintenance stages.

1. Windows Communication Foundation Security

2. Authentication and Authorization in WCF Services – Part 1

3. Setting Assembly Attributes