Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

vm-existence confirmation attacks #2436

Closed
jpouellet opened this issue Nov 14, 2016 · 21 comments
Closed

vm-existence confirmation attacks #2436

jpouellet opened this issue Nov 14, 2016 · 21 comments
Labels
C: core privacy This issue pertains to data or information privacy through technological means.

Comments

@jpouellet
Copy link
Contributor

jpouellet commented Nov 14, 2016

It would be nice to try to prevent whonix-ws from confirming the existence of ${workplace_name}-vault (or similar).

qrexec currently leaks such information in various ways, for example:

AppVM$ time /usr/lib/qubes/qrexec-client-vm sys-net qubes.VMShell
Request refused
/usr/lib/qubes/qrexec-client-vm sys-net qubes.VMShell  0.00s user
0.00s system 1% cpu 0.180 total
AppVM$ time /usr/lib/qubes/qrexec-client-vm does-not-exist qubes.VMShell
Request refused
/usr/lib/qubes/qrexec-client-vm does-not-exist qubes.VMShell  0.00s
user 0.00s system 0% cpu 1.565 total

In this case the difference in time is quite obvious because it blocks while an error dialog is open in dom0, but there are many other more subtle side channels dependent on individual qrexec policies.

I think to solve this correctly it would need to be handled in a generic way by qrexec, independent of policy config. The path forward is to try to identify and normalize the qrexec-client-visible differences between rpc requests to VMs that don't exist vs ones that are unauthorized.

EDIT:

Note that we should revisit the issue of vm-existence leakage when privacy-tagged whonix VMs become reality, and consider possibly some substitution of QREXEC_REMOTE_DOMAIN with a random unique-per-vm value.

@jpouellet jpouellet changed the title vm-existance confirmation attacks vm-existence confirmation attacks Nov 14, 2016
@marmarek
Copy link
Member

This is hard to do for one another case: when qrexec policy set to 'ask'.
In case of existing VM, user get a prompt. If the VM does not exist,
the request is denied immediately. This can't be fixed the same way as
for qubes.VMShell (not blocking while waiting error dialog to be
closed).

Some (IMO very bad) solution would be always showing some message - also
when VM exists but request is denied. But this would greatly degrade
user experience. We want to get rid of those prompts where possible, not
adding more of them.

For the case of whonix-ws (after fixing blocking error dialog), maybe
good thing to do is to explicitly isolate it from other VMs, by placing
'deny' action even when default is to 'ask'? Especially when the target
is some sensitive VM. Personally I have very similar configuration on my
system - almost all services have 'deny' action when the target is
keys-something, vault or such.

@adrelanos any opinion?

Best Regards,
Marek Marczykowski-Górecki
Invisible Things Lab
A: Because it messes up the order in which people normally read text.
Q: Why is top-posting such a bad thing?

@jpouellet
Copy link
Contributor Author

One (perhaps less bad) idea is to keep track of which VMs have ever successfully made any RPC request to which other VMs (a "previously-authorized" graph), and each time a new edge is requested, immediately return an error in a non-blocking way as if the VM did not exist, and pop a "should vm X be able to know about about vm Y?" [Yes], [Not now], [Never]).

Requests to non-existent VMs right now currently pop an error in dom0:
qrexec-no-such-domain
and the request does not terminate until the dialog is closed. Making it fail immediately, combined with the above immediate-fail and asynchronous-enable-future-requests described above sounds to me like one possible good direction.

Thoughts?

@andrewdavidwong andrewdavidwong added C: core enhancement privacy This issue pertains to data or information privacy through technological means. labels Nov 15, 2016
@andrewdavidwong
Copy link
Member

each time a new edge is requested, immediately return an error in a non-blocking way as if the VM did not exist, and pop a "should vm X be able to know about about vm Y?" [Yes], [Not now], [Never]

That's a clever solution. The downside is, of course, that it generates additional prompts for the user, and as @marmarek pointed out, we want to reduce them, not add more. On the other hand, these prompts would occur only once for each pair of VMs, so perhaps the benefits are worth the cost? I don't know.

@andrewdavidwong
Copy link
Member

The more I think about it, the more I think it should be a combination of @marmarek's and @jpouellet's proposals: Create an a new "permission to know about existence" prompt, but only for Whonix VMs. Why? Because only Whonix VMs come with any guarantee of privacy in the first place. There are a thousand other side-channels that compromise the privacy of non-Whonix VMs, and our standard reply to all of those (for now, anyway) is: "If privacy is a concern, use a Whonix VM."

@jpouellet
Copy link
Contributor Author

I don't like the idea of special-casing dom0 policy a particular VM type. How do we even detect a whonix vm? By name? By name of proxyvm? By name of template of proxyvm? What if a user wants to change this? Do they suddenly lose guarantees that they don't know were being provided in the first place?

If you really want to make a distinction between "can be known" and "can not be known", then let the user decide that with a configuration option or something. I'd say don't tie it to whonix. Perhaps I have some vault VM where I keep secret offline documents, and this vm is named something guessable and indicative of the contents of the documents. Sure, this is bad practice, but now we need to increase user education? I just don't think this is the right path forward. One dialog per edge seems like a small price to pay to me.

@jpouellet
Copy link
Contributor Author

In practice, I have ~40 VMs already, and only ~10 or so edges. Note that 10 << 40**2.

However, I also often copy things from a DispVM back to the thing that launched that DispVM, so perhaps we wish to pre-authorize that case?

@marmarek
Copy link
Member

The usability problem with your approach is it will fail the first
request, by design. This may not be a big problem for advanced users,
but surely will be for beginners. Or when we ever come back to LiveCD
edition.

I think better approach would be to configure it specifically for Whonix
VMs - either using salt, or using some VM tag (#865). So the policy
would look like this:

# some explicit allow/ask rules here
$tag:privacy $anyvm deny
$anyvm $anyvm ask

Then, whonix VMs would have set tag 'privacy' set - for example by
inheriting it from template or similar mechanism. I think very similar
mechanism could also be used to point DispVM parent VM.

This of course is possible only in Qubes 4.0.

Best Regards,
Marek Marczykowski-Górecki
Invisible Things Lab
A: Because it messes up the order in which people normally read text.
Q: Why is top-posting such a bad thing?

@jpouellet
Copy link
Contributor Author

jpouellet commented Nov 15, 2016

I think having a privacy tag would be useful in general, but if the problem here is usability, then a privacy tag does not solve the problem.

The usability problem with your approach is it will fail the first request, by design.

This is true. I agree that this is undesired. I believe there is a way around this involving adding a blocking error dialog in the event of a deny match (which should not happen under normal circumstances, and an argument can be made in favor of wanting the user to know that either to warn them of attack or simply report a bug), but I need to more carefully enumerate and think through all cases before I am sure, and am definitely too tired to do so confidently at the moment.

Still, this does not sound like the ideal solution.


More radical proposal:

In the case of copy/paste, and both source and destination are indicated to dom0 in a secure manner by which windows receive the copy/paste shortcuts, which is a direct path from user to dom0 without any opportunity for AppVM interference, and therefore (obviously) requires no confirmation dialog. (Ignoring focus stealing attacks for the sake of argument.)

One thing I always found kind of odd was that other operations (file copy, etc) do not share the same secure user->dom0 path for target/destination vm indication.

For any inter-vm operation, at some point the user needs to choose which vm it will come from and which vm it will go to. Doing so in an AppVM is inherently insecure, and this is why we have the dom0 "confirm" dialog in the first place. If instead, we move the target selection to dom0, then:

  1. we eliminate the need for confirmation dialogues altogether! (@andrewdavidwong)
  2. "pick a vm" (AppVM) and "yes" (dom0) becomes "pick a vm" (dom0)
  3. "no" becomes cancel
  4. "yes to all" becomes somehow analogous to "target= for all", although the desired semantics here require more thought
  5. we happen to solve this issue as a side-effect because a source vm does not need to know the target vm (and indeed it currently can not depend on the value it requests being reality anyway due to possibility of target= in policy)

I believe this proposal would still be an improvement outside the context of this issue.

tl;dr - have appvm say "i want to do this operation to some target", and dom0 specify "ok, this target"

Thoughts? (perhaps this type of proposal belongs on the mailing list instead?)

@rustybird
Copy link

rustybird commented Nov 15, 2016

Maybe a short-term 95% solution could consist of a combination of a) tweaking the general qrexec-policy algorithm and b) documenting a warning against certain policy definitions.

a)

if targetvm does not exist
    if targetvm would have matched Ask policy
        pop up usual confirmation dialog
        wait for user to select an action, but ignore it
    respond indistinguishable to Deny

b)

(Relevant for #2280)
"Don't use the following policy definition if you want to keep the existence of any of your VMs private:

$anyvm $anyvm allow

"Don't use either of the following policy definitions if you want to keep the existence of secret-vm private:

$anyvm secret-vm deny
$anyvm $anyvm    ask
----------------------
$anyvm secret-vm ask
$anyvm $anyvm    deny

@jpouellet:

More radical proposal: [...]
I believe this proposal would still be an improvement outside the context of this issue.

Indeed. There's a ticket somewhere about somehow asking for the destination VM name in a dom0 popup for enhanced UX and privacy, but I can't find it...

@andrewdavidwong
Copy link
Member

@rustybird:

Indeed. There's a ticket somewhere about somehow asking for the destination VM name in a dom0 popup for enhanced UX and privacy, but I can't find it...

#910?

@rustybird
Copy link

@andrewdavidwong: That's it, thanks.

Generalizing the copy-and-paste workflow as @jpouellet suggested sounds like it could be an amazingly fruitful approach. I'm thinking along the lines of:

  • User invokes an RPC service without specifying a destination VM, e.g. just qvm-copy-to-vm somefile
  • User presses uninterceptable dom0 qrexec keyboard shortcut (which would replace Ctrl-Shift-C)
  • dom0 notification: Selected <srcvm> as the source for qubes.Filecopy (with a human-readable description of what the service does)
  • Application menu and/or window manager temporarily offer new menu item Select as destination for qubes.Filecopy from <srcvm>

In one swoop, this would get rid of:

  • Very different UX for copy-and-paste vs. qrexec invocation
  • VM existence confirmation and brute force VM enumeration attacks
  • Having to manually type the complete destination VM name
  • Potentially, having to disclose the destination VM name to the source VM
  • The whole confirmation dialog with all its focus stealing issues

@marmarek
Copy link
Member

That would be indeed good idea @jpouellet. I think the only missing part
in Qubes 4.0 right now, it to specify in policy that explicit target is
forbidden. And implementation of target VM prompt (GUI part). Do you
want to propose some syntax, consistent the current syntax?

Best Regards,
Marek Marczykowski-Górecki
Invisible Things Lab
A: Because it messes up the order in which people normally read text.
Q: Why is top-posting such a bad thing?

@jpouellet
Copy link
Contributor Author

@rustybird Can you elaborate on how you suggest copy/paste might change?

I was not going to touch the copy/paste workflow at all, rather I just brought it up as an example of securely identifying VMs.

In one swoop, this would get rid of:

  • Very different UX for copy-and-paste vs. qrexec invocation

I do not see this as a problem. I view them as different actions. Why do you think they should be unified?

  • The whole confirmation dialog with all its focus stealing issues

IMO focus stealing is really a separate issue entirely which warrants its own solution, but regardless, I do not believe need a trusted keyboard shortcut to achieve focus-stealing attack mitigation in this particular case. Forcing the user to choose a VM (from dropdown, autocompleting text-field, etc.) in a way where any human-queued muscle memory input actions do not have an effect on the dialog just popped appears to me to be sufficient. Furthermore, not requiring a keyboard shortcut if not necessary seems like a better UX.

@jpouellet
Copy link
Contributor Author

jpouellet commented Nov 15, 2016

@marmarek wrote:

Do you want to propose some syntax, consistent the current syntax?

Syntax for what exactly? I (perhaps naively) don't see any required changes.

If you mean for explicit target being forbidden, I don't see why this could not simply interpret $anyvm my-vm deny to mean "don't show user my-vm in list of possible targets"? (perhaps a reasonable default for dom0?) Perhaps there is some problem that has not occurred to me here.

If you mean syntax for qrexec-client-vm, qvm-copy-to-vm, qvm-move-to-vm, qvm-open-in-vm, etc., then I suggest we just drop the vmname positional parameter (or more likely: keep it for backwards compat, but ignore it, and possibly deprecate qvm-move-to-vm in favor of qvm-move without a vmname arg). However, I do not feel very strongly about this and definitely defer to a better suggestion.

@jpouellet
Copy link
Contributor Author

jpouellet commented Nov 15, 2016

Note that we should revisit the issue of vm-existence leakage when privacy-tagged whonix VMs become reality, and consider possibly some substitution of QREXEC_REMOTE_DOMAIN with a random unique-per-vm value.

Except for QREXEC_REMOTE_DOMAIN, I now see this issue as effectively a duplicate of #910.

@rustybird
Copy link

@jpouellet:

I was not going to touch the copy/paste workflow at all, rather I just brought it up as an example of securely identifying VMs.

Well, I kind of liked the general direction so much that I jumped straight ahead to an even more extreme version :), where copy-and-paste would be just a regular qrexec service. This still seems to me like it could somehow simplify the concept and implementation, but I see that I haven't thought it through enough yet. In particular the hypothetical "qrexec keyboard shortcut" couldn't really replace Ctrl-Shift-C in this case. Sorry for derailing!

@marmarek
Copy link
Member

@rustybird Well, copy-and-paste is implemented as qrexec service ;) for HVM domains. But policy is evaluated for all the cases. With one specific difference: pressing Ctrl-Shift-V is assumed to confirm the call, even if policy says 'ask'. If you call qubes.ClipboardPaste service manually, you'll still get prompt dialog. 'deny' action is respected in all the cases.

@jpouellet not sure what to do with QREXEC_REMOTE_DOMAIN. Generally it is important in many cases. For example in file copy, you place files in directory named after source domain. This require being something easy for user (human) to parse. Random, unique, per-vm value is not...
I think if you don't want to disclose source domain to some (Whonix?) VM, you shouldn't copy files there. After all many files formats will leak hostname anyway ("last edited on ..."). And perhaps use more generic VM names - instead of "secret-project-xyz", use "work-project2" and have VM description (#899) for more details.

For other cases, moving discussion to #910.

@jpouellet
Copy link
Contributor Author

@marmarek Yeah, makes sense.

I was not aware of #910 when I opened this. Closing now as everything is handled by other tickets.

Thanks for all the feedback :)

@adrelanos
Copy link
Member

@marmarek:

For the case of whonix-ws (after fixing blocking error dialog), maybe good thing to do is to explicitly isolate it from other VMs, by placing 'deny' action even when default is to 'ask'?

That sounds confusing. Imagine a user who has set it to ask but then when trying it does not actually ask. Seems like a bug to the user.


Perhaps another option. What if VM does not exist or request is denied by policy, have qrexec wait a random amount of seconds to make it always looks like the user manually denied it? [That feature with the ability to opt-out. Opt-in by default.]

@marmarek
Copy link
Member

On Thu, Nov 17, 2016 at 09:21:17AM -0800, Patrick Schleizer wrote:

@marmarek:

For the case of whonix-ws (after fixing blocking error dialog), maybe good thing to do is to explicitly isolate it from other VMs, by placing 'deny' action even when default is to 'ask'?

That sounds confusing. Imagine a user who has set it to ask but then when trying it does not actually ask. Seems like a bug to the user.

I'm not proposing some magic, hidden option. I'm proposing changing
default policy to have explicit "$tag:privacy $anyvm deny" as the first
line, before "$anyvm $anyvm ask".

Perhaps another option. What if VM does not exist or request is denied by policy, have qrexec wait a random amount of seconds to make it always looks like the user manually denied it? [That feature with the ability to opt-out. Opt-in by default.]

I don't think it will help much. Compromised VM can try to guess when
user is really away and then perform tries - those with random delay
will still return much earlier than those waiting for user (coming back
with a coffee).

Best Regards,
Marek Marczykowski-Górecki
Invisible Things Lab
A: Because it messes up the order in which people normally read text.
Q: Why is top-posting such a bad thing?

@adrelanos
Copy link
Member

Marek Marczykowski-Górecki:

I'm not proposing some magic, hidden option. I'm proposing changing
default policy to have explicit "$tag:privacy $anyvm deny" as the first
line, before "$anyvm $anyvm ask".

Sounds good. I however see a usability issue. Would be hard then to copy
out data from privacy VMs to other VMs. There can be legitimate reasons
such as copying to non-networked vault VM. Users would try and it would
fail silently while that works for other VMs, which seems like a bug to
the user.

That can be solved. In case of deny, perhaps show a one time popup.
Something like this.

VM X tried Y. Request was refused. See link to documentation of this
subject.

[ ] Do not show this popup again.

OK

Alternatively there could be a one time passive popup notification.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C: core privacy This issue pertains to data or information privacy through technological means.
Projects
None yet
Development

No branches or pull requests

5 participants