AnyConnect Elevation of Privileges, Part 2

AnyConnect Elevation of Privileges, Part 2

In the previous part of this multi-part article, I explained how I reversed engineered one of the binaries of the Cisco AnyConnect (CAC) Secure Mobility Client. This allowed me to understand the header format of the network packets used in the Inter-Process Communication (IPC) mechanism. In this part, I will focus on doing a more dynamic analysis in order to understand what goes in the packet body.

To understand the packet body content (i.e. the data returned by the getDataBuffer function in the CIpcMessage class), instead of continuing with the reverse engineering effort (by focusing on the CLaunchClientAppTlv class), I decided to do a dynamic analysis.

Instead of capturing the network traffic in a traditional manner, I decided to use API Monitor. This allows for the interception of the network traffic but also the calls to the various functions that could be involved in the IPC mechanism. To do that, I enabled the interception of:

  • The WSASend and WSARecv functions.
  • All the functions of the CProcessApi class.
  • All of the TLV classes member functions.

Then, I attached to the vpnagent.exe process and by using the vpnui.exe client to initiate a connection to VPN endpoint, I was able to obtain the following capture.

API Monitor capture
The captured functions calls while connecting.

From the “Monitored Processes” list, it is clear that at some point in the connection process, the vpndownloader.exe executable is launched (also referenced in the Google Project Zero advisory). Searching in the capture for CLaunchClientAppTlv revealed a nice sequence of function calls that are clearly related with that launch.

API Monitor capture detail
Details of the packet header received.
API Monitor capture detail
Details of the packet body received.

Since the calling thread is the same, it is clear that these functions are executed sequentially. This is what happened:

  • The first 26 bytes of the packet are received and validated by vpnagent.exe.
  • If the validation is successful, the rest of the packet is read from the socket.
  • A CLaunchClientAppTlv class is instantiated and used to obtain the parameters necessary to launch the application.
  • A CProcessApi class is instantiated to launch the application.

Mapping the received packet header to the CIpcMessage fields results in the following.

 Notice how the headerLength value (26 bytes) matches the received header data length and how the dataLength value (430 bytes) matches the received body length.

Taking into consideration the fact that the packet body is of a Type, Length, Value (TLV) format and using as an example a packet generated by the Google POC, it is easy to extract the various entries. However, the second to last entry doesn’t seem to follow the same format as the others and is missing from the packet generated by Google POC.

Going back to the functions call trace, and inspecting the disassembly of the called CLaunchClientAppTlv class member functions, it was possible to understand what each function maps to:

  • CLaunchClientAppTlv::GetRelocatableFilePath maps to entry at index 6.
  • CLaunchClientAppTlv::GetCmdLine maps to entry at index 2.
  • CLaunchClientAppTlv::GetGUIDesktop not used in the packet, but maps to a entry at index 4.
  • CLaunchClientAppTlv::GetUseInstalled maps to entry at index 5.
GetUseInstalled detail
Details of the GetUseInstalled disassembly.

Taking all of this into account, it was possible to understand the format of the entry at index 5.

This entry got me thinking: what if the value was zero? To answer this question, I added a after-call breakpoint on the WSARecv function so that when it was triggered, I could change this entry value to zero directly on the data received. This made the vpnagent.exe launch the vpndownloader.exe from the C:\ProgramData\Cisco\Cisco AnyConnect Secure Mobility Client\Temp\Downloader directory.

Exploit example runs
Exploit example runs.

Since this directory is world writable, and the vpndownloader.exe application is (still) vulnerable to DLL planting it is possible to escalate privileges in the same maner as it was in CVE-2015-4211 and CVE-2015-6305.

 The DLL must be named dbghelp.dll. After this DLL is loaded, the vpndownloader.exe restricts the LoadLibrary search path.

The Cisco advisory can be found here and I have hosted the proof of concept source code based on this research in this repository. Cheers x)