Published: June 2024
CVSS Score: 6.3 (Medium)
Affected Versions: PostgreSQL before 17.1, 16.5, 15.9, 14.14, 13.17, and 12.21
Reference: PostgreSQL Security Advisory
What is CVE-2024-10978?
CVE-2024-10978 is a security vulnerability in PostgreSQL that could let less-privileged database users access or update data rows they normally shouldn’t be able to. This flaw happens when the application hands over control to a different role or user in an SQL session using SET ROLE, SET SESSION AUTHORIZATION, or something similar.
If you’re running any supported version of PostgreSQL released before the following versions, you’re at risk:
12.21
Let's break down how this can go wrong, how it can lead to accidental data leaks or changes, and what you can do about it.
How Does the Exploit Work?
Applications often switch the database session’s identity for each user request, especially in multi-tenant SaaS setups. This is done using SET ROLE or SET SESSION AUTHORIZATION in PostgreSQL.
The danger:
Some applications use session parameters or session user ID within queries (e.g., current_setting('role'), current_user, session_user) to filter data. With CVE-2024-10978, a less-privileged user can make the app show or alter data as if a different user were logged in—bypassing the SET ROLE protection.
`
4. However, using crafted requests and PostgreSQL's internal behavior, an attacker might be able to see rows belonging to users other than themselves, or modify other users’ data.
Note: The attacker cannot pick which incorrect user ID is used—they just get someone else's data.
Sample Exploit Code
Below is a basic Python script demonstrating a possible exploit scenario. This assumes a simplified model for demonstration.
import psycopg2
conn = psycopg2.connect(
dbname='exampledb',
user='appuser',
password='secret',
host='localhost'
)
cur = conn.cursor()
# The application tries to safely switch to a less-privileged role
cur.execute("SET ROLE TO safe_user;")
# Attacker submits a request that uses a function depending on current user
# The vulnerability allows the attacker to see data of other users unpredictably
cur.execute("SELECT * FROM confidential_data WHERE owner = current_user;")
rows = cur.fetchall()
for row in rows:
print(row)
cur.close()
conn.close()
If the database is unpatched, the attacker could see rows belonging to other users, even though the SET ROLE should prevent that.
Privilege separation (between application users) depends on session or role switching.
- Your queries use session settings (e.g., current_user, current_setting('role')) to filter or update data.
Regulatory risk: Exposure of private or regulated data.
Keep in mind:
This does *not* let a remote attacker run arbitrary queries or escalate to full database access. The exploit doesn't grant control over *which* other user’s data is accessed, but *random* cross-access can still be damaging.
Upgrade PostgreSQL to the nearest fixed version.
2. Avoid using SET ROLE or SET SESSION AUTHORIZATION for vital privilege separation unless sure the database is fully up to date.
3. Change queries: Stop using session-dependent settings such as current_user in WHERE clauses for security checks; pass explicit user IDs via parameters instead.
Replace
SELECT * FROM confidential_data WHERE owner = current_user;
With
-- Use an explicit parameter from your application layer
SELECT * FROM confidential_data WHERE owner = %s;
And make sure %s is always set to the currently authenticated user's username, not derived from the session.
References
- PostgreSQL's Official CVE-2024-10978 Advisory
- NVD Vulnerability Entry
- PostgreSQL Release Notes
- psycopg2 Documentation
Conclusion
CVE-2024-10978 is a reminder that privilege management in database applications should be handled with care, and that session state isn’t always as isolated as it seems. Update your database ASAP, audit your queries, and never rely solely on SET ROLE or SET SESSION AUTHORIZATION for user isolation in your app logic unless you’re on a fixed version.
Timeline
Published on: 11/14/2024 13:15:04 UTC
Last modified on: 11/15/2024 13:58:08 UTC