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

Commit67a2fbb

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 parent13a67ce commit67a2fbb

22 files changed

+435
-13
lines changed

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

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

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

101113
<refsect1 id="pg-dump-options">
@@ -1252,6 +1264,29 @@ PostgreSQL documentation
12521264
</listitem>
12531265
</varlistentry>
12541266

1267+
<varlistentry>
1268+
<term><option>--restrict-key=<replaceable class="parameter">restrict_key</replaceable></option></term>
1269+
<listitem>
1270+
<para>
1271+
Use the provided string as the <application>psql</application>
1272+
<command>\restrict</command> key in the dump output. This can only be
1273+
specified for plain-text dumps, i.e., when <option>--format</option> is
1274+
set to <literal>plain</literal> or the <option>--format</option> option
1275+
is omitted. If no restrict key is specified,
1276+
<application>pg_dump</application> will generate a random one as
1277+
needed. Keys may contain only alphanumeric characters.
1278+
</para>
1279+
<para>
1280+
This option is primarily intended for testing purposes and other
1281+
scenarios that require repeatable output (e.g., comparing dump files).
1282+
It is not recommended for general use, as a malicious server with
1283+
advance knowledge of the key may be able to inject arbitrary code that
1284+
will be executed on the machine that runs
1285+
<application>psql</application> with the dump output.
1286+
</para>
1287+
</listitem>
1288+
</varlistentry>
1289+
12551290
<varlistentry>
12561291
<term><option>--rows-per-insert=<replaceable class="parameter">nrows</replaceable></option></term>
12571292
<listitem>

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

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

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

7181
<refsect1>
@@ -591,6 +601,26 @@ exclude database <replaceable class="parameter">PATTERN</replaceable>
591601
</listitem>
592602
</varlistentry>
593603

604+
<varlistentry>
605+
<term><option>--restrict-key=<replaceable class="parameter">restrict_key</replaceable></option></term>
606+
<listitem>
607+
<para>
608+
Use the provided string as the <application>psql</application>
609+
<command>\restrict</command> key in the dump output. If no restrict
610+
key is specified, <application>pg_dumpall</application> will generate a
611+
random one as needed. Keys may contain only alphanumeric characters.
612+
</para>
613+
<para>
614+
This option is primarily intended for testing purposes and other
615+
scenarios that require repeatable output (e.g., comparing dump files).
616+
It is not recommended for general use, as a malicious server with
617+
advance knowledge of the key may be able to inject arbitrary code that
618+
will be executed on the machine that runs
619+
<application>psql</application> with the dump output.
620+
</para>
621+
</listitem>
622+
</varlistentry>
623+
594624
<varlistentry>
595625
<term><option>--rows-per-insert=<replaceable class="parameter">nrows</replaceable></option></term>
596626
<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">
@@ -796,6 +808,28 @@ PostgreSQL documentation
796808
</listitem>
797809
</varlistentry>
798810

811+
<varlistentry>
812+
<term><option>--restrict-key=<replaceable class="parameter">restrict_key</replaceable></option></term>
813+
<listitem>
814+
<para>
815+
Use the provided string as the <application>psql</application>
816+
<command>\restrict</command> key in the dump output. This can only be
817+
specified for SQL script output, i.e., when the <option>--file</option>
818+
option is used. If no restrict key is specified,
819+
<application>pg_restore</application> will generate a random one as
820+
needed. Keys may contain only alphanumeric characters.
821+
</para>
822+
<para>
823+
This option is primarily intended for testing purposes and other
824+
scenarios that require repeatable output (e.g., comparing dump files).
825+
It is not recommended for general use, as a malicious server with
826+
advance knowledge of the key may be able to inject arbitrary code that
827+
will be executed on the machine that runs
828+
<application>psql</application> with the dump output.
829+
</para>
830+
</listitem>
831+
</varlistentry>
832+
799833
<varlistentry>
800834
<term><option>--section=<replaceable class="parameter">sectionname</replaceable></option></term>
801835
<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
<application>pg_upgrade</application> supports upgrades from 9.2.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
@@ -3551,6 +3551,24 @@ SELECT $1 \parse stmt1
35513551
</varlistentry>
35523552

35533553

3554+
<varlistentry id="app-psql-meta-command-restrict">
3555+
<term><literal>\restrict <replaceable class="parameter">restrict_key</replaceable></literal></term>
3556+
<listitem>
3557+
<para>
3558+
Enter "restricted" mode with the provided key. In this mode, the only
3559+
allowed meta-command is <command>\unrestrict</command>, to exit
3560+
restricted mode. The key may contain only alphanumeric characters.
3561+
</para>
3562+
<para>
3563+
This command is primarily intended for use in plain-text dumps
3564+
generated by <application>pg_dump</application>,
3565+
<application>pg_dumpall</application>, and
3566+
<application>pg_restore</application>, but it may be useful elsewhere.
3567+
</para>
3568+
</listitem>
3569+
</varlistentry>
3570+
3571+
35543572
<varlistentry id="app-psql-meta-command-s">
35553573
<term><literal>\s [ <replaceable class="parameter">filename</replaceable> ]</literal></term>
35563574
<listitem>
@@ -3802,6 +3820,24 @@ SELECT 1 \bind \sendpipeline
38023820
</varlistentry>
38033821

38043822

3823+
<varlistentry id="app-psql-meta-command-unrestrict">
3824+
<term><literal>\unrestrict <replaceable class="parameter">restrict_key</replaceable></literal></term>
3825+
<listitem>
3826+
<para>
3827+
Exit "restricted" mode (i.e., where all other meta-commands are
3828+
blocked), provided the specified key matches the one given to
3829+
<command>\restrict</command> when restricted mode was entered.
3830+
</para>
3831+
<para>
3832+
This command is primarily intended for use in plain-text dumps
3833+
generated by <application>pg_dump</application>,
3834+
<application>pg_dumpall</application>, and
3835+
<application>pg_restore</application>, but it may be useful elsewhere.
3836+
</para>
3837+
</listitem>
3838+
</varlistentry>
3839+
3840+
38053841
<varlistentry id="app-psql-meta-command-unset">
38063842
<term><literal>\unset <replaceable class="parameter">name</replaceable></literal></term>
38073843

‎src/bin/pg_combinebackup/t/002_compare_backups.pl‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@
174174
$pitr1->command_ok(
175175
[
176176
'pg_dumpall',
177+
'--restrict-key=test',
177178
'--no-sync',
178179
'--no-unlogged-table-data',
179180
'--file'=>$dump1,
@@ -183,6 +184,7 @@
183184
$pitr2->command_ok(
184185
[
185186
'pg_dumpall',
187+
'--restrict-key=test',
186188
'--no-sync',
187189
'--no-unlogged-table-data',
188190
'--file'=>$dump2,

‎src/bin/pg_dump/dumputils.c‎

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

24+
staticconstcharrestrict_chars[]="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
2425

2526
staticboolparseAclItem(constchar*item,constchar*type,
2627
constchar*name,constchar*subname,intremoteVersion,
@@ -957,3 +958,40 @@ create_or_open_dir(const char *dirname)
957958
pg_fatal("directory \"%s\" is not empty",dirname);
958959
}
959960
}
961+
962+
/*
963+
* Generates a valid restrict key (i.e., an alphanumeric string) for use with
964+
* psql's \restrict and \unrestrict meta-commands. For safety, the value is
965+
* chosen at random.
966+
*/
967+
char*
968+
generate_restrict_key(void)
969+
{
970+
uint8buf[64];
971+
char*ret=palloc(sizeof(buf));
972+
973+
if (!pg_strong_random(buf,sizeof(buf)))
974+
returnNULL;
975+
976+
for (inti=0;i<sizeof(buf)-1;i++)
977+
{
978+
uint8idx=buf[i] %strlen(restrict_chars);
979+
980+
ret[i]=restrict_chars[idx];
981+
}
982+
ret[sizeof(buf)-1]='\0';
983+
984+
returnret;
985+
}
986+
987+
/*
988+
* Checks that a given restrict key (intended for use with psql's \restrict and
989+
* \unrestrict meta-commands) contains only alphanumeric characters.
990+
*/
991+
bool
992+
valid_restrict_key(constchar*restrict_key)
993+
{
994+
returnrestrict_key!=NULL&&
995+
restrict_key[0]!='\0'&&
996+
strspn(restrict_key,restrict_chars)==strlen(restrict_key);
997+
}

‎src/bin/pg_dump/dumputils.h‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,4 +65,7 @@ extern void makeAlterConfigCommand(PGconn *conn, const char *configitem,
6565
PQExpBufferbuf);
6666
externvoidcreate_or_open_dir(constchar*dirname);
6767

68+
externchar*generate_restrict_key(void);
69+
externboolvalid_restrict_key(constchar*restrict_key);
70+
6871
#endif/* DUMPUTILS_H */

‎src/bin/pg_dump/pg_backup.h‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,8 @@ typedef struct _restoreOptions
163163
booldumpSchema;
164164
booldumpData;
165165
booldumpStatistics;
166+
167+
char*restrict_key;
166168
}RestoreOptions;
167169

168170
typedefstruct_dumpOptions
@@ -213,6 +215,8 @@ typedef struct _dumpOptions
213215
booldumpSchema;
214216
booldumpData;
215217
booldumpStatistics;
218+
219+
char*restrict_key;
216220
}DumpOptions;
217221

218222
/*

‎src/bin/pg_dump/pg_backup_archiver.c‎

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ dumpOptionsFromRestoreOptions(RestoreOptions *ropt)
195195
dopt->include_everything=ropt->include_everything;
196196
dopt->enable_row_security=ropt->enable_row_security;
197197
dopt->sequence_data=ropt->sequence_data;
198+
dopt->restrict_key=ropt->restrict_key ?pg_strdup(ropt->restrict_key) :NULL;
198199

199200
returndopt;
200201
}
@@ -459,6 +460,17 @@ RestoreArchive(Archive *AHX)
459460

460461
ahprintf(AH,"--\n-- PostgreSQL database dump\n--\n\n");
461462

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

800812
ahprintf(AH,"--\n-- PostgreSQL database dump complete\n--\n\n");
801813

814+
/*
815+
* If generating plain-text output, exit restricted mode at the very end
816+
* of the script. This is not pro forma; in particular, pg_dumpall
817+
* requires this when transitioning from one database to another.
818+
*/
819+
if (ropt->restrict_key)
820+
ahprintf(AH,"\\unrestrict %s\n\n",ropt->restrict_key);
821+
802822
/*
803823
* Clean up & we're done.
804824
*/
@@ -3437,11 +3457,21 @@ _reconnectToDB(ArchiveHandle *AH, const char *dbname)
34373457
else
34383458
{
34393459
PQExpBufferDataconnectbuf;
3460+
RestoreOptions*ropt=AH->public.ropt;
3461+
3462+
/*
3463+
* We must temporarily exit restricted mode for \connect, etc.
3464+
* Anything added between this line and the following \restrict must
3465+
* be careful to avoid any possible meta-command injection vectors.
3466+
*/
3467+
ahprintf(AH,"\\unrestrict %s\n",ropt->restrict_key);
34403468

34413469
initPQExpBuffer(&connectbuf);
34423470
appendPsqlMetaConnect(&connectbuf,dbname);
3443-
ahprintf(AH,"%s\n",connectbuf.data);
3471+
ahprintf(AH,"%s",connectbuf.data);
34443472
termPQExpBuffer(&connectbuf);
3473+
3474+
ahprintf(AH,"\\restrict %s\n\n",ropt->restrict_key);
34453475
}
34463476

34473477
/*

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp