Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitc204bd3

Browse files
Restrict psql meta-commands in plain-text dumps.
A malicious server could inject psql meta-commands into plain-textdump output (i.e., scripts created with pg_dump --format=plain,pg_dumpall, or pg_restore --file) that are run at restore time onthe machine running psql. To fix, introduce a new "restricted"mode in psql that blocks all meta-commands (except for \unrestrictto exit the mode), and teach pg_dump, pg_dumpall, and pg_restore touse this mode in plain-text dumps.While at it, encourage users to only restore dumps generated fromtrusted servers or to inspect it beforehand, since restoring causesthe destination to execute arbitrary code of the source superusers'choice. However, the client running the dump and restore needn'ttrust the source or destination superusers.Reported-by: Martin RakhmanovReported-by: Matthieu Denais <litezeraw@gmail.com>Reported-by: RyotaK <ryotak.mail@gmail.com>Suggested-by: Tom Lane <tgl@sss.pgh.pa.us>Reviewed-by: Noah Misch <noah@leadboat.com>Reviewed-by: Michael Paquier <michael@paquier.xyz>Reviewed-by: Peter Eisentraut <peter@eisentraut.org>Security:CVE-2025-8714Backpatch-through: 13
1 parent2179e60 commitc204bd3

File tree

19 files changed

+431
-10
lines changed

19 files changed

+431
-10
lines changed

‎doc/src/sgml/ref/pg_dump.sgml‎

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,18 @@ PostgreSQL documentation
9292
light of the limitations listed below.
9393
</para>
9494

95+
<warning>
96+
<para>
97+
Restoring a dump causes the destination to execute arbitrary code of the
98+
source superusers' choice. Partial dumps and partial restores do not limit
99+
that. If the source superusers are not trusted, the dumped SQL statements
100+
must be inspected before restoring. Non-plain-text dumps can be inspected
101+
by using <application>pg_restore</application>'s <option>--file</option>
102+
option. Note that the client running the dump and restore need not trust
103+
the source or destination superusers.
104+
</para>
105+
</warning>
106+
95107
</refsect1>
96108

97109
<refsect1 id="pg-dump-options">
@@ -984,6 +996,29 @@ PostgreSQL documentation
984996
</listitem>
985997
</varlistentry>
986998

999+
<varlistentry>
1000+
<term><option>--restrict-key=<replaceable class="parameter">restrict_key</replaceable></option></term>
1001+
<listitem>
1002+
<para>
1003+
Use the provided string as the <application>psql</application>
1004+
<command>\restrict</command> key in the dump output. This can only be
1005+
specified for plain-text dumps, i.e., when <option>--format</option> is
1006+
set to <literal>plain</literal> or the <option>--format</option> option
1007+
is omitted. If no restrict key is specified,
1008+
<application>pg_dump</application> will generate a random one as
1009+
needed. Keys may contain only alphanumeric characters.
1010+
</para>
1011+
<para>
1012+
This option is primarily intended for testing purposes and other
1013+
scenarios that require repeatable output (e.g., comparing dump files).
1014+
It is not recommended for general use, as a malicious server with
1015+
advance knowledge of the key may be able to inject arbitrary code that
1016+
will be executed on the machine that runs
1017+
<application>psql</application> with the dump output.
1018+
</para>
1019+
</listitem>
1020+
</varlistentry>
1021+
9871022
<varlistentry>
9881023
<term><option>--rows-per-insert=<replaceable class="parameter">nrows</replaceable></option></term>
9891024
<listitem>

‎doc/src/sgml/ref/pg_dumpall.sgml‎

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,16 @@ PostgreSQL documentation
6565
linkend="libpq-pgpass"/> for more information.
6666
</para>
6767

68+
<warning>
69+
<para>
70+
Restoring a dump causes the destination to execute arbitrary code of the
71+
source superusers' choice. Partial dumps and partial restores do not limit
72+
that. If the source superusers are not trusted, the dumped SQL statements
73+
must be inspected before restoring. Note that the client running the dump
74+
and restore need not trust the source or destination superusers.
75+
</para>
76+
</warning>
77+
6878
</refsect1>
6979

7080
<refsect1>
@@ -501,6 +511,26 @@ PostgreSQL documentation
501511
</listitem>
502512
</varlistentry>
503513

514+
<varlistentry>
515+
<term><option>--restrict-key=<replaceable class="parameter">restrict_key</replaceable></option></term>
516+
<listitem>
517+
<para>
518+
Use the provided string as the <application>psql</application>
519+
<command>\restrict</command> key in the dump output. If no restrict
520+
key is specified, <application>pg_dumpall</application> will generate a
521+
random one as needed. Keys may contain only alphanumeric characters.
522+
</para>
523+
<para>
524+
This option is primarily intended for testing purposes and other
525+
scenarios that require repeatable output (e.g., comparing dump files).
526+
It is not recommended for general use, as a malicious server with
527+
advance knowledge of the key may be able to inject arbitrary code that
528+
will be executed on the machine that runs
529+
<application>psql</application> with the dump output.
530+
</para>
531+
</listitem>
532+
</varlistentry>
533+
504534
<varlistentry>
505535
<term><option>--rows-per-insert=<replaceable class="parameter">nrows</replaceable></option></term>
506536
<listitem>

‎doc/src/sgml/ref/pg_restore.sgml‎

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,18 @@ PostgreSQL documentation
6868
<application>pg_restore</application> will not be able to load the data
6969
using <command>COPY</command> statements.
7070
</para>
71+
72+
<warning>
73+
<para>
74+
Restoring a dump causes the destination to execute arbitrary code of the
75+
source superusers' choice. Partial dumps and partial restores do not limit
76+
that. If the source superusers are not trusted, the dumped SQL statements
77+
must be inspected before restoring. Non-plain-text dumps can be inspected
78+
by using <application>pg_restore</application>'s <option>--file</option>
79+
option. Note that the client running the dump and restore need not trust
80+
the source or destination superusers.
81+
</para>
82+
</warning>
7183
</refsect1>
7284

7385
<refsect1 id="app-pgrestore-options">
@@ -659,6 +671,28 @@ PostgreSQL documentation
659671
</listitem>
660672
</varlistentry>
661673

674+
<varlistentry>
675+
<term><option>--restrict-key=<replaceable class="parameter">restrict_key</replaceable></option></term>
676+
<listitem>
677+
<para>
678+
Use the provided string as the <application>psql</application>
679+
<command>\restrict</command> key in the dump output. This can only be
680+
specified for SQL script output, i.e., when the <option>--file</option>
681+
option is used. If no restrict key is specified,
682+
<application>pg_restore</application> will generate a random one as
683+
needed. Keys may contain only alphanumeric characters.
684+
</para>
685+
<para>
686+
This option is primarily intended for testing purposes and other
687+
scenarios that require repeatable output (e.g., comparing dump files).
688+
It is not recommended for general use, as a malicious server with
689+
advance knowledge of the key may be able to inject arbitrary code that
690+
will be executed on the machine that runs
691+
<application>psql</application> with the dump output.
692+
</para>
693+
</listitem>
694+
</varlistentry>
695+
662696
<varlistentry>
663697
<term><option>--section=<replaceable class="parameter">sectionname</replaceable></option></term>
664698
<listitem>

‎doc/src/sgml/ref/pgupgrade.sgml‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,14 @@ PostgreSQL documentation
7070
pg_upgrade supports upgrades from 9.0.X and later to the current
7171
major release of <productname>PostgreSQL</productname>, including snapshot and beta releases.
7272
</para>
73+
74+
<warning>
75+
<para>
76+
Upgrading a cluster causes the destination to execute arbitrary code of the
77+
source superusers' choice. Ensure that the source superusers are trusted
78+
before upgrading.
79+
</para>
80+
</warning>
7381
</refsect1>
7482

7583
<refsect1>

‎doc/src/sgml/ref/psql-ref.sgml‎

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3147,6 +3147,24 @@ lo_import 152801
31473147
</varlistentry>
31483148

31493149

3150+
<varlistentry>
3151+
<term><literal>\restrict <replaceable class="parameter">restrict_key</replaceable></literal></term>
3152+
<listitem>
3153+
<para>
3154+
Enter "restricted" mode with the provided key. In this mode, the only
3155+
allowed meta-command is <command>\unrestrict</command>, to exit
3156+
restricted mode. The key may contain only alphanumeric characters.
3157+
</para>
3158+
<para>
3159+
This command is primarily intended for use in plain-text dumps
3160+
generated by <application>pg_dump</application>,
3161+
<application>pg_dumpall</application>, and
3162+
<application>pg_restore</application>, but it may be useful elsewhere.
3163+
</para>
3164+
</listitem>
3165+
</varlistentry>
3166+
3167+
31503168
<varlistentry>
31513169
<term><literal>\s [ <replaceable class="parameter">filename</replaceable> ]</literal></term>
31523170
<listitem>
@@ -3321,6 +3339,24 @@ testdb=&gt; <userinput>\setenv LESS -imx4F</userinput>
33213339
</varlistentry>
33223340

33233341

3342+
<varlistentry>
3343+
<term><literal>\unrestrict <replaceable class="parameter">restrict_key</replaceable></literal></term>
3344+
<listitem>
3345+
<para>
3346+
Exit "restricted" mode (i.e., where all other meta-commands are
3347+
blocked), provided the specified key matches the one given to
3348+
<command>\restrict</command> when restricted mode was entered.
3349+
</para>
3350+
<para>
3351+
This command is primarily intended for use in plain-text dumps
3352+
generated by <application>pg_dump</application>,
3353+
<application>pg_dumpall</application>, and
3354+
<application>pg_restore</application>, but it may be useful elsewhere.
3355+
</para>
3356+
</listitem>
3357+
</varlistentry>
3358+
3359+
33243360
<varlistentry>
33253361
<term><literal>\unset <replaceable class="parameter">name</replaceable></literal></term>
33263362

‎src/bin/pg_dump/dumputils.c‎

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include"dumputils.h"
2020
#include"fe_utils/string_utils.h"
2121

22+
staticconstcharrestrict_chars[]="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
2223

2324
staticboolparseAclItem(constchar*item,constchar*type,
2425
constchar*name,constchar*subname,intremoteVersion,
@@ -1079,3 +1080,40 @@ makeAlterConfigCommand(PGconn *conn, const char *configitem,
10791080

10801081
pg_free(mine);
10811082
}
1083+
1084+
/*
1085+
* Generates a valid restrict key (i.e., an alphanumeric string) for use with
1086+
* psql's \restrict and \unrestrict meta-commands. For safety, the value is
1087+
* chosen at random.
1088+
*/
1089+
char*
1090+
generate_restrict_key(void)
1091+
{
1092+
uint8buf[64];
1093+
char*ret=palloc(sizeof(buf));
1094+
1095+
if (!pg_strong_random(buf,sizeof(buf)))
1096+
returnNULL;
1097+
1098+
for (inti=0;i<sizeof(buf)-1;i++)
1099+
{
1100+
uint8idx=buf[i] %strlen(restrict_chars);
1101+
1102+
ret[i]=restrict_chars[idx];
1103+
}
1104+
ret[sizeof(buf)-1]='\0';
1105+
1106+
returnret;
1107+
}
1108+
1109+
/*
1110+
* Checks that a given restrict key (intended for use with psql's \restrict and
1111+
* \unrestrict meta-commands) contains only alphanumeric characters.
1112+
*/
1113+
bool
1114+
valid_restrict_key(constchar*restrict_key)
1115+
{
1116+
returnrestrict_key!=NULL&&
1117+
restrict_key[0]!='\0'&&
1118+
strspn(restrict_key,restrict_chars)==strlen(restrict_key);
1119+
}

‎src/bin/pg_dump/dumputils.h‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,7 @@ extern void makeAlterConfigCommand(PGconn *conn, const char *configitem,
6767
constchar*type2,constchar*name2,
6868
PQExpBufferbuf);
6969

70+
externchar*generate_restrict_key(void);
71+
externboolvalid_restrict_key(constchar*restrict_key);
72+
7073
#endif/* DUMPUTILS_H */

‎src/bin/pg_dump/pg_backup.h‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,8 @@ typedef struct _restoreOptions
134134
intenable_row_security;
135135
intsequence_data;/* dump sequence data even in schema-only mode */
136136
intbinary_upgrade;
137+
138+
char*restrict_key;
137139
}RestoreOptions;
138140

139141
typedefstruct_dumpOptions
@@ -179,6 +181,8 @@ typedef struct _dumpOptions
179181

180182
intsequence_data;/* dump sequence data even in schema-only mode */
181183
intdo_nothing;
184+
185+
char*restrict_key;
182186
}DumpOptions;
183187

184188
/*

‎src/bin/pg_dump/pg_backup_archiver.c‎

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ dumpOptionsFromRestoreOptions(RestoreOptions *ropt)
207207
dopt->include_everything=ropt->include_everything;
208208
dopt->enable_row_security=ropt->enable_row_security;
209209
dopt->sequence_data=ropt->sequence_data;
210+
dopt->restrict_key=ropt->restrict_key ?pg_strdup(ropt->restrict_key) :NULL;
210211

211212
returndopt;
212213
}
@@ -463,6 +464,17 @@ RestoreArchive(Archive *AHX)
463464

464465
ahprintf(AH,"--\n-- PostgreSQL database dump\n--\n\n");
465466

467+
/*
468+
* If generating plain-text output, enter restricted mode to block any
469+
* unexpected psql meta-commands. A malicious source might try to inject
470+
* a variety of things via bogus responses to queries. While we cannot
471+
* prevent such sources from affecting the destination at restore time, we
472+
* can block psql meta-commands so that the client machine that runs psql
473+
* with the dump output remains unaffected.
474+
*/
475+
if (ropt->restrict_key)
476+
ahprintf(AH,"\\restrict %s\n\n",ropt->restrict_key);
477+
466478
if (AH->archiveRemoteVersion)
467479
ahprintf(AH,"-- Dumped from database version %s\n",
468480
AH->archiveRemoteVersion);
@@ -734,6 +746,14 @@ RestoreArchive(Archive *AHX)
734746

735747
ahprintf(AH,"--\n-- PostgreSQL database dump complete\n--\n\n");
736748

749+
/*
750+
* If generating plain-text output, exit restricted mode at the very end
751+
* of the script. This is not pro forma; in particular, pg_dumpall
752+
* requires this when transitioning from one database to another.
753+
*/
754+
if (ropt->restrict_key)
755+
ahprintf(AH,"\\unrestrict %s\n\n",ropt->restrict_key);
756+
737757
/*
738758
* Clean up & we're done.
739759
*/
@@ -3239,11 +3259,21 @@ _reconnectToDB(ArchiveHandle *AH, const char *dbname)
32393259
else
32403260
{
32413261
PQExpBufferDataconnectbuf;
3262+
RestoreOptions*ropt=AH->public.ropt;
3263+
3264+
/*
3265+
* We must temporarily exit restricted mode for \connect, etc.
3266+
* Anything added between this line and the following \restrict must
3267+
* be careful to avoid any possible meta-command injection vectors.
3268+
*/
3269+
ahprintf(AH,"\\unrestrict %s\n",ropt->restrict_key);
32423270

32433271
initPQExpBuffer(&connectbuf);
32443272
appendPsqlMetaConnect(&connectbuf,dbname);
3245-
ahprintf(AH,"%s\n",connectbuf.data);
3273+
ahprintf(AH,"%s",connectbuf.data);
32463274
termPQExpBuffer(&connectbuf);
3275+
3276+
ahprintf(AH,"\\restrict %s\n\n",ropt->restrict_key);
32473277
}
32483278

32493279
/*

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp