Fri, Jan 24th, 2025


dde-api-proxy: Authentication Bypass in Deepin D-Bus Proxy Service (CVE-2025-23222)
Table of Contents
- 1) Introduction
- 2) Authentication Bypass Issue
- 3) Reproducers
- 4) Affected D-Bus Interfaces
- 5) Suggested Bugfix
- 6) Upstream Bugfix
- 7) Possible Workarounds
- 8) CVE Assignment
- 9) Timeline
- 10) References
1) Introduction
We received a review request for the Deepin api-proxy D-Bus service which is part of the Deepin desktop environment. During the review we discovered a major authentication flaw in the design of this D-Bus service which allows local users to escalate privileges in various ways.
We reported this issue privately to Deepin security in December and did not receive a reply for a month. As we were preparing for publication, upstream became alive and quickly released a bugfix which is, sadly, still incomplete.
This report is based on dde-api-proxy version 1.0.17. The findings still apply to release 1.0.18. Upstream has attempted to fix these findings in release 1.0.19, but the bugfix is insufficient as outlined in section 6).
2) Authentication Bypass Issue
Dde-api-proxy runs as root
and provides various D-Bus services on the
D-Bus system bus. It sticks out since it ships a lot of D-Bus configuration
files but only little code. The reason for this is that the service only
forwards D-Bus requests between its clients and the actual Deepin D-Bus
services. We believe this is for backward compatibility due to changes in
Deepin D-Bus interface names, alas the component’s GitHub
repository provides little insight into its
purpose.
During startup the proxy service proactively registers the requested legacy
D-Bus interface and creates a connection to the actual Deepin D-Bus service,
to which messages will be forwarded to. When a client sends a message to one
of the legacy service names, the proxy synchronously forwards the message
(see handleMessage()
) via its existing connection
and returns the reply to the client.
This rather straightforward approach of proxying D-Bus messages has a major security flaw, however:
- the proxy runs as
root
. - the proxy forwards messages from arbitrary local users to the actual D-Bus services without any authentication requirements.
- the actual D-Bus services don’t know about the proxy situation, they believe
that
root
is asking them to perform operations.
Consequently with the help of dde-api-proxy, legacy D-Bus methods that normally wouldn’t be accessible to non-root users will become accessible without authentication.
3) Reproducers
D-Bus Method without Polkit
Following is a simple demonstration of the issue based on the Deepin Grub2 service. This service simply checks the UID of the D-Bus client for authentication of privileged operations. In the first command shown below the actual D-Bus service name is used, and the service rejects the operation, because the caller is not privileged:
user$ gdbus call -y -d org.deepin.dde.Grub2 \
-o /org/deepin/dde/Grub2 -m org.deepin.dde.Grub2.SetTimeout 100
Error: GDBus.Error:org.deepin.dde.DBus.Error.Unnamed: not allow :1.167 call this method
In the next command the legacy D-Bus service name is used, and this time the target service performs the operation, because it believes the request originates from a privileged UID 0 client (dde-api-proxy):
user$ gdbus call -y -d com.deepin.daemon.Grub2 \
-o /com/deepin/daemon/Grub2 -m com.deepin.daemon.Grub2.SetTimeout 10
()
D-Bus method using Polkit
In the previous example Polkit authentication was not involved. When it is involved then the caller is treated as “admin”, resulting in a similar escalation of privileges. We found a suitable example using Polkit in the Deepin accounts service. This service offers a large range of system operations, among them the possibility to add users to groups. It checks the authorization of the “org.deepin.dde.accounts.user-administration” Polkit action, which is by default only allowed for users in a local session if they provide admin credentials.
The following gdbus
call attempts to add the unprivileged user with UID 1000
to the root
group. The call only works this way when it runs from within a
(Deepin) graphical session. The actual accounts service interface is invoked
here, thus the operation fails (it would require entering a root password).
user$ gdbus call -y -d org.deepin.dde.Accounts1 -o /org/deepin/dde/Accounts1/User1000 \
-m org.deepin.dde.Accounts1.User.AddGroup root
Error: GDBus.Error:org.deepin.dde.DBus.Error.Unnamed: Policykit authentication failed
When switching to the legacy accounts service interface offered by dde-api-proxy, the operation succeeds without any authentication request, because the accounts service again believes root with UID 0 is the client asking for this:
user$ gdbus call -y -d com.deepin.daemon.Accounts -o /com/deepin/daemon/Accounts/User1000 \
-m com.deepin.daemon.Accounts.User.AddGroup root
()
4) Affected D-Bus Interfaces
We did not look into all the privileged D-Bus methods that become available to unauthenticated local users via dde-api-proxy. On some of the proxied interfaces only a certain set of “filtered methods” is allowed to be invoked. The rest of the interfaces don’t put restrictions on the methods invoked, though. On first look, interesting attack surface seems to be found in the following D-Bus interfaces offered by dde-api-proxy:
- Accounts services (no method filter list)
- network proxy settings (no method filter list)
- PasswdConf1 WriteConfig method
- Lastore service (Apt backend, no method filter list)
- Lastore manager install package method
5) Suggested Bugfix
The authentication bypass is deeply rooted in the design of dde-api-proxy, thus fixing it is difficult. Possible approaches to addressing it are presented in the following sub-sections.
a) Dropping Privileges
The proxy could temporarily drop privileges to the unprivileged caller’s credentials, create a new D-Bus connection and forward the message to the proper service. This still won’t work properly if the D-Bus service in question is using Polkit for authentication, because Polkit differentiates whether the caller is in an active session or not. The D-Bus proxy service will never be in a session, though. This means that authentication requirements could be stronger than necessary. At least this approach would be safer than what currently happens.
b) Reimplementing Authentication Checks
The proxy could implement all necessary authentication checks on its own. This would result in the proper authentication being performed, but would lead to duplication of a lot of code. It would also add the danger that the authentication requirements of the proxy service and the actual service get out of sync.
c) Implementing Legacy Interfaces in the Affected Services
Finally dde-api-proxy could be dropped completely and the backward compatibility could be implemented in every one of the affected services. This is a less generic approach than what dde-api-proxy attempts to achieve, of course.
6) Upstream Bugfix
After a longer period of silence, upstream unexpectedly replied to our report and a short embargo period was established until a bugfix was published on January 17. The bugfix is found in upstream commit 95b50dd which made its way into release 1.0.19.
For the bugfix upstream went in the direction of our suggestion outlined in section 5.b), by implementing redundant Polkit authorization checks in the proxy service. A list of sensitive D-Bus methods offered by the proxy is now maintained in the source code. All of these methods are protected by a single, newly introduced Polkit action “org.deepin.dde.api.proxy” which requires admin authentication.
The bugfix introduces a new problem, though. The Polkit authorization check is implemented as follows:
bool checkAuthorization(const QString &actionId, const QString &service,const QDBusConnection &connection) const
{
auto pid = connection.interface()->servicePid(service).value();
auto authority = PolkitQt1::Authority::instance();
auto result = authority->checkAuthorizationSync(actionId,
PolkitQt1::UnixProcessSubject(pid),
PolkitQt1::Authority::AllowUserInteraction);
/* snip */
}
This code forwards the client’s process ID (PID) to the Polkit service for authentication. This way of using the Polkit UnixProcessSubject has been deprecated for a long time, because it is subject to a race condition that allows to bypass such authorization checks. This issue was discovered in 2013 by former SUSE security engineer Sebastian Krahmer, and was assigned CVE-2013-4288.
Upstream did not share the bugfix with us before publication, thus we were not able to prevent this incomplete bugfix. It should be possible to amend the incomplete bugfix by switching to the SystemBusName subject for authentication.
Even with an improved fix we believe this approach is not ideal, since it requires proper maintenance of all the proxied methods by upstream. If new methods are added at a later time, security issues could sneak in again. Also the newly introduced Polkit action makes the proxy service less transparent and could hamper the user experience. There is no more fine-grained control over the authentication requirements of individual D-Bus methods, and the authentication message for all of these proxied D-Bus methods is generic and unhelpful for end users.
7) Possible Workarounds
We don’t see any viable ways to work around this issue, except for removing dde-api-proxy from the system.
8) CVE Assignment
This finding is a bigger design issue in dde-api-proxy that allows for a local root (group) exploit and likely more similar attack vectors. We decided to request a CVE from Mitre to make the community aware of the issue. Mitre assigned CVE-2025-23222 to track this issue.
Formally another CVE would need to be assigned for the new security issue introduced by the incomplete bugfix described in section 6), but we refrained from doing so at this time.
9) Timeline
2024-12-18 | We reported the issues by email to security@deepin.com, which is documented on the project’s contact page. The email was rejected by the mail server. |
2024-12-18 | We reached out to support@deepin.org asking what the proper way to report Deepin security issues is. We quickly got a reply that pointed us to their (public) bug tracker or security@deepin.org. |
2024-12-19 | We reported the issues by email to security@deepin.org, offering coordinated disclosure. This time the email was not rejected. |
2025-01-07 | Since we did not receive a reply yet from Deepin security yet we sent another email asking for an initial reply until 2025-01-12, otherwise we would publish the information. |
2025-01-13 | Since we still did not receive a reply we started working on publishing the full report. We requested a CVE from Mitre. |
2025-01-14 | Mitre assigned CVE-2025-23222. |
2025-01-16 | An upstream contact unexpectedly replied and confirmed the issue, stating they are working on a bugfix. We asked once more whether coordinated disclosure is desired, and also forwarded the assigned CVE. |
2025-01-17 | Upstream replied that they want to maintain an embargo until 2025-01-20. |
2025-01-23 | Since no activity at the publication date was visible upstream and we did not get a notification, we asked upstream whether publication will happen as planned. |
2025-01-24 | Upstream pointed us to the bugfix, which had already been published with no further communication on 2025-01-17. |
2025-01-24 | Since the bugfix was published, we decided to publish all information. While reviewing the bugfix, we realised it was incomplete and notified upstream by email. |
10) References
Thu, Jan 23rd, 2025


Submit a Presentation for the openSUSE Conference
The call for papers for openSUSE Conference 2025 is open.
The conference is scheduled to take place June 26 to 28 in Nuremberg, Germany.
Until April 30, people can submit proposals for a talk or workshop to share insights and their expertise.
People have 97 days to submit a talk for the conference and are encouraged to submit talks based on the following length and topics:
Presentations can be submitted for the following length of time:
- Lightning Talk (10 mins)
- Short Talk (30 mins)
- Virtual Talk (30 mins)
- Long Talk (45 mins)
- Workshop (1 hour)
The following tracks are listed for the conference:
- Cloud and Containers
- Community
- Embedded Systems and Edge Computing
- New Technologies
- Open Source
- openSUSE
- Open Source for Business: Beyond Code into Sustainability Track
Volunteers who would like to help the with the organization of the conference are encouraged to email ddemaio@opensuse.org or attend a weekly community meetings.
Conferences need sponsors to support community driven events to keep events free and open to new contributing members. Companies can find sponsorship information or donate to the Geeko Foundation to assist with funds that will go toward the conference.
Tue, Jan 21st, 2025


Labeling projects across the OBS
Mon, Jan 20th, 2025


openSUSE Board Elections Update
Members of the openSUSE Election Committee have informed the project that Board elections are underway.
Four candidates are running for three open seats.
The final candidate list is:
- Chuck Payne
- Ish Sookun
- Jeff Mahoney
- Rachel Schrader
Key Dates
- Jan. 19, 2025: Voting opens
- Feb. 2, 2025: Voting closes
- Feb. 3, 2025: Results announced
For more information about the candidates and the election, visit the project mailing list where candidates are answering questions and informing members of their platform.
Board members serve as guides for the community, handle key project functions, facilitate initiatives, organize meetings, and manage openSUSE domains and trademarks. They also uphold community standards, including overseeing complaints and ensuring compliance with the openSUSE Code of Conduct.
Per the Election Rules, only current members are eligible to run for board positions. New members joining during the membership drive can participate in voting but cannot stand as candidates.
The election is overseen by committee members Edwin Zakaria, and Ariez Vachha. Their responsibilities include finalizing the candidate list and ensuring a smooth election process.
Fri, Jan 17th, 2025


Tumbleweed – Review of the week 2025/03
Dear Tumbleweed users and hackers,
The year is in full swing, people mostly seem back from their deserved holiday break and submissions keep coming. Based on all the submit requests, we picked what we could and published 5 snapshots out of that (20250109, 0112, 0113, 0114, and 0115)
The most relevant changes delivered during the last week were:
- GStreamer 1.24.11
- Dracut 059+suse.672: rework timeout for devices added via –mount and –add-device (bsc#1231792)
- Mozilla Firefox 134.0
- KDE Gear 24.12.1
- KDE Frameworks 6.10.0
- fwupd 1.9.27
- Poppler 25.01.0
- sssd 2.10.1
- Linux kernel 6.12.9
- shadow 4.17.2
- All python 3.10 modules have been removed. The interpreter is (for now) still in the repository, but probably not for long.
The next snapshot is already in QA, and looks good to be released later today (no promise given though – we only know at the end of QA). This snapshot, and the next ones in planning, will likely bring these changes:
- GIMP 3 (RC2)
- GNOME 47.3
- gpg 2.5.3
- util-linux 2.40.4
- SQLite 3.48.0
- Systemd 257
- RPM 4.20
- KDE Plasma 6.3: Beta is currently staged to get preliminary QA results
Thu, Jan 16th, 2025


The syslog-ng Insider 2025-01: Alpine Linux; Leap 16.0; Alma Linux
The December syslog-ng newsletter is now on-line:
-
A syslog-ng container image based on Alpine Linux
-
Call for testing: syslog-ng in openSUSE Leap 16.0
-
Experimental syslog-ng container image based on Alma Linux
It is available at https://www.syslog-ng.com/community/b/blog/posts/the-syslog-ng-insider-2025-01-alpine-linux-leap-16-0-alma-linux

syslog-ng logo


Gaming on Linux, How openSUSE Stacks Up for Gamers
Millions of gamers are facing a critical decision; upgrade their operating system, invest in new hardware or explore alternatives like Linux with the end of Windows 10 support in October next year.
The good news is that gaming on Linux has never been better, and openSUSE is a powerful and versatile platform for gamers to continue enjoying their favorite titles.
Linux gaming has evolved significantly over the past decade. Thanks to tools like Proton, Steam and Lutris, a large number of Windows-exclusive games are now playable on Linux. openSUSE is an excellent choice for gamers making the switch since it’s well known for its stability, flexibility and hardware support.
Why Choose openSUSE for Gaming? openSUSE brings a unique combination of features that make it a desired Linux distribution for gamers:
- Stability and Performance: openSUSE Leap provides a reliable environment for gaming, while Tumbleweed offers the latest software and drivers for cutting-edge performance.
- Wide Hardware Support: Whether you’re using NVIDIA or AMD GPUs, openSUSE has excellent driver support.
- Customizability: openSUSE allows you to easily tailor your system for gaming with access to tools and tweaks.
Distributions of openSUSE will breathe new life into your existing hardware, help you to avoid costly upgrades and keep gaming without interruption.
Setting Up Gaming on openSUSE
Step 1: Install Steam
Steam is the cornerstone of Linux gaming, providing access to thousands of native and Proton-supported games. Open the software center (Discover for KDE Plasma, GNOME Software for GNOME) or use the terminal.
Install Steam:
sudo zypper install steam
Launch Steam, log in, and enable Steam Play:
- Go to Settings > Steam Play.
- Enable Steam Play for supported titles and Steam Play for all other titles.
- Select the latest version of Proton.
Steam Play allows you to run many Windows games seamlessly on Linux.
Step 2: Install Lutris
Lutris is a game manager that simplifies the installation and configuration of games from sources like GOG, Epic Games, and even emulators.
Install Lutris via the terminal:
sudo zypper install lutris
- Open Lutris and log in to your account. Use Lutris’s library to install and manage your games. It provides pre-configured setups for many popular titles, making the process effortless.
Step 3: Configure Your GPU Drivers
Proper GPU drivers are essential for gaming performance.
For NVIDIA GPUs:
Add the NVIDIA repository:
sudo zypper addrepo --refresh https://download.nvidia.com/opensuse/tumbleweed NVIDIA
Install the NVIDIA drivers:
sudo zypper search nvidia
(package)
sudo zypper install
(package)
For AMD GPUs:
AMD GPUs work out of the box with open-source Mesa drivers. To ensure optimal performance, update your system:
sudo zypper dup
Check out the GPU Switching if you use multiple GPUs.
Step 4: Optimize Your System
Install MangoHud: Monitor FPS and system performance in games.
sudo zypper install mangohud
Use GameMode: Optimize system resources for gaming performance.
sudo zypper install gamemode
Popular Games on openSUSE
Many games have native Linux versions that run flawlessly on openSUSE:
- Counter-Strike: Global Offensive
- Dota 2
- Sid Meier’s Civilization VI
- Hades
- Valheim
Proton, Steam’s compatibility layer, allows you to play many Windows games on Linux:
- The Witcher 3: Wild Hunt
- Cyberpunk 2077
- Red Dead Redemption 2
- Elden Ring
- No Man’s Sky
Retro Gaming
For retro gaming enthusiasts, tools like RetroArch and Dolphin Emulator enable you to relive classic titles from consoles like the Nintendo 64, GameCube, and PlayStation.
Resources and Support
Need help? The Linux gaming community is active and ready to assist. Check out these resources:
- Proton – Find information about how well your favorite games run on Linux.
- Lutris – Guides and tips for setting up games.
- openSUSE Forums – Connect with the community for support.
Gaming on Linux, particularly with openSUSE, is no longer a compromise. Whether you’re playing AAA titles, indie games or retro classics, openSUSE offers the tools and performance you need to enjoy a seamless gaming experience.
Don’t wait until Windows 10 support ends; make the switch today and keep your gaming journey alive on openSUSE.
Upgrading to Windows 11 may require new hardware, which could add significant costs. Switching to openSUSE not only extends the life of your current hardware but also gives you access to a modern, secure gaming platform. By adopting openSUSE, you avoid contributing to e-waste caused by discarding perfectly functional machines and take advantage of a free, open-source operating system tailored for performance and reliability. This is part of a series on Upgrade to Freedom where we offer reasons to transition from Windows to Linux.


Millions of gamers are facing a critical decision; upgrade their operating system, invest in new hardware or explore alternatives like Linux with the end of Windows 10 support in October next year.
Millions of gamers are facing a critical decision; upgrade their operating system, invest in new hardware or explore alternatives like Linux with the end of Windows 10 support in October next year.
The good news is that gaming on Linux has never been better, and openSUSE is a powerful and versatile platform for gamers to continue enjoying their favorite titles.
Linux gaming has evolved significantly over the past decade. Thanks to tools like Proton, Steam and Lutris, a large number of Windows-exclusive games are now playable on Linux. openSUSE is an excellent choice for gamers making the switch since it’s well known for its stability, flexibility and hardware support.
Why Choose openSUSE for Gaming? openSUSE brings a unique combination of features that make it a desired Linux distribution for gamers:
- Stability and Performance: openSUSE Leap provides a reliable environment for gaming, while Tumbleweed offers the latest software and drivers for cutting-edge performance.
- Wide Hardware Support: Whether you’re using NVIDIA or AMD GPUs, openSUSE has excellent driver support.
- Customizability: openSUSE allows you to easily tailor your system for gaming with access to tools and tweaks.
Distributions of openSUSE will breathe new life into your existing hardware, help you to avoid costly upgrades and keep gaming without interruption.
Setting Up Gaming on openSUSE
Step 1: Install Steam
Steam is the cornerstone of Linux gaming, providing access to thousands of native and Proton-supported games. Open the software center (Discover for KDE Plasma, GNOME Software for GNOME) or use the terminal.
Install Steam:
sudo zypper install steam
Launch Steam, log in, and enable Steam Play:
- Go to Settings > Steam Play.
- Enable Steam Play for supported titles and Steam Play for all other titles.
- Select the latest version of Proton.
Steam Play allows you to run many Windows games seamlessly on Linux.
Step 2: Install Lutris
Lutris is a game manager that simplifies the installation and configuration of games from sources like GOG, Epic Games, and even emulators.
Install Lutris via the terminal:
sudo zypper install lutris
- Open Lutris and log in to your account. Use Lutris’s library to install and manage your games. It provides pre-configured setups for many popular titles, making the process effortless.
Step 3: Configure Your GPU Drivers Proper GPU drivers are essential for gaming performance.
For NVIDIA GPUs:
Add the NVIDIA repository:
sudo zypper addrepo --refresh https://download.nvidia.com/opensuse/tumbleweed NVIDIA
Install the NVIDIA drivers:
sudo zypper search nvidia
(package)
sudo zypper install
(package)
For AMD GPUs:
AMD GPUs work out of the box with open-source Mesa drivers. To ensure optimal performance, update your system:
sudo zypper dup
Check out the GPU Switching if you use multiple GPUs.
Step 4: Optimize Your System
Install MangoHud: Monitor FPS and system performance in games.
sudo zypper install mangohud
Use GameMode: Optimize system resources for gaming performance.
sudo zypper install gamemode
Popular Games on openSUSE Native Linux Games Many games have native Linux versions that run flawlessly on openSUSE:
- Counter-Strike: Global Offensive
- Dota 2
- Sid Meier’s Civilization VI
- Hades
- Valheim
Windows Games with Proton Proton, Steam’s compatibility layer, allows you to play many Windows games on Linux:
- The Witcher 3: Wild Hunt
- Cyberpunk 2077
- Red Dead Redemption 2
- Elden Ring
- No Man’s Sky
Retro Gaming For retro gaming enthusiasts, tools like RetroArch and Dolphin Emulator enable you to relive classic titles from consoles like the Nintendo 64, GameCube, and PlayStation.
Resources and Support Need help? The Linux gaming community is active and ready to assist. Check out these resources: ProtonDB: protondb.com – Find information about how well your favorite games run on Linux. Lutris Wiki: lutris.net – Guides and tips for setting up games. openSUSE Forums: forums.opensuse.org – Connect with the community for support.
Gaming on Linux, particularly with openSUSE, is no longer a compromise. Whether you’re playing AAA titles, indie games or retro classics, openSUSE offers the tools and performance you need to enjoy a seamless gaming experience.
Don’t wait until Windows 10 support ends; make the switch today and keep your gaming journey alive on openSUSE.
Upgrading to Windows 11 may require new hardware, which could add significant costs. Switching to openSUSE not only extends the life of your current hardware but also gives you access to a modern, secure gaming platform. By adopting openSUSE, you avoid contributing to e-waste caused by discarding perfectly functional machines and take advantage of a free, open-source operating system tailored for performance and reliability.
This is part of a series on Upgrade to Freedom where we offer reasons to transition from Windows to Linux.
Tue, Jan 14th, 2025


OpenVINO with Generative AI
The openSUSE Innovator initiative and the Intel Innovator program play a crucial role in ensuring that the openVINO repository remains up to date for the openSUSE Linux distribution community, which I continually to strive to help.
OpenVINO (Open Visual Inference and Neural Network Optimization) is one of the most crucial tools in the AI ecosystem, especially for applications requiring optimized performance for deep learning model inference. The 2024.6.0 release that arrived in Tumbleweed brings significant advancements in compatibility, optimizations and support for complex models, including those used in Generative AI, such as Large Language Models (LLMs).
The Importance of OpenVINO on openSUSE Linux
- Seamless Hardware and Software Integration: OpenVINO provides native acceleration for Intel CPUs and GPUs while maintaining flexibility to support other platforms. When paired with openSUSE Linux’s optimized kernel and advanced library compatibility, OpenVINO reaches its full potential.
- Generative AI in Open Source: In the era of Generative AI, tools like OpenVINO democratize access to cutting-edge technologies and allow developers of all levels to create advanced solutions directly on openSUSE without requiring expensive proprietary hardware.
- Performance and Efficiency: OpenVINO significantly reduces inference times and resource usage, which is a critical feature for LLM-based applications processing large amounts of data in real-time.
- Developer Simplicity: One of OpenVINO’s greatest advantages is its accessibility. It enables even beginner developers to build robust applications with minimal code while still offering flexibility and customization for advanced projects.
Building an LLM Application in 3 Lines of Code
With OpenVINO, creating an application using a generative language model is as simple as:
import openvino_genai as ov_genai
pipe = ov_genai.LLMPipeline("TinyLlama-1.1B-Chat-v1.0/", "CPU")
print(pipe.generate("Openvino é", max_new_tokens=100, do_sample=False))
This simplicity highlights how OpenVINO allows seamless integration of Generative AI technologies into openSUSE Linux, combining optimization with ease of use.
Conclusion
The presence of OpenVINO on openSUSE Linux reinforces the role of open source in leading technological advancements in the AI era. It empowers businesses, independent developers and enthusiasts to build efficient, scalable and impactful applications. With tools like OpenVINO, openSUSE positions itself as a powerful platform for innovation in Generative AI.
Feedback and suggestions for the evolution of work can be sent to Alessandro de Oliveira Faria (A.K.A. CABELO) cabelo@pensuse.org


pam-u2f: problematic PAM_IGNORE return values in pam_sm_authenticate() (CVE-2025-23013)
Table of Contents
- 1) Introduction
- 2) Improper use of
PAM_IGNORE
Return Values - 3) Upstream Bugfix
- 4) Remaining Uses of
PAM_IGNORE
- 5) Possible Workaround
- 6) Timeline
- 7) References
1) Introduction
The pam-u2f module allows to use U2F (Universal 2nd Factor) devices like YubiKeys in the PAM authentication stack. The hardware tokens can be used as a second authentication factor, or to allow password-less login.
We have been checking all PAM modules in the openSUSE code base for bad return
values. During this effort we found that improper use of PAM_IGNORE
return
values in the pam-u2f module implementation could allow bypass of the second
factor or password-less login without inserting the proper device.
This report is based on pam-u2f release 1.3.0.
2) Improper use of PAM_IGNORE
Return Values
PAM modules basically consist of a set of hook functions that are invoked by
libpam based on the active PAM stack configuration. Each PAM module function
returns an int
containing one of the PAM_*
return
values defined in the libpam headers. These return
values are vital for the outcome of a PAM authentication procedure, since
libpam reports authentication success or failure depending on the return
values encountered while processing the modules configured in the auth
management group of the active PAM stack configuration.
The main business logic of the pam-u2f module is found in function
pam_sm_authenticate()
, which contains multiple code
paths that will result in a PAM_IGNORE
return value. The following is a list
of the possible situations that can cause this to happen:
- if an error occurs in
gethostname()
. - if various memory allocation errors occur in
strdup()
orcalloc()
. - if
resolve_authfile_path()
fails (which fails ifasprintf()
fails). - if
pam_modutil_drop_priv()
orpam_modutil_regain_priv()
fail.
Returning PAM_IGNORE
signifies to libpam that the pam-u2f module shall not
contribute to the return value that the application obtains. If no module
reports a decisive return value, then libpam will report an authentication
failure by default. However, if any other module in the auth
management group returns PAM_SUCCESS
, and no module marks an error
condition, the overall result of the authentication will be “success”.
How exactly this can happen is explored in the rest of this section.
In the pam-u2f documentation two main use cases for the PAM module are stated:
# as a second factor
auth required pam_u2f.so authfile=/etc/u2f_mappings cue
# for password-less authentication:
auth sufficient pam_u2f.so authfile=/etc/u2f_mappings cue pinverification=1
In the “second factor” scenario, a PAM_IGNORE
return from pam-u2f means that
login will be possible without actually providing a second factor. The first
factor authentication module (typically something like pam_unix
) will set a
PAM_SUCCESS
return value, which will become the overall authentication
result.
In the “password-less” authentication scenario, when pam-u2f is used
exclusively for authentication, a PAM_IGNORE
return could mean that login
will succeed without providing any authentication at all. The precondition for
this is that another module in the auth
management group returns
PAM_SUCCESS
. There exist utility modules that don’t actually authenticate
but perform helper functions or enforce policy. An example is the
pam_faillock
module, which can be added to the
auth
management group to record failed authentication attempts and lock the
account for a certain time if too many failed attempts occur. This module will
return PAM_SUCCESS
when running in “preauth” mode and if the maximum number
of failed attempts has not been reached yet. In such a case PAM_SUCCESS
would become the overall authentication result when pam-u2f returns
PAM_IGNORE
.
An attacker can attempt to provoke a situation that results in a PAM_IGNORE
return value in pam-u2f to achieve one of these outcomes. In particular,
provoking an out-of-memory situation comes to mind - for example if a local
attacker already has user level access and wants to escalate privileges via
sudo
or su
.
3) Upstream Bugfix
We suggested to upstream to change the problematic PAM_IGNORE
return values
to others that mark the authentication as failed, e.g. PAM_BUF_ERR
for
memory allocation errors or PAM_ABORT
for other critical errors. Furthermore
we suggested to harmonize the error handling in the affected function, because
different styles of return values have been used in
the retval
variable (PAM_*
constants mixed with literal integers returned
from sub-functions).
Upstream implemented a bugfix along these lines, which is available in commit a96ef17f74b8e4. This bugfix is available as part of release 1.3.1. Yubico also offer their own security advisory for this CVE.
4) Remaining Uses of PAM_IGNORE
PAM_IGNORE
should only be used in clearly defined circumstances, like when
necessary configuration for the PAM module is missing. Even then, this
behaviour ideally should require an explicit opt-in by administrators, by
passing configuration settings to the module’s PAM configuration line.
Two such cases remain in pam-u2f with the bugfix applied. These cases trigger if no auth file exists for the user to be authenticated and if the “nouserok” option has been passed to the PAM module.
5) Possible Workaround
If applying the bugfix is not possible right away, then a temporary workaround
for the issue can be applied via the PAM stack configuration by changing
the pam_u2f
line as follows:
auth [success=ok default=bad] pam_u2f.so [...]
This way even a PAM_IGNORE
return in pam_u2f.so
will be considered a bad
authentication result by libpam.
6) Timeline
2024-11-20 | We reported the issue to Yubico security, offering coordinated disclosure. |
2024-11-22 | Yubico security accepted coordinated disclosure and stated that they are working on a fix. |
2024-12-06 | Yubico security notified us that a bugfix release is planned in early January. |
2024-12-12 | Yubico security shared their suggested bugfix with us. We sent back minor suggestions for improvement. |
2025-01-08 | Yubico security informed us of the release date of 2025-01-14. |
2025-01-10 | Yubico security shared the CVE identifier and their formal security advisory with us. |
2025-01-14 | The upstream bugfix release 1.3.1 has been published as planned. |