Project

General

Profile

Bug #17134

Make sure the user can see the Unsafe Browser's warning dialog

Added by segfault about 1 month ago. Updated 9 days ago.

Status:
Confirmed
Priority:
Normal
Assignee:
-
Category:
-
Target version:
-
Start date:
Due date:
% Done:

0%

Feature Branch:
wip/bugfix/17134-make-sure-user-sees-unsafe-browser-warning
Type of work:
Code
Blueprint:
Starter:
Affected tool:
Unsafe Browser

Description

In #15635, it was reported that the Unsafe Browser's warning dialog can be hidden from the user by setting a different value for the $DISPLAY environment variable. We should prevent this, by hard coding the $DISPLAY variable in /usr/local/sbin/unsafe-browser.

We can also make sure that the dialog is not immediately closed programmatically (to prevent the user from seeing it), by adding making the "Launch" button insensitive for a few seconds.

Warning Dialog Insensitive.png View (19 KB) segfault, 10/08/2019 06:39 PM

Warning Dialog Sensitive.png View (19.1 KB) segfault, 10/08/2019 06:39 PM


Related issues

Related to Tails - Bug #15635: The Unsafe Browser allows to retrieve the public IP address by a compromised amnesia user with no user interaction Confirmed 06/04/2018

Associated revisions

Revision a9278fcb (diff)
Added by segfault about 1 month ago

Hardcode the $DISPLAY used for the Unsafe Browser (refs: #17134)

This prevents malicious use of the Unsafe Browser without the user
having a chance to see that the Unsafe Browser is started.

Revision 9a9199aa (diff)
Added by segfault about 1 month ago

Add a new warning dialog for the Unsafe Browser (refs: #17134)

This dialog makes the "Launch" button insensitive for 5 seconds, to
increase the chances that the user notices if the Unsafe Browser is
started for malicious use.

History

#1 Updated by segfault about 1 month ago

  • Related to Bug #15635: The Unsafe Browser allows to retrieve the public IP address by a compromised amnesia user with no user interaction added

#2 Updated by segfault about 1 month ago

  • Status changed from Confirmed to In Progress

#3 Updated by segfault about 1 month ago

I implemented both the hardcoded $DISPLAY variable and a countdown in the warning dialog until the "Launch" button becomes sensitive.

I'm attaching screenshots of the new warning dialog. I'm not sure if the red color of the "Launch" button is too much, I'm open to remove that.

@intrigeri, @sajolida: What do you think?

#4 Updated by intrigeri about 1 month ago

In #15635, it was reported that the Unsafe Browser's warning dialog can be hidden from the user by setting a different value for the $DISPLAY environment variable.

I don't understand this part: the way I understand it, a different $DISPLAY will not only prevent the warning dialog from showing up, but it'll also prevent the Unsafe Browser from starting and be usable for the class of attacks #15635 is about, no?

Here's what I tried:

amnesia@amnesia:~$ sudo DISPLAY=:69 unsafe-browser
Unable to init server: Could not connect: Connection refused

(zenity:7168): Gtk-WARNING **: 07:34:50.483: cannot open display: :69
amnesia@amnesia:~$ 

The PoC for #15635 indeed uses a different $DISPLAY, that's managed by Xvfb, so both the dialog and the Unsafe Browser are "displayed", just not where the user can see them.

If I missed something, could you please explain me what it is, and how one can tweak $DISPLAY in a way that hides the warning dialog without preventing the Unsafe Browser from being exploited?

Either way, as long as we're on X.Org, I think it would be sane secure programming practice that the code we run with elevated privileges (with sudo/pkexec) can't be hidden, by an adversary, on a new Xvfb-managed $DISPLAY. So this proposed change goes in the right direction IMO. I wonder if we could do better, e.g. by configuring sudo globally to always set $DISPLAY as we want it to be, instead of having to hard-code this value in a bunch of programs. How does this sound? We don't have to block on this: I'm happy to first merge code that addresses this problem only for the Unsafe Browser and follow-up on a new ticket for this other idea of mine.

We can also make sure that the dialog is not immediately closed programmatically (to prevent the user from seeing it), by adding making the "Launch" button insensitive for a few seconds.

Given this impacts UX negatively, with the aim to increase security, let's do a minimal analysis of what security gains we expect. If I got this right:

  • This mitigates the problem when the attacker has gained the capability to run arbitrary code as the amnesia user and uses it to programmatically use the Unsafe Browser (on the default $DISPLAY) to deanonymize the user. That is:
    • If the user is in front on the screen, with this change they will see the warning dialog for a few seconds. Else, they won't, so for example the attacker could wait for the user to be idle and bypass this new mitigation.
    • If the user is in front on the screen, regardless of this change, they will see the Unsafe Browser pop up and then (if the attack is not overly simplistic) disappear pretty quickly once the page that discloses the IP has loaded.
  • It delays by a few seconds the attack demonstrated on #15635: the exploit needs to wait for the timeout to expire before clicking through the warning dialog. But apart of that, that attack still works just fine.
  • This makes connecting to a captive portal a bit more painful. Arguably, given how long the Unsafe Browser takes to start, it could be acceptable if the security benefits are significant.

Correct?

Then, I'm wondering what I can do, as a user, if I see this dialog pop up while I did not intentionally start the Unsafe Browser. I have only a few seconds to react until the exploit clicks "Launch". Assuming I understand I'm under attack, my options are:

  • click "Cancel", but then the attack can be repeated, and perhaps eventually I won't click "Cancel" quickly enough
  • disconnect from the network as fast as I can, so that the attack can't succeed; but an attacker who can run arbitrary code as the amnesia user can reconnect to Wi-Fi
  • shut down the computer
  • anything else?

All in all, in the current state of my thinking, I'm not convinced that in practice, this extra delay will be sufficient, for the vast majority of our users, for them to realize what's going on and take appropriate measures to protect themselves. So I'm worried that we're making UX worse for every user who needs captive portals, while helping only very few users. But I'm of course open to discussing this further and to changing my mind :)

#5 Updated by intrigeri about 1 month ago

We can also make sure that the dialog is not immediately closed programmatically (to prevent the user from seeing it), by adding making the "Launch" button insensitive for a few seconds.

Gah, forgot to wrote what I had in the back of my mind: long-term, I believe GNOME Shell's polkit authentication agent would provide what we need here, that is requiring user interaction in a way that 1. the question can't be hidden by an attacker; 2. the attacker can't impersonate the user to answer the question. This mechanism is for example used by pkexec and by GNOME Disks' "Restore disk image" (to ask confirmation).

This is probably not option on X.Org: our test suite programmatically deals with polkit prompts with Sikuli.
But on Wayland, it could be exactly what we need to ensure the user sees the confirmation dialog and answers it themselves, no?

#6 Updated by segfault about 1 month ago

intrigeri wrote:

In #15635, it was reported that the Unsafe Browser's warning dialog can be hidden from the user by setting a different value for the $DISPLAY environment variable.

I don't understand this part: the way I understand it, a different $DISPLAY will not only prevent the warning dialog from showing up, but it'll also prevent the Unsafe Browser from starting and be usable for the class of attacks #15635 is about, no?

If a new screen is created and used, like it is in the PoC, then setting $DISPLAY to that screen will not prevent the Unsafe Browser from starting and it is usable for the class of attacks #15635 is about.

Here's what I tried:

[...]

The PoC for #15635 indeed uses a different $DISPLAY, that's managed by Xvfb, so both the dialog and the Unsafe Browser are "displayed", just not where the user can see them.

That's exactly what I meant. I don't see where I wrote that the dialog and the Unsafe Browser aren't displayed, I wrote that they are hidden from the user.

Either way, as long as we're on X.Org, I think it would be sane secure programming practice that the code we run with elevated privileges (with sudo/pkexec) can't be hidden, by an adversary, on a new Xvfb-managed $DISPLAY. So this proposed change goes in the right direction IMO. I wonder if we could do better, e.g. by configuring sudo globally to always set $DISPLAY as we want it to be, instead of having to hard-code this value in a bunch of programs. How does this sound? We don't have to block on this: I'm happy to first merge code that addresses this problem only for the Unsafe Browser and follow-up on a new ticket for this other idea of mine.

OK, then lets create a follow-up ticket for that.

We can also make sure that the dialog is not immediately closed programmatically (to prevent the user from seeing it), by adding making the "Launch" button insensitive for a few seconds.

Given this impacts UX negatively, with the aim to increase security, let's do a minimal analysis of what security gains we expect. If I got this right:

  • This mitigates the problem when the attacker has gained the capability to run arbitrary code as the amnesia user and uses it to programmatically use the Unsafe Browser (on the default $DISPLAY) to deanonymize the user. That is:
    • If the user is in front on the screen, with this change they will see the warning dialog for a few seconds. Else, they won't, so for example the attacker could wait for the user to be idle and bypass this new mitigation.
    • If the user is in front on the screen, regardless of this change, they will see the Unsafe Browser pop up and then (if the attack is not overly simplistic) disappear pretty quickly once the page that discloses the IP has loaded.

The difference is that without the timeout, both the dialog and the Unsafe Browser can be closed in a split second. Like I wrote in the commit message, the timeout is about increasing the chance that the user notices if the Unsafe Browser is started for malicious use.

  • It delays by a few seconds the attack demonstrated on #15635: the exploit needs to wait for the timeout to expire before clicking through the warning dialog. But apart of that, that attack still works just fine.
  • This makes connecting to a captive portal a bit more painful. Arguably, given how long the Unsafe Browser takes to start, it could be acceptable if the security benefits are significant.

Correct?

Then, I'm wondering what I can do, as a user, if I see this dialog pop up while I did not intentionally start the Unsafe Browser.
I have only a few seconds to react until the exploit clicks "Launch". Assuming I understand I'm under attack, my options are:

  • click "Cancel", but then the attack can be repeated, and perhaps eventually I won't click "Cancel" quickly enough
  • disconnect from the network as fast as I can, so that the attack can't succeed; but an attacker who can run arbitrary code as the amnesia user can reconnect to Wi-Fi
  • shut down the computer
  • anything else?

All in all, in the current state of my thinking, I'm not convinced that in practice, this extra delay will be sufficient, for the vast majority of our users, for them to realize what's going on and take appropriate measures to protect themselves. So I'm worried that we're making UX worse for every user who needs captive portals, while helping only very few users. But I'm of course open to discussing this further and to changing my mind :)

The purpose of the timeout is not to allow the user to prevent the attack, but to increase the chances that they at least notice that they are being attacked.

If you worry about the UX impact, we could also decrease the timeout. But please try it out first, I didn't have the impression that the timeout is very annoying. Maybe it's one second too long.


I just noticed that all this is probably completely ineffective, because an attacker could also just move the dialog and the Unsafe Browser to another workspace. On Tails we have two workspaces by default, so they wouldn't even have to create a new workspace for this.

#7 Updated by segfault about 1 month ago

intrigeri wrote:

We can also make sure that the dialog is not immediately closed programmatically (to prevent the user from seeing it), by adding making the "Launch" button insensitive for a few seconds.

Gah, forgot to wrote what I had in the back of my mind: long-term, I believe GNOME Shell's polkit authentication agent would provide what we need here, that is requiring user interaction in a way that 1. the question can't be hidden by an attacker; 2. the attacker can't impersonate the user to answer the question. This mechanism is for example used by pkexec

I also thought about using a GNOME Shell dialog. But I don't see why an attacker shouldn't be able to simulate mouse clicks there. And we can't add a timeout there, that's why I decided to go with a normal GTK dialog.

and by GNOME Disks' "Restore disk image" (to ask confirmation).

I don't see any GNOME Shell dialog when restoring a disk image via GNOME Disks.

This is probably not option on X.Org: our test suite programmatically deals with polkit prompts with Sikuli.
But on Wayland, it could be exactly what we need to ensure the user sees the confirmation dialog and answers it themselves, no?

I don't know whether Wayland effectively prevents simulation of mouse clicks / keyboard events.

#8 Updated by intrigeri about 1 month ago

segfault wrote:

intrigeri wrote:

The PoC for #15635 indeed uses a different $DISPLAY, that's managed by Xvfb, so both the dialog and the Unsafe Browser are "displayed", just not where the user can see them.

That's exactly what I meant. I don't see where I wrote that the dialog and the Unsafe Browser aren't displayed, I wrote that they are hidden from the user.

OK, I understand and I think we're now on the same page!

(For some reason, I was initially confused and interpreted "Make sure the user can see the Unsafe Browser's warning dialog" as "can see the warning dialog even if they don't see the Unsafe Browser itself", or something. Anyways :)

Either way, as long as we're on X.Org, I think it would be sane secure programming practice that the code we run with elevated privileges (with sudo/pkexec) can't be hidden, by an adversary, on a new Xvfb-managed $DISPLAY. So this proposed change goes in the right direction IMO. I wonder if we could do better, e.g. by configuring sudo globally to always set $DISPLAY as we want it to be, instead of having to hard-code this value in a bunch of programs. How does this sound? We don't have to block on this: I'm happy to first merge code that addresses this problem only for the Unsafe Browser and follow-up on a new ticket for this other idea of mine.

OK, then lets create a follow-up ticket for that.

I've created #17141 for it.

Given the freeze for 4.0~rc1 is tonight and this branch includes other stuff (#17135 + the added delay) that might not reach a conclusion in due time, should I review, test, and cherry-pick a9278fcba29b279ae916cf2dfcb705eba2f1f775 today? I guess I'll also need to update the test suite accordingly, unless you want to.

The purpose of the timeout is not to allow the user to prevent the attack, but to increase the chances that they at least notice that they are being attacked.

Ah, OK! Thanks for clarifying. (Previously, I did not realize that the branch history would have extra info I should read before replying here.)

I'll let sajolida assess UX impact (both the expected benefits and the potential regression).

#9 Updated by segfault about 1 month ago

intrigeri wrote:

segfault wrote:
Given the freeze for 4.0~rc1 is tonight and this branch includes other stuff (#17135 + the added delay) that might not reach a conclusion in due time, should I review, test, and cherry-pick a9278fcba29b279ae916cf2dfcb705eba2f1f775 today? I guess I'll also need to update the test suite accordingly, unless you want to.

If we can't prevent the window to be hidden by moving it to another workspace, lets not waste time on an ineffective mitigation.

I'll let sajolida assess UX impact (both the expected benefits and the potential regression).

Same here, lets not waste time on this.

#10 Updated by segfault about 1 month ago

segfault wrote:

I just noticed that all this is probably completely ineffective, because an attacker could also just move the dialog and the Unsafe Browser to another workspace. On Tails we have two workspaces by default, so they wouldn't even have to create a new workspace for this.

To prevent an attacker from hiding the windows on another workspace, a GNOME Shell dialog is the only solution I see. The polkit agent only allows to start password authentication dialogs. To use this, we would have to require a password to be set for the amnesia user. I don't have time right now to think through, will do that later.

#11 Updated by intrigeri about 1 month ago

First, sorry, it seems I'm reading/replying everything too fast today, missing important bits :(

To prevent an attacker from hiding the windows on another workspace, a GNOME Shell dialog is the only solution I see.

OK.

The polkit agent only allows to start password authentication dialogs.

Ah, crap, I thought there was a way to only request OK/Cancel style confirmation :/

#12 Updated by segfault about 1 month ago

  • Status changed from In Progress to Confirmed
  • Assignee deleted (segfault)
  • Target version deleted (Tails_4.0)

segfault wrote:

To prevent an attacker from hiding the windows on another workspace, a GNOME Shell dialog is the only solution I see. The polkit agent only allows to start password authentication dialogs. To use this, we would have to require a password to be set for the amnesia user. I don't have time right now to think through, will do that later.

I briefly thought about actually requring a password to start the Unsafe Browser. That would obviously also have a negative UX impact, because the user would have to reboot if they didn't set an admin password - so it wouldn't be much better UX-wise than to disable the Unsafe Browser by default and allowing to enable it in the Greeter (see #17085). But it would also be ineffective, because an attacker who is able to run code as amnesia could also log keystrokes and find out the admin password that way (at least on Xorg).

To use a GNOME Shell dialog which doesn't require a password, I suppose we would have to write our own GNOME Shell extension. I took a quick look at the implementation of the AuthenticationDialog in polkitAgent.js from the gnome-shell.git repo. It doesn't look too crazy, but I assume that it would still take me quite some time, because I'm still uncomfortable in the JavaScript world. And I'm not sure if it's worth the effort since (at least on Xorg) this would also not prevent the attack but only give the user a chance to notice the attack.

I'm unassigning myself here for now and will look at the other options to solve or mitigate #15635.

#13 Updated by intrigeri about 1 month ago

  • Feature Branch changed from bugfix/17134-make-sure-user-sees-unsafe-browser-warning to wip/bugfix/17134-make-sure-user-sees-unsafe-browser-warning

#14 Updated by cypherpunks 16 days ago

Unfortunately, an attacker will have access to the X11 protocol, so hardcoding the DISPLAY variable will not help. An attacker will be able to hide the dialog box, cover it, or simulate clicking it. Hardcoding the variable does not matter since both the Unsafe Browser and the attacker have access to the same X11 cookie.

This provides no security at all due to Xorg's lack of window isolation.

#15 Updated by cypherpunks 16 days ago

segfault wrote:

intrigeri wrote:

segfault wrote:
Given the freeze for 4.0~rc1 is tonight and this branch includes other stuff (#17135 + the added delay) that might not reach a conclusion in due time, should I review, test, and cherry-pick a9278fcba29b279ae916cf2dfcb705eba2f1f775 today? I guess I'll also need to update the test suite accordingly, unless you want to.

If we can't prevent the window to be hidden by moving it to another workspace, lets not waste time on an ineffective mitigation.

I'll let sajolida assess UX impact (both the expected benefits and the potential regression).

Same here, lets not waste time on this.

The window can be made invisible; an attacker doesn't need to move it to another workspace. Remember that the concept of "workspaces" is implemented by the window manager, which itself has the same access to Xorg as any other running process (including an attacker's). There are no situations in which a window manager, using the X11 protocol, can override an attacker when connected to the same Xorg instance.

#16 Updated by sajolida 9 days ago

But it would also be ineffective, because an attacker who is able to run code as amnesia could also log keystrokes and find out the admin password that way (at least on Xorg).

Does this mean that an attacker that can do the deanonymization attack, could also still the admin password? If so, then setting an admin password could equally lead to deanonymization. root can deanonymize you, and if you set an admin password, it's because you'll type it at some point, and then it could be stolen (if I understand correctly).

Also available in: Atom PDF