Linux privileged vpndaemon wrongly and incompletely implements Polkit authentication; potential information Leaks
Categories
(Mozilla VPN :: Client for Linux, defect)
Tracking
(Not tracked)
People
(Reporter: freddy, Assigned: nkirby)
References
Details
(Whiteboard: [external reporter][suggested disclosure date 2023-08-02 or earlier])
Attachments
(1 file, 1 obsolete file)
352 bytes,
text/plain
|
Details |
Hello Mozilla security,
I am a member of the SUSE security team. An openSUSE user wants to
package Mozilla VPN for openSUSE Tumbleweed. For this a review of the
D-Bus service and Polkit authentication contained in Mozilla VPN is
required.A colleague and I reviewed the Mozilla VPN codebase for release 2.14.1
and we believe to have found local security issues in the D-Bus daemon
implementation. Please find the details below.Coordinated Disclosure Process
The SUSE security team offers coordinated disclosure according to the
openSUSE disclosure policy 1. We can keep the issue(s) private for up
to 90 days, but recommend shorter embargo periods of 14 days. As of
today the latest publication date will be 2023-08-02.Please inform us whether you can confirm the security issues in this
report, whether you want to follow coordinated disclosure and what your
desired publication date is. The alternative to coorindated disclosure
is to make the issues public right away.Broken Polkit Authentication Check
The code for the privileged component in Mozilla VPN on Linux is mostly
found in mozillavpn-2.14.1/src/apps/vpn/platforms/linux. The D-Bus
method callbacks are found insrc/apps/vpn/platforms/linux/daemon/dbusservice.cpp.
Mozilla VPN ships a Polkit policy with the following content:
<action id="org.mozilla.vpn.activate"> <description>Activate the Mozilla VPN</description> <message>Activate the Mozilla VPN</message> <defaults> <allow_inactive>no</allow_inactive> <allow_active>auth_admin</allow_active> </defaults> </action> <action id="org.mozilla.vpn.deactivate"> <description>Deactivate the Mozilla VPN</description> <message>Deactivate the Mozilla VPN</message> <defaults> <allow_inactive>no</allow_inactive> <allow_active>auth_admin</allow_active> </defaults> </action>
Of these two privileged actions, the polkit authorization check is only
performed in theactivate
D-Bus method, while no such check is present
at all in thedeactive
method.For the activate D-Bus method the Polkit check is implemented in
PolkitHelper::checkAuthorization() in
src/apps/vpn/platforms/linux/daemon/polkithelper.cpp line 58:h.m_subject = polkit_unix_process_new_for_owner(getpid(), 0, -1);
The UNIX process Polkit subject is deprecated and shouldn't be used
anymore, because it is by design affected by race conditions. Instead
the D-Bus sender subject should be used, which is based on the UNIX
domain socket used by D-Bus to identify the credentials of the client
via the Linux kernel.Even worse, the UNIX process polkit subject is initialized here using
getpid()
as the process ID and-1
for the user ID, The latter asks
Polkit to determine the given PID's user ID by looking into /proc.
Basically this asks Polkit to check whether the privileged Mozilla VPN
D-Bus service itself is authorized to perform the action. Since The
Mozilla VPN D-Bus service runs as root, this will always be true.This can be verified from the command line using a minimal pseudo
configuration like this:nobody$ gdbus call -y -d org.mozilla.vpn.dbus -o / -m org.mozilla.vpn.dbus.activate \ '{"privateKey": "stuff", "serverPublicKey": "stuff", "serverPort": 1234, "deviceIpv4Address": "127.0.0.2", "serverIpv4AddrIn": "127.0.0.3", "allowedIPAddressRanges": []}'
This D-Bus call will work without any authentication, even if a fully
unprivileged user account likenobody
runs it.The impact is that arbitrary local users can configure arbitrary VPN
setups using Mozilla VPN and thus possibly redirect network traffic to
malicious parties, pretend that a secure VPN is present while it
actually isn't, perform a DoS against an existing VPN connection or
other integrity violations.Since the linux daemon does not perform any file system operations or
otherwise dangerous operations besides of the network setup I don't see
a possibility to escalate privileges using this attack vector.Missing Polkit Authentication Checks
Apart from the fact that the existing Polkit authentication check is
wrong, there isn't even an attempt to secure any of the other D-Bus
methods offered by the Mozilla VPN D-Bus service.For the following methods Polkit authorization checks should be
considered, or their scope should be limited by other means:
getLogs(): returns potentially problematic world-readable log data, even
debug logs, e.g. also about other users' activities in the system. The
same data is publically available in /var/log/mozillavpn.txt. These
logs allow tracking of what applications other users start, for
example.Log data of system services should generally not be world readable, so
this item refers to both, the D-Bus API and the logfile in /var/log.
This is an information leak (especially since there is also debug data
found here) that might facilitate other security issues or might allow
other users in the system to deduce what a Mozilla VPN user is doing.cleanupLogs(): allows everybody to clear the current logs. This should
be restricted to authorized users, otherwise it might be used to clear
traces of attacks etc.runningApps(): this leaks information from other users'
sessions and their apps to everybody in the system. Most of this data
is probably also available viaps
or /proc, respectively. Some
hardened systems may not allow this, though. A solution might be to
only return data here that belongs to the user making the request on
D-Bus.firewallApp(): allows to put arbitrary appIDs into split tunneling /
exclude, even for other users. This should be restricted to
applications of the requesting D-Bus user.firewallClear(): clears the exclude list. should also be restricted to
entries affecting the calling user.deactivate(): everybody may shutdown the whole VPN. There is a
deactivate() Polkit action declared but is is never used.From looking at the D-Bus implementation it is apparent that Mozilla VPN
on Linux doesn't really have a proper multi user concept. A simple way
out of this may be to store the UID of the user that successfully
authenticates during activate() and then only allow the other D-Bus
methods for the same user until deactivate() is called. Mixing
different user contexts would be avoided this way.Privilege Drop Considerations
As far as I see the Mozilla VPN linux daemon only uses its higher
privileges for two things:
- setting up the network
- monitoring user sessions and attaching to their D-Bus session busses
to keep track of running applications ("AppTracker" class).It could be considered running this service not as root but only with
the CAP_NET_ADMIN capability. This would limit the potential attack
surface considerably. I'm not sure how well this idea plays with the
monitoring aspects, but it is a direction that could be investigated to
harden this D-Bus service. Also dropping privileged to an unauthorized
user and only raising them on a case-by-case basic e.g. when connecting
to other users' session busses might be a way to go.CVE assignments
The invalid Polkit Authentication check and the unauthenticated
decativate() D-Bus method deserve CVE assignments. Please inform us
whether you will assign CVEs on your end. I understand that you are a
CVE CNA so this would fall into your responsibility.The other missing authentication checks and possible information leaks
are a bit of a gray area and will not necessarily need CVEs from my
point of view.Cheers
Matthias
Reporter | ||
Comment 1•2 years ago
|
||
While the team is developing a plan and gathering the necessary patches to address these issues, let me answer the last question about CVE assignments: Yes, Mozilla is a a CNA and we generally issue CVE IDs once a bug has been resolved (in order to make sure that we fully appreciate the issue when we submit this).
Reporter | ||
Updated•2 years ago
|
Comment 2•2 years ago
|
||
Can you meanwhile confirm the outlined security problems?
It seems you want to follow coordinated disclosure. Do you have a desired publication date yet?
Comment 3•2 years ago
|
||
We are still missing any formal recognition of the report and any details about the disclosure process. Please provide that.
If there is no progress in communicating these details then we will consider disclosing the report to the public in 14 days on 2023-06-14.
Assignee | ||
Comment 4•2 years ago
|
||
We are are beginning to look into this issue, and we are hoping to have a mitigation in place for the 2.16 release. I do not yet have a date on when this release will happen.
My initial thoughts are that we should be able to eliminate the use of polkit entirely and the network interface management should be feasible with only the CAP_NET_ADMIN permission. I am unsure on the best approach for dealing with the AppTracker and whether we can continue to support split tunnelling if we drop root permissions in the daemon, but I agree that some additional hardening is a good idea for this component.
Comment 5•2 years ago
|
||
Thanks for the update. Please bear in mind that our maximum embargo period according to our disclosure policy is until 2023-08-02.
Updated•2 years ago
|
Updated•2 years ago
|
Comment 6•2 years ago
|
||
I'm sorry to tell you that our community packager, that triggered the review of this component, and thus shared the knowledge about this issue, just violated the embargo by creating this public pull request:
https://github.com/mozilla-mobile/mozilla-vpn-client/pull/7151
Maybe you can try to remove this information for GitHub again (is this even possible?). Otherwise I don't really know how to continue from here. The PR# is no full information leak but it's still not ideal.
Reporter | ||
Comment 7•2 years ago
|
||
While the cat is out of the bag, we should discuss our options. If this was a simple patch, we should probably just take it.
Given this is a non-trivial patch, we're going to take some time to review and decide.
I've nudged the development team to see if they can give this priority, but further information TBD.
Thanks for the heads up!
Comment 8•2 years ago
|
||
Thanks for the heads up here. As far as I know it's not possible to meaningfully remove the PR from GitHub. Naomi, the engineer assigned to this bug, and who is best suited to review this patch, is on PTO until tomorrow. We've added another reviewer to the PR in the meantime.
Comment 9•2 years ago
|
||
It seems our community packager was inspired by another PR# that also talked openly about the problem here:
https://github.com/mozilla-mobile/mozilla-vpn-client/pull/7055
I don't know if that was discovered independently or if it is related to our report.
Please let us now you further plans once you've come to a decision.
Comment 10•2 years ago
|
||
Adding a colleague from my team as backup since I will be unavailable for a while after this week.
Updated•2 years ago
|
Comment 11•2 years ago
|
||
The maximum embargo time we offer will be reached tomorrow on August 2nd. Although parts of the issue already leaked via the GitHub PRs anyway. I will be publishing my formal report after this date.
You still did not answer any of the questions about the disclosure process. There is no CVE visible. There is no update here on the supposed patch - it seems from the Pull request #7710 that the use of Polkit has been removed. Do you have anything to add for the publishing of the formal report? Especially about the following topics:
- which version(s) will receive a fix?
- will there be a CVE assignment?
- what is the impact analysis on your end?
Thanks
Matthias
Comment 12•2 years ago
|
||
Hello Lesley,
Can you please check the questions in the above comment?
Thanks,
Frida
Assignee | ||
Comment 13•2 years ago
|
||
We wound up fixing this issue in two parts, the first PR (https://github.com/mozilla-mobile/mozilla-vpn-client/pull/7055) removed the buggy use of polkit, which should close off any potential privilege escalation issues that could have manifested from polkit. However this PR on its own effectively changes nothing in the VPN behaviour, and it still permits any logged in user to control the VPN tunnel. This change will be included in the v2.16.0 release whenever that goes live (currently in QA and release testing as of today).
The follow-up PR (https://github.com/mozilla-mobile/mozilla-vpn-client/pull/7110) attempts to introduce better authorization controls on the D-Bus API by requiring the caller to possess CAP_NET_ADMIN permission, or matching the UID of the user who activated the connection. This lets any user activate the VPN, but once active only that user (or root) can control the VPN. This patch did not land in time for the 2.16.0 merge window, so we anticipate it will go live in the 2.17.0 release. There is no date for the 2.17 release yet, but our typical cadence should see it go live in 1-2 months time.
Comment 14•2 years ago
|
||
Thanks for the update. This still leaves the question of a CVE assignment, what are your plans?
Comment 15•2 years ago
|
||
Hello Matthias,
We are working on issuing the CVE.
Thanks,
Frida
Comment 16•2 years ago
|
||
Regarding the fix for this you should not forget the following two aspects:
- only users with an active local session should be allowed to initiate a connection, not just anybody (like
nobody
). Polkit, if used properly, can be used for this with via theallow_active: yes
policy setting. - the leaking of log data as outlined in the initial report (see: getLogs()) should also be hardened.
Updated•2 years ago
|
Updated•2 years ago
|
Updated•2 years ago
|
Reporter | ||
Comment 17•2 years ago
|
||
The bug has been discussed in public, so there's no need to keep this hidden any longer.
The team is targeting a release of 2.16.1 for Linux on August 11th.
Reporter | ||
Comment 18•2 years ago
|
||
Mozilla VPN v2.16.1 has been made available by the team.
Reporter | ||
Comment 19•1 years ago
|
||
Attaching draft advisory for internal review.
Reporter | ||
Comment 20•1 years ago
|
||
Updated•1 year ago
|
Description
•