Page MenuHome GnuPG

Kleopatra: LPE issue on Windows
Open, NormalPublic

Description

Kleopatra contains a mechanism for ensuring that only one instance is running.
On Windows, this mechanism can be exploited by a local unprivileged attacker
to gain the full privileges of the user who runs Kleopatra.

Kleopatra could be used in a staged attack to gain higher privileges up to
full administrator privileges.

See https://kde.org/info/security/advisory-20260408-1.txt

Event Timeline

GpgOL/Web is likely also affected.

This is not a security bug. Consider: The user starts kleopatra as administrator (via runas or an administrator terminal) and then starts a second kleopatra to have a "privilege escalation" - So what is the point - if you can do runas you already have all the privileges you could get with this privilege escalation.

And nobody should run arbitrary programs with escalated privileges - GUI applications are in most cases not made for this. Regardless on whether this is on Windows or Unix.

Please revert the fixes to Gpg4win and Kleopatra in favor of showing the "Do not run as Adminstrator" before checking for a running instance.

The attack works like this: An unprivileged user starts an application which creates a window like the one Kleopatra looks for. Then the normal user (or an admin) starts Kleopatra. Kleopatra finds the existing window (it looks for any window with the right name) and grants the unprivileged process full access to the Kleopatra process. Now the unprivileged process can do anything the Kleopatra process can do.

For my own understanding I repeat your explanation with some changes
for clarity:

An user accidently starts a standard application which happens to
implement a trojan. The trojan creates a hidden windows with the same
name as used by Kleopatra. The trojan runs without elevated rights.

Then the user starts Kleopatra. To check for an already running
Kleopatra instance it looks for an other Windows with the Kleopatra
name. Now if the user starts Kleopatra with elevated rights (which
s/he should never do) Kleopatra finds the Window owned by the trojan
and basically transfers control, including its own elevated rights,
to the trojan. The trojan has thus gained elevated rights without the
user has seen a confirmation dialog to allow priviliged access
(because s/he has already confimed this when starting Kleopatra or the
Admin Terminal from which Kleopatra was started).

werner renamed this task from Security (internal) - Kleopatra: LPE issue on Windows to Kleopatra: LPE issue on Windows.Thu, Apr 9, 2:59 PM
werner changed the visibility from "g10code (Project)" to "Public (No Login Required)".
werner changed the edit policy from "Custom Policy" to "Contributor (Project)".

See also T5248

I would suggest to move the is_elevated check before checking for running instances and then always terminate the process. For those footgunners we can add a Registry key AllowRunningAsAdmin=footgun as HKCU which prints it only as a warning.

I do think that switching from our own copied-around-code to a wider shared component for single-application setups does make very much sense rather than try to battle-harden our own code against scenarios of various likeliness.

Even without considering the severity of the LPE, I do think that changing to kdsingleapplication makes sense on it's own:

In amount of code changes, we swap around 350 lines of code in kleopatra and 350 lines in gpgol/web for 450 lines of code in kdsingleapplication.

There is also movement in Okular to switch to kdsingleapplication to get its various multiple-documents-single-window-features working on windows without dbus.

I would like to see a description on how Kdsingleapplication handles the Windows Named Pipes. In particular how does it ensure that there is no way to remotely connect to the named pipe. AFAICR, there is no way in Windows to do that.

For current vsd we definitely can't switch to a new IPC mechanism.

werner lowered the priority of this task from Unbreak Now! to Needs Triage.Sun, Apr 12, 7:19 PM
ikloecker mentioned this in Unknown Object (Maniphest Task).Mon, Apr 13, 9:40 AM

Citing the API documentation of CreateNamedPipe (https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createnamedpipea):

One of the following remote-client modes can be specified. Different instances of the same pipe can specify different remote-client modes.

PIPE_REJECT_REMOTE_CLIENTS Connections from remote clients are automatically rejected.
0x00000008

This seems to indicate that it's possible to avoid remote connections to the named pipe.

QLocalServer (which is used by KDSingleApplication) doesn't use this mode flag. Interestingly, QProcess does use this mode flag (for redirecting the standard I/O channels).

We could patch our Qt to set this mode flag and try to get it upstream (probably as option).

The documentation for named pipes also mentions

If you intend to use a named pipe locally only, deny access to NT AUTHORITY\NETWORK or switch to local RPC.

This seems to be a newer flag, although not stated in the docs.. Hart does not mention this in Windows Systems Programming either. I recall that I did extensive tests with Named Pipes and Mailslots to find a way to restrict access to local processes only. Sure you can use capabilities to restrict access but that is a pretty complex beast and easy to get wrong. It did not worked back then when I tested this with NT 3.5 or so. Thus our solution was to to use TCP where you can easily specifcy the listening port.

PIPE_REJECT_REMOTE_CLIENTS is from windows vista and onwards. I guess that's good enough for us.

Windows 10 since some build number also has real Local Sockets which avoids the trouble with Windows ACLs.

Still, why shall we add more KDE specific code when it is not needed. In particular because GpgOL does very similar things. Not allowing to run elevated is the better choice.

ikloecker mentioned this in Unknown Object (Maniphest Task).Mon, Apr 20, 9:43 AM
ebo added a subscriber: ebo.

As I'd like to have it in vsd34, I'll set that tag (and of course gpd5x, too)

werner triaged this task as Normal priority.Sun, Apr 26, 6:44 PM
werner shifted this object from the Restricted Space space to the S1 Public space.
werner removed a project: to-be-discussed.