Bug 1130388 - AUDIT-STALE: deepin-clone: new polkit action com.deepin.pkexec.deepin-clone
AUDIT-STALE: deepin-clone: new polkit action com.deepin.pkexec.deepin-clone
Status: REOPENED
Classification: openSUSE
Product: openSUSE Tumbleweed
Classification: openSUSE
Component: Security
Current
All All
: P5 - None : Normal (vote)
: ---
Assigned To: zhang dingyuan
E-mail List
:
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2019-03-25 13:02 UTC by Hillwood Yang
Modified: 2021-05-03 09:47 UTC (History)
3 users (show)

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


Attachments
com.deepin.pkexec.deepin-clone.policy (9.84 KB, application/xml)
2019-03-25 13:04 UTC, Hillwood Yang
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Hillwood Yang 2019-03-25 13:02:31 UTC
[  129s] deepin-clone.x86_64: E: polkit-untracked-privilege (Badness: 10000) com.deepin.pkexec.deepin-clone (auth_admin:auth_admin:auth_admin)
[  129s] The privilege is not listed in /etc/polkit-default-privs.* which makes it
[  129s] harder for admins to find. Furthermore polkit authorization checks can easily
[  129s] introduce security issues. If the package is intended for inclusion in any
[  129s] SUSE product please open a bug report to request review of the package by the
[  129s] security team. Please refer to
[  129s] https://en.opensuse.org/openSUSE:Package_security_guidelines#audit_bugs for
[  129s] more information.
[  129s] 
[  129s] (none): E: badness 10000 exceeds threshold 1000, aborting.
[  129s] 3 packages and 0 specfiles checked; 1 errors, 2 warnings.
Comment 1 Hillwood Yang 2019-03-25 13:04:34 UTC
Created attachment 801090 [details]
com.deepin.pkexec.deepin-clone.policy

Please reveiwe this file.
Comment 2 Hillwood Yang 2019-03-25 13:05:46 UTC
This package is at https://build.opensuse.org/package/show/X11:Deepin:Factory/deepin-clone
Comment 3 Matthias Gerstner 2019-03-25 14:04:43 UTC
Thank you for opening the review bug. The program is of moderate size (about
8.500 lines of C++ code). Most of the code is probably concerned with GUI
management.

The other deepin code reviews from a while ago showed a couple of security
problems so we should be careful with this addition.

The security team is currently under a high load of reviews so it may take a
while until we can take care of this one.
Comment 4 Matthias Gerstner 2019-04-25 12:52:52 UTC
I will start working on this review.
Comment 5 Matthias Gerstner 2019-04-26 12:11:39 UTC
I just realize that there is still bug 1070943 pending for deepin-api. Do you
have a new version there with the patches included?
Comment 6 Hillwood Yang 2019-04-29 08:47:39 UTC
(In reply to Matthias Gerstner from comment #5)
> I just realize that there is still bug 1070943 pending for deepin-api. Do you
> have a new version there with the patches included?

Yes, I have updated bug 1070943. Thanks!
Comment 7 Matthias Gerstner 2019-04-29 12:57:56 UTC
So I reviewed deepin-clone and there are a couple of issues regarding
security. They need to be fixed before we can accept the package:

1) in GUI mode deepin-clone creates "/tmp/.deepin-clone.log" and follows
  symlinks there. This file needs to be open()ed with
  O_NOFOLLOW|O_CREAT|O_EXCL.  Or even better using a non predictable temporary
  file in /tmp using QTemporaryFile.

2) temporaryMountDevice() uses a fixed path
  /tmp/.deepin-clone/mount/<block-dev-basename> to temporarily mount a file
  system there. These paths can be prepared by an attacker and symlinks will
  be followed during mounting. If the attacker quickly enters the mount then
  it probably can also prevent the following unmount. This logic can e.g. be
  triggered by running `deepin-clone -i /dev/sdX`.

  An attacker can thus cause the file system to be permanently mounted at an
  arbitrary location in the file system.

3) `Helper::getPartitionSizeInfo()` uses /tmp/partclone.log as a fixed path
  during execution of partclone. The same issues about symlink attacks etc.
  like in 1) apply here. This needs to be a non-predictable path, or a path in
  a directory not accessible to regular users.

4) similarly in `BootDoctor::fix()` the fixed path /tmp/repo.iso is created and
  the fixed directory /tmp/.deepin-clone is used. The same concerns as in 1)
  and 3) apply.

5) /tmp/.deepin-clone.log and /var/log/deepin-clone.log are both world
  readable. Log files whould not be world readable when they come from a
  program running as root as it may leak information valuable to an attacker.

6) in helper.cpp:986:

  ```
  if (QFile::exists(QString("/proc/%1").arg(process->pid()))) {
      process->terminate();
      process->waitForFinished();
  } else {
  ```

  I don't know if this check is really necessary but if it is then it is a
  race condition and could be used to kill an unrelated process in case the
  child PID is replaced by some other process unrelated to deepin-clone.

7) in GUI and pkexec mode deepin-clone opens the `PKEXEC_UID`s
  `~/.pam_environment` while following symlinks and not checking file types.
  While it can be argued that the executor that successfully was granted
  access by pkexec shouldn't be an attacker it would still be a better style
  not to open this file as root. It should be opened only with
  setfsuid(PKEXEC_UID).

Non security issues but style/robustness issues:

8) isBlockSpecialFile() returns true if the path starts with /dev? That sounds
  like a hack and could lead to surprises!
9) DDiskInfo::getInfo() under some circumstances also creates the file? Sounds
  like an unexpected side effect!

The issue 1) and 2) and probably also 3) and 4) could require CVE assignments
since these are realistic security issues that can be exploited by local
regular users in the system.
Comment 8 Hillwood Yang 2019-04-29 13:12:39 UTC
(In reply to Matthias Gerstner from comment #7)
> So I reviewed deepin-clone and there are a couple of issues regarding
> security. They need to be fixed before we can accept the package:
> 
> 1) in GUI mode deepin-clone creates "/tmp/.deepin-clone.log" and follows
>   symlinks there. This file needs to be open()ed with
>   O_NOFOLLOW|O_CREAT|O_EXCL.  Or even better using a non predictable
> temporary
>   file in /tmp using QTemporaryFile.
> 
> 2) temporaryMountDevice() uses a fixed path
>   /tmp/.deepin-clone/mount/<block-dev-basename> to temporarily mount a file
>   system there. These paths can be prepared by an attacker and symlinks will
>   be followed during mounting. If the attacker quickly enters the mount then
>   it probably can also prevent the following unmount. This logic can e.g. be
>   triggered by running `deepin-clone -i /dev/sdX`.
> 
>   An attacker can thus cause the file system to be permanently mounted at an
>   arbitrary location in the file system.
> 
> 3) `Helper::getPartitionSizeInfo()` uses /tmp/partclone.log as a fixed path
>   during execution of partclone. The same issues about symlink attacks etc.
>   like in 1) apply here. This needs to be a non-predictable path, or a path
> in
>   a directory not accessible to regular users.
> 
> 4) similarly in `BootDoctor::fix()` the fixed path /tmp/repo.iso is created
> and
>   the fixed directory /tmp/.deepin-clone is used. The same concerns as in 1)
>   and 3) apply.
> 
> 5) /tmp/.deepin-clone.log and /var/log/deepin-clone.log are both world
>   readable. Log files whould not be world readable when they come from a
>   program running as root as it may leak information valuable to an attacker.
> 
> 6) in helper.cpp:986:
> 
>   ```
>   if (QFile::exists(QString("/proc/%1").arg(process->pid()))) {
>       process->terminate();
>       process->waitForFinished();
>   } else {
>   ```
> 
>   I don't know if this check is really necessary but if it is then it is a
>   race condition and could be used to kill an unrelated process in case the
>   child PID is replaced by some other process unrelated to deepin-clone.
> 
> 7) in GUI and pkexec mode deepin-clone opens the `PKEXEC_UID`s
>   `~/.pam_environment` while following symlinks and not checking file types.
>   While it can be argued that the executor that successfully was granted
>   access by pkexec shouldn't be an attacker it would still be a better style
>   not to open this file as root. It should be opened only with
>   setfsuid(PKEXEC_UID).
> 
> Non security issues but style/robustness issues:
> 
> 8) isBlockSpecialFile() returns true if the path starts with /dev? That
> sounds
>   like a hack and could lead to surprises!
> 9) DDiskInfo::getInfo() under some circumstances also creates the file?
> Sounds
>   like an unexpected side effect!
> 
> The issue 1) and 2) and probably also 3) and 4) could require CVE assignments
> since these are realistic security issues that can be exploited by local
> regular users in the system.

Thanks! I will report to upstream.
Comment 9 Hillwood Yang 2019-06-08 13:21:30 UTC
Upstream have fixed this security issue in new version 1.1.3, could you check this fix?
Comment 11 Matthias Gerstner 2019-07-03 10:26:54 UTC
So lets see what has been improved:

(In reply to matthias.gerstner@suse.com from comment #7)
> 1) in GUI mode deepin-clone creates "/tmp/.deepin-clone.log" and follows
>   symlinks there. This file needs to be open()ed with
>   O_NOFOLLOW|O_CREAT|O_EXCL.  Or even better using a non predictable temporary
>   file in /tmp using QTemporaryFile.

This file has been moved to /var/log/deepin-clone.log. At least the symlink
attack should be avoided this way.

> 2) temporaryMountDevice() uses a fixed path
>   /tmp/.deepin-clone/mount/<block-dev-basename> to temporarily mount a file
>   system there. These paths can be prepared by an attacker and symlinks will
>   be followed during mounting. If the attacker quickly enters the mount then
>   it probably can also prevent the following unmount. This logic can e.g. be
>   triggered by running `deepin-clone -i /dev/sdX`.

The mount is now performed in QStandardPaths::RuntimeLocation which is
/run/user/$UID on Linux. It's a bit unusual to use that for this purpose but
it should address the symlink attack.

> 3) `Helper::getPartitionSizeInfo()` uses /tmp/partclone.log as a fixed path
>   during execution of partclone. The same issues about symlink attacks etc.
>   like in 1) apply here. This needs to be a non-predictable path, or a path in
>   a directory not accessible to regular users.

The file has been moved to /var/log/partclone.log. The symlink attack should
be addressed this way.

> 4) similarly in `BootDoctor::fix()` the fixed path /tmp/repo.iso is created and
>   the fixed directory /tmp/.deepin-clone is used. The same concerns as in 1)
>   and 3) apply.

This has been moved to /var/cache/deepin-clone. /var/cache is usually only
writable by root. Should handle this attack vector.

> 5) /tmp/.deepin-clone.log and /var/log/deepin-clone.log are both world
>   readable. Log files whould not be world readable when they come from a
>   program running as root as it may leak information valuable to an attacker.

As far as I can see this item has not been addressed.

> 6) in helper.cpp:986:
> 
>   ```
>   if (QFile::exists(QString("/proc/%1").arg(process->pid()))) {
>       process->terminate();
>       process->waitForFinished();
>   } else {
>
>   ```
>   I don't know if this check is really necessary but if it is then it is a
>   race condition and could be used to kill an unrelated process in case the
>   child PID is replaced by some other process unrelated to deepin-clone.

This item has also not been adressed, only a Chinese comment was added that I
can't fully understand. It seems to be a kind of workaround for something but
this approach is not good security wise.

> 7) in GUI and pkexec mode deepin-clone opens the `PKEXEC_UID`s
>   `~/.pam_environment` while following symlinks and not checking file types.
>   While it can be argued that the executor that successfully was granted
>   access by pkexec shouldn't be an attacker it would still be a better style
>   not to open this file as root. It should be opened only with
>   setfsuid(PKEXEC_UID).

The parsing of this file has been removed, instead an environment variable
D_QT_THEME_CONFIG_PATH pointing to the users ~/.config directory is setup. I'm
not quite sure where this environment variable is used at all at the moment.
So the status is unclear to me.

> Non security issues but style/robustness issues:
> 
> 8) isBlockSpecialFile() returns true if the path starts with /dev? That sounds
>   like a hack and could lead to surprises!

This is still the same.

> 9) DDiskInfo::getInfo() under some circumstances also creates the file? Sounds
>   like an unexpected side effect!

So the issues 5), 6), 8) and 9) have not been addressed yet. For 7) I'm not
sure.

The more severe issues have been fixed at least. 5) and 6) should still be
addressed before we accept it, the others ... well they look very hacky and I
think something should be done as well.
Comment 12 Matthias Gerstner 2019-12-16 12:44:03 UTC
There has been no response from the packager or from upstream for a long time.
Closing this and related deepin bugs.
Comment 13 Hillwood Yang 2021-04-26 01:43:12 UTC
Assign to justforlxz@gmail.com
Comment 14 Matthias Gerstner 2021-04-29 12:06:18 UTC
(In reply to hillwoodroc@gmail.com from comment #13)
> Assign to justforlxz@gmail.com

this time actually assign :)