|
| 1 | +--- |
| 2 | +title: CVE-2025-2291 - PgBouncer "VALID UNTIL yesterday" |
| 3 | +navTitle: CVE-2025-2291 |
| 4 | +affectedProducts: All versions of PGBouncer prior to 1.24.1, TPA prior to 23.38.0, PGAI Cloud Service prior to May 12, 2025 |
| 5 | +--- |
| 6 | + |
| 7 | +First Published: 2025/04/30 |
| 8 | + |
| 9 | +Last Updated: 2025/04/30 |
| 10 | + |
| 11 | +Important: This is an assessment of the impact of CVE-2025-2291 on EDB products and services. It links to and details the CVE and supplements that information with EDB's own assessment. |
| 12 | + |
| 13 | +## Summary |
| 14 | + |
| 15 | +In PgBouncer, the `auth_query` mechanism does not consider the `VALID UNTIL` attribute set in PostgreSQL for user passwords. |
| 16 | +This oversight allows users to authenticate using expired passwords, potentially granting unauthorized access. The flaw was fixed in [PgBouncer 1.24.1](https://www.pgbouncer.org/changelog.html#pgbouncer-124x). |
| 17 | + |
| 18 | +## Vulnerability details |
| 19 | + |
| 20 | +CVE-ID: [CVE-2025-2291](https://nvd.nist.gov/vuln/detail/CVE-2025-2291) |
| 21 | + |
| 22 | +CVSS Base Score: 8.1 |
| 23 | + |
| 24 | +CVSS Temporal Score: Undefined |
| 25 | + |
| 26 | +CVSS Environmental Score: Undefined |
| 27 | + |
| 28 | +CVSS Vector: CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H |
| 29 | + |
| 30 | +## Affected products and versions |
| 31 | + |
| 32 | +* Community PgBouncer: All versions prior to 1.24.1 |
| 33 | +* EDB PgBouncer: All versions prior to 1.24.1 |
| 34 | +* EDB TPA: All versions prior to 23.38.0 |
| 35 | +* PGAI Cloud Service: All versions prior to May 12, 2025 release. |
| 36 | + |
| 37 | +## Remediation/fixes |
| 38 | + |
| 39 | +| Product | VRMF | Remediation/First Fix | |
| 40 | +|---------------|---------|---------------------------------------| |
| 41 | +| Community PgBouncer | 1.24.1 | Upgrade to Community PgBouncer 1.24.1 | |
| 42 | +| EDB PgBouncer | 1.24.1 | Upgrade to EDB PgBouncer 1.24.1 | |
| 43 | +| EDB TPA | 23.38.0 | Upgrade to TPA 23.38.0 when available | |
| 44 | +| PGAI Cloud Service | May 12, 2025 | Resolved by May 12, 2025 Release | |
| 45 | + |
| 46 | +For TPA we recommend applying the following mitigation measures until the upcoming version with a fix is available: |
| 47 | + |
| 48 | +Two solutions are available: |
| 49 | + |
| 50 | +The first and preferred solution is to create a `postgres-config-final` hook that will be run at the end of the existing `tpaexec deploy` command. The hook should be placed in the cluster directory under the `hooks/` folder and should be named `postgres-config-final.yml`, with the following content. |
| 51 | + |
| 52 | +```yaml |
| 53 | +--- |
| 54 | + |
| 55 | +- name: Mitigate CVE-2025-2291 |
| 56 | + block: |
| 57 | + - name: Edit function pgbouncer_get_auth() and grant execute permissions |
| 58 | + postgresql_query: |
| 59 | + conninfo: "{{ dsn|dbname(item) }}" |
| 60 | + queries: |
| 61 | + - text: > |
| 62 | + CREATE OR REPLACE FUNCTION pg_catalog.pgbouncer_get_auth(p_usename TEXT) |
| 63 | + RETURNS TABLE(username TEXT, password TEXT) AS $$ |
| 64 | + BEGIN |
| 65 | + RETURN QUERY |
| 66 | + SELECT usename::TEXT, CASE WHEN valuntil < now() THEN NULL ELSE passwd::TEXT END |
| 67 | + FROM pg_catalog.pg_shadow |
| 68 | + WHERE usename = p_usename; |
| 69 | + END; |
| 70 | + $$ LANGUAGE plpgsql SECURITY DEFINER |
| 71 | + - text: REVOKE ALL ON FUNCTION pg_catalog.pgbouncer_get_auth(p_usename TEXT) FROM PUBLIC |
| 72 | + - text: GRANT EXECUTE ON FUNCTION pg_catalog.pgbouncer_get_auth(p_usename TEXT) TO "{{ pgbouncer_auth_user }}" |
| 73 | + changed_when: true |
| 74 | + become_user: "{{ postgres_user }}" |
| 75 | + become: yes |
| 76 | + with_items: "{{ cluster_facts.databases.keys()|list }}" |
| 77 | + vars: |
| 78 | + dbs: "{{ auth_function_dbs|default({}) }}" |
| 79 | + when: |
| 80 | + - item not in ['template0', 'bdr_supervisordb'] |
| 81 | + when: > |
| 82 | + postgres_users|json_query("[?username=='%s']" % pgbouncer_auth_user) != [] |
| 83 | + and task_selector|permits('pgbouncer') |
| 84 | +``` |
| 85 | +
|
| 86 | +Then you should run `tpaexec deploy <cluster_dir>` to apply the changes. |
| 87 | +This will modify the underlying function used by auth_query setting in PgBouncer to take password validity into account. |
| 88 | + |
| 89 | +The second solution is to apply the same modification via a custom command: |
| 90 | +The custom command file should be created as `mitigate-CVE-2025-2291.yml` in the `commands/` folder inside the TPA cluster directory with the following content: |
| 91 | + |
| 92 | +```yaml |
| 93 | +--- |
| 94 | +
|
| 95 | +- import_playbook: "{{ tpa_dir }}/architectures/lib/init.yml" |
| 96 | + tags: always |
| 97 | +
|
| 98 | +- name: Perform custom command tasks |
| 99 | + hosts: all |
| 100 | + tasks: |
| 101 | + - name: Mitigate CVE-2025-2291 |
| 102 | + block: |
| 103 | + - name: Edit function pgbouncer_get_auth() and grant execute permissions |
| 104 | + postgresql_query: |
| 105 | + conninfo: "{{ dsn|dbname(item) }}" |
| 106 | + queries: |
| 107 | + - text: > |
| 108 | + CREATE OR REPLACE FUNCTION pg_catalog.pgbouncer_get_auth(p_usename TEXT) |
| 109 | + RETURNS TABLE(username TEXT, password TEXT) AS $$ |
| 110 | + BEGIN |
| 111 | + RETURN QUERY |
| 112 | + SELECT usename::TEXT, CASE WHEN valuntil < now() THEN NULL ELSE passwd::TEXT END |
| 113 | + FROM pg_catalog.pg_shadow |
| 114 | + WHERE usename = p_usename; |
| 115 | + END; |
| 116 | + $$ LANGUAGE plpgsql SECURITY DEFINER |
| 117 | + - text: REVOKE ALL ON FUNCTION pg_catalog.pgbouncer_get_auth(p_usename TEXT) FROM PUBLIC |
| 118 | + - text: GRANT EXECUTE ON FUNCTION pg_catalog.pgbouncer_get_auth(p_usename TEXT) TO "{{ pgbouncer_auth_user }}" |
| 119 | + changed_when: true |
| 120 | + become_user: "{{ postgres_user }}" |
| 121 | + become: yes |
| 122 | + with_items: "{{ cluster_facts.databases.keys()|list }}" |
| 123 | + vars: |
| 124 | + dbs: "{{ auth_function_dbs|default({}) }}" |
| 125 | + when: |
| 126 | + - item not in ['template0', 'bdr_supervisordb'] |
| 127 | + when: > |
| 128 | + "primary" in role |
| 129 | +``` |
| 130 | + |
| 131 | +The playbook can be run using the command |
| 132 | +`tpaexec mitigate-CVE-2025-2291 .` |
| 133 | + |
| 134 | +## References |
| 135 | + |
| 136 | +* [CVSS Calculator v3.1](https://www.first.org/cvss/calculator/3.1) |
| 137 | + |
| 138 | +## Related information |
| 139 | + |
| 140 | +* [EnterpriseDB](https://www.enterprisedb.com/) |
| 141 | +* [PgBouncer](https://www.pgbouncer.org/) |
| 142 | +* [EDB Blogs link](https://enterprisedb.com/blog/) |
| 143 | + |
| 144 | +## Acknowledgement |
| 145 | + |
| 146 | +Source: [PostgreSQL Security Team](https://www.postgresql.org/support/security/) |
| 147 | + |
| 148 | +## Change history |
| 149 | + |
| 150 | +* 30 April 2025: First published version of the document. |
| 151 | + |
| 152 | +## Disclaimer |
| 153 | + |
| 154 | +This document is provided on an "as is" basis and does not imply any kind of guarantee or warranty, including the warranties of merchantability or fitness for a particular use. Your use of the information on the document is at your own risk. EDB reserves the right to change or update this document at any time. Customers are therefore recommended to always view the latest version of this document. |
0 commit comments