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

Leaky qrexec env variables #3345

Closed
newchain opened this Issue Nov 28, 2017 · 3 comments

Comments

Projects
None yet
3 participants
@newchain

Qubes OS version:

R3.2

Affected TemplateVMs:

whonix-gw (but presumably all)


Steps to reproduce the behavior:

Configure service policy in dom0 to redirect to a domain.

Create service that unsets or readonly's and then exports QREXEC_SERVICE_ARGUMENT (and QREXEC_REMOTE_DOMAIN) before launching processes.

Expected behavior:

For services redirected in dom0 and targeted in the 'client' domain to itself, QREXEC_REMOTE_DOMAIN is not leaked to the 'server' domain at all.

Environment variables that are passed to the 'server' but are then either unset or readonly-overwritten by the service script are either not present in launched processes' environment or replaced with the overwritten values. i.e. these values are inherited by processes launched in the service script from the service script.

Actual behavior:

For redirected services, QREXEC_REMOTE_DOMAIN is leaked to the 'server' domain

Even when QREXEC_SERVICE_ARGUMENT (and QREXEC_REMOTE_DOMAIN) is unset or overwritten read-only in the service script before a processes is launched is set in the process's environment.

General notes:

I have mostly replaced IP in my template (Gentoo) and sys-whonix using socat chains and qrexec with the aim of removing IP from the kernels of all domains behind one locked down proxy in front of sys-whonix that acts as its ip. The final three problems are: that control-port-filter-python does not work on tunneled unix sockets, for which I would appreciate @adrelanos's help, though socket_wrapper looks promising as a workaround; the second is that I do not have the knowledge necessary to adjust sys-whonix's firewall for a separate domain (which only @adrelanos could do safely); and the third, which is the problem I am reporting, is that nomatter how many times I try to hide QREXEC* from anything launched from my service in the 'server' domain, they end up in every process's environment.

At the moment I'm hashing a secret that lasts as long as the service in the 'client' and sending the hash and an indication of when the client's session is over as QREXEC_SERVICE_ARGUMENT. The service has a temporary list of mapped hashes to sockets that are configured by Tor. When the service is called without "-shutdown" in QREXEC_SERVICE_ARGUMENT, it checks first whether the list exists. If it doesn't, it generates a secret and records it. It then hashes that secret with the hash sent by the client. It unsets QREXEC_SERVICE_ARGUMENT (and QREXEC_REMOTE_DOMAIN) and randomly selects an available socket, then records hash(hash+secret) in the mapping.
When the hash is not in that mapping, a new "session" is created by creating a secret, hashing QREXEC_SERVICE_ARGUMENT with that secret, and recording both the secret and hash(hash+secret) in the list. If the list already exists, the secret is read and the mapping derived from hash(hash+secret). With -shutdown, the mapping is removed. If it's the last mapping, the secret is removed too.

Thus, anything without ptrace of qubes-rpc-multiplexer or the service script should not be able to learn the true mapping. The client service is protected with SELinux and grsecurity RBAC, while the server is protected with AppArmor, setcaps and unshare. Both have hidepid=2. Most of /proc and all of /sys are hidden in the client, but not the 'server' as AppArmor does not provide for hiding objects.

When moving to add openssl to the socat chain so as to both gain zero knowledge passwords and protect Xen from malicious fuzzing or magic sequences, I discovered that my current scheme was a little useless due to sys-whonix learning QREXEC_REMOTE_DOMAIN and further completely useless as socat learns both QREXEC_SERVICE_ARGUMENT and QREXEC_REMOTE_DOMAIN.

I would be very grateful if you could fix this for R3.2 as I will not have the time to either migrate or port to R4.0 for several months.


Related issues:

Generally, a great deal of information is non-optionally leaked about the system through qubesdb and qrexec. It would be nice if this could be configured with per-domain or per-template configuration to either: not send; spoof with specific values; or randomly select between commonly seen sets of values.

@newchain

This comment has been minimized.

Show comment
Hide comment
@newchain

newchain Nov 28, 2017

sorry for not previewing the submission thoroughly enough. Where there's a repetition I meant to say that if hash(hash+secret) is found, socat tunnels to the socket mapped to it in the list.

sorry for not previewing the submission thoroughly enough. Where there's a repetition I meant to say that if hash(hash+secret) is found, socat tunnels to the socket mapped to it in the list.

@newchain

This comment has been minimized.

Show comment
Hide comment
@newchain

newchain Dec 16, 2017

Sorry again for the noise - there is no issue with rcp-multiplexer 'remembering' unset environment. It was simply an error on my part. The other issue (with QREXEC_REMOTE_DOMAIN) remains, however.

Sorry again for the noise - there is no issue with rcp-multiplexer 'remembering' unset environment. It was simply an error on my part. The other issue (with QREXEC_REMOTE_DOMAIN) remains, however.

@marmarek

This comment has been minimized.

Show comment
Hide comment
@marmarek

marmarek Dec 17, 2017

Member

This is design choice that target domain get unspoofable information about source domain name (it is send by dom0, not by source domain). It is not a bug. See https://www.qubes-os.org/doc/qrexec3/#qubes-rpc-administration

But even if we add a feature to not send this information directly, it is still possible to get at list Xen domain ID of the other end of connection (by inspecting internal structures of qrexec-agent). This information is needed to establish the connection, so we can't avoid it.
So, this would be only slightly better than just unsetting QREXEC_REMOTE_DOMAIN in your service script to avoid its propagation.
If you want to completely hide source information from sys-whonix, create intermediate domain (VM1 -> VM2 -> sys-whonix), which would passthrough all connections to your service to sys-whonix.

Member

marmarek commented Dec 17, 2017

This is design choice that target domain get unspoofable information about source domain name (it is send by dom0, not by source domain). It is not a bug. See https://www.qubes-os.org/doc/qrexec3/#qubes-rpc-administration

But even if we add a feature to not send this information directly, it is still possible to get at list Xen domain ID of the other end of connection (by inspecting internal structures of qrexec-agent). This information is needed to establish the connection, so we can't avoid it.
So, this would be only slightly better than just unsetting QREXEC_REMOTE_DOMAIN in your service script to avoid its propagation.
If you want to completely hide source information from sys-whonix, create intermediate domain (VM1 -> VM2 -> sys-whonix), which would passthrough all connections to your service to sys-whonix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment