Bug 1176742 - AUDIT-1: plasma5-disks: new kauth helper org.kde.kded.smart.service (polkit, d-bus)
Summary: AUDIT-1: plasma5-disks: new kauth helper org.kde.kded.smart.service (polkit, ...
Status: RESOLVED FIXED
Alias: None
Product: openSUSE Tumbleweed
Classification: openSUSE
Component: Security (show other bugs)
Version: Current
Hardware: Other Other
: P5 - None : Normal (vote)
Target Milestone: ---
Assignee: Security Team bot
QA Contact: E-mail List
URL:
Whiteboard:
Keywords:
Depends on: 1177298
Blocks:
  Show dependency treegraph
 
Reported: 2020-09-19 21:29 UTC by Fabian Vogt
Modified: 2024-03-13 09:20 UTC (History)
6 users (show)

See Also:
Found By: ---
Services Priority:
Business Priority:
Blocker: ---
Marketing QA Status: ---
IT Deployment: ---


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Fabian Vogt 2020-09-19 21:29:22 UTC
Hi, 

Plasma 5.20 includes a new component which warns the user if SMART values of disks are critical.
For this it uses a KAuth helper with calls smartctl with the provided device.

The two D-Bus service files found by rpmlint are:

- /usr/share/dbus-1/system-services/org.kde.kded.smart.service
- /usr/share/dbus-1/system.d/org.kde.kded.smart.conf

Code used by the helper:

- https://invent.kde.org/plasma/plasma-disks/-/blob/master/src/helper.cpp
- https://invent.kde.org/plasma/plasma-disks/-/blob/master/src/helper.h
- https://invent.kde.org/plasma/plasma-disks/-/blob/master/src/org.kde.kded.smart.actions

A package including these features is available at https://build.opensuse.org/package/show/home:Vogtinator:plasma-disks/plasma5-disks
and once the .spec got reviewed at
https://build.opensuse.org/package/show/KDE:Unstable:Frameworks/plasma5-disks
Comment 2 Matthias Gerstner 2020-10-02 08:02:57 UTC
I will start the review.
Comment 3 Matthias Gerstner 2020-10-02 10:51:33 UTC
(In reply to fvogt@suse.com from comment #1)
> I had a quick look at the helper and while it prevents arbitrary arguments
> to be passed (the absolute path has to be below /dev), this can probably be
> circumvented by sending a file descriptor over dbus and passing /dev/fd/X
> (should be predictable) as argument.

Yes this would be possible, but it requires the attacker to open the file in
advance (i.e. he needs to have certain access rights anyway). It could be
combined with a symlink attack in the path that /dev/fd/X is pointing to.

Furthermore there is a TOCTOU race condition regarding the call to
`info.absoluteFilePath()` and the time the path is actually accessed by
smartctl. Since /dev/shm is a world writable sticky bit directory an attacker
can:

- first place a regular file in /dev/shm/myfile
- call the org.kde.kded.smart.smartctl action for /dev/shm/myfile
- try to win the race condition by replacing /dev/shm/myfile with a symlink at
  the right time
- on success smartctl will dereference the symlink and arbitrary paths will
  become possible.
- kernel symlink protection will prevent the worst

Mostly this issue could be used for file existence tests. Since smartctl only
operates on block devices there shouldn't be much further damage involved.

Since we are seeing these types of weak file path checks again and again I
still like to see improved code. We need to stop spreading such bad examples
in OSS code.

What can be done is something along the following lines:

- use realpath() to resolve all path components of the input path
- require that the resolved path starts with /dev
- split up the path into individual path components
- open /dev with the O_PATH|O_NOFOLLOW flags and start descending down the
  resolved path components using openat(), O_PATH|O_NOFOLLOW.

for each path component:

- perform an fstat() and inspect the owner, file type and mode.
- if the file type is other than block device or directory then an error needs
  to be returned.
- if the file is owned by a non-root user then an error needs to be returned.
- if the file is world-writable (sticky-bit directories) then an error needs
  to be returned.

- the final path component needs to be of the block device file type
- smartctl needs to be pointed to the resolved path. No path components under
  attacker control should be involved.
Comment 4 Fabian Vogt 2020-10-02 11:21:36 UTC
(In reply to Matthias Gerstner from comment #3)
> (In reply to fvogt@suse.com from comment #1)
> > I had a quick look at the helper and while it prevents arbitrary arguments
> > to be passed (the absolute path has to be below /dev), this can probably be
> > circumvented by sending a file descriptor over dbus and passing /dev/fd/X
> > (should be predictable) as argument.
> 
> Yes this would be possible, but it requires the attacker to open the file in
> advance (i.e. he needs to have certain access rights anyway). It could be
> combined with a symlink attack in the path that /dev/fd/X is pointing to.

Shouldn't even be necessary. open with O_PATH doesn't require privileges like
that and smartctl seems to dereference the passed path anyway...

> Furthermore there is a TOCTOU race condition regarding the call to
> `info.absoluteFilePath()` and the time the path is actually accessed by
> smartctl. Since /dev/shm is a world writable sticky bit directory an attacker
> can:
> 
> - first place a regular file in /dev/shm/myfile
> - call the org.kde.kded.smart.smartctl action for /dev/shm/myfile
> - try to win the race condition by replacing /dev/shm/myfile with a symlink
> at
>   the right time
> - on success smartctl will dereference the symlink and arbitrary paths will
>   become possible.
> - kernel symlink protection will prevent the worst
> 
> Mostly this issue could be used for file existence tests. Since smartctl only
> operates on block devices there shouldn't be much further damage involved.
> 
> Since we are seeing these types of weak file path checks again and again I
> still like to see improved code. We need to stop spreading such bad examples
> in OSS code.

Definitely. IIRC I've heard of a library which implements several of such
primitives in a secure way, so if that's license compatible it could be used
(or copied, as it's past dep freeze). I don't know where I found that anymore
though, maybe you know something?

> What can be done is something along the following lines:
> 
> - use realpath() to resolve all path components of the input path
> - require that the resolved path starts with /dev
> - split up the path into individual path components
> - open /dev with the O_PATH|O_NOFOLLOW flags and start descending down the
>   resolved path components using openat(), O_PATH|O_NOFOLLOW.
> 
> for each path component:
> 
> - perform an fstat() and inspect the owner, file type and mode.
> - if the file type is other than block device or directory then an error
> needs
>   to be returned.
> - if the file is owned by a non-root user then an error needs to be returned.
> - if the file is world-writable (sticky-bit directories) then an error needs
>   to be returned.
> 
> - the final path component needs to be of the block device file type
> - smartctl needs to be pointed to the resolved path. No path components under
>   attacker control should be involved.
Comment 5 Malte Kraus 2020-10-02 12:44:35 UTC
(In reply to Fabian Vogt from comment #4)
> 
> Definitely. IIRC I've heard of a library which implements several of such
> primitives in a secure way, so if that's license compatible it could be used
> (or copied, as it's past dep freeze). I don't know where I found that anymore
> though, maybe you know something?
> 

You may be thinking of https://github.com/openSUSE/libpathrs
Comment 6 Matthias Gerstner 2020-10-02 13:19:27 UTC
(In reply to fvogt@suse.com from comment #4)
> (In reply to Matthias Gerstner from comment #3)
> > (In reply to fvogt@suse.com from comment #1)
> > > I had a quick look at the helper and while it prevents arbitrary arguments
> > > to be passed (the absolute path has to be below /dev), this can probably be
> > > circumvented by sending a file descriptor over dbus and passing /dev/fd/X
> > > (should be predictable) as argument.
> > 
> > Yes this would be possible, but it requires the attacker to open the file in
> > advance (i.e. he needs to have certain access rights anyway). It could be
> > combined with a symlink attack in the path that /dev/fd/X is pointing to.
> 
> Shouldn't even be necessary. open with O_PATH doesn't require privileges like
> that and smartctl seems to dereference the passed path anyway...

This is only partly valid. For opening with O_PATH you still need execute
permission on the involved directories.

> Definitely. IIRC I've heard of a library which implements several of such
> primitives in a secure way, so if that's license compatible it could be used
> (or copied, as it's past dep freeze). I don't know where I found that anymore
> though, maybe you know something?

Yes the library that Malte mentioned probably. I'm not sure if it is
production ready yet, though.

Since the KDE seems to have a lot of uses cases of this kind it could also be
a solution to provide this path security check algorithm in some suitable
framework library. Most of the time what is needed is simply a path that is
known not to be under control of anybody else but root.
Comment 7 Matthias Gerstner 2020-10-05 09:56:03 UTC
Thinking some more about this, a simpler approach could be to implement a
whitelist of paths that are accepted. I could imagine something like:

- block devices directly in /dev
- anything below /dev/disk

Virtual block devices like from LVM or dmcrypt should not be needed here,
since they shouldn't deliver SMART data anyways.
Comment 8 Luca Beltrame 2020-10-05 13:40:17 UTC
We have contacted upstream. I will forward a mail to the security team with the developer in CC, with also a potential patch on their side to address the issue.
Comment 9 Matthias Gerstner 2020-10-07 11:53:17 UTC
Downgrading to AUDIT-1. Waiting for new code drop. There's a separate
discussion about the fix with upstream running by e-mail.
Comment 10 Luca Beltrame 2020-10-10 11:57:26 UTC
Upstream has merged the change (https://invent.kde.org/plasma/plasma-disks/-/merge_requests/5) and we ship it in the packages which are under review at this point.

Is there anything else left to do, or can this be whitelisted now? Thanks.
Comment 11 Matthias Gerstner 2020-10-12 08:18:28 UTC
(In reply to lbeltrame@kde.org from comment #10)
> Is there anything else left to do, or can this be whitelisted now? Thanks.

I started the whitelisting process. Thanks for working on the issue.
Comment 12 Fabian Vogt 2020-10-19 12:35:08 UTC
Is there a SR or PR for tracking progress?
Some users asked why plasma5-disks is missing in TW and I could only link this report.
Comment 13 Matthias Gerstner 2020-10-19 12:58:19 UTC
(In reply to fabian@ritter-vogt.de from comment #12)
> Is there a SR or PR for tracking progress?
> Some users asked why plasma5-disks is missing in TW and I could only link this report.

Hm for some reason the submission bot didn't post a comment about sr#841162 /
sr#841629 regarding the D-Bus whitelisting in rpmlint.

For some other reason I seem to have forgotten to actually update
polkit-default-privs which I did just now, is on the way to Factory via
sr#842553.
Comment 14 OBSbugzilla Bot 2020-10-19 13:30:08 UTC
This is an autogenerated message for OBS integration:
This bug (1176742) was mentioned in
https://build.opensuse.org/request/show/842553 Factory / polkit-default-privs
Comment 15 Matthias Gerstner 2020-10-26 12:54:18 UTC
The whitelisting should be through by now.