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

Commit850caae

Browse files
committed
Convert newlines to spaces in names written in v11+ pg_dump comments.
Maliciously-crafted object names could achieve SQL injection duringrestore.CVE-2012-0868 fixed this class of problem at the time, butlater work reintroduced three cases. Commitbc8cd50 (back-patched to v11+ in2023-05 releases) introduced the pg_dump case. Commit6cbdbd9 (v12+) introduced the twopg_dumpall cases. Move sanitize_line(), unchanged, to dumputils.c sopg_dumpall has access to it in all supported versions. Back-patch tov13 (all supported versions).Reviewed-by: Robert Haas <robertmhaas@gmail.com>Reviewed-by: Nathan Bossart <nathandbossart@gmail.com>Backpatch-through: 13Security:CVE-2025-8715
1 parent1926342 commit850caae

File tree

7 files changed

+90
-41
lines changed

7 files changed

+90
-41
lines changed

‎src/bin/pg_dump/dumputils.c‎

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,43 @@ static void AddAcl(PQExpBuffer aclbuf, const char *keyword,
2929
constchar*subname);
3030

3131

32+
/*
33+
* Sanitize a string to be included in an SQL comment or TOC listing, by
34+
* replacing any newlines with spaces. This ensures each logical output line
35+
* is in fact one physical output line, to prevent corruption of the dump
36+
* (which could, in the worst case, present an SQL injection vulnerability
37+
* if someone were to incautiously load a dump containing objects with
38+
* maliciously crafted names).
39+
*
40+
* The result is a freshly malloc'd string. If the input string is NULL,
41+
* return a malloc'ed empty string, unless want_hyphen, in which case return a
42+
* malloc'ed hyphen.
43+
*
44+
* Note that we currently don't bother to quote names, meaning that the name
45+
* fields aren't automatically parseable. "pg_restore -L" doesn't care because
46+
* it only examines the dumpId field, but someday we might want to try harder.
47+
*/
48+
char*
49+
sanitize_line(constchar*str,boolwant_hyphen)
50+
{
51+
char*result;
52+
char*s;
53+
54+
if (!str)
55+
returnpg_strdup(want_hyphen ?"-" :"");
56+
57+
result=pg_strdup(str);
58+
59+
for (s=result;*s!='\0';s++)
60+
{
61+
if (*s=='\n'||*s=='\r')
62+
*s=' ';
63+
}
64+
65+
returnresult;
66+
}
67+
68+
3269
/*
3370
* Build GRANT/REVOKE command(s) for an object.
3471
*

‎src/bin/pg_dump/dumputils.h‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#endif
3737

3838

39+
externchar*sanitize_line(constchar*str,boolwant_hyphen);
3940
externboolbuildACLCommands(constchar*name,constchar*subname,constchar*nspname,
4041
constchar*type,constchar*acls,constchar*baseacls,
4142
constchar*owner,constchar*prefix,intremoteVersion,

‎src/bin/pg_dump/pg_backup_archiver.c‎

Lines changed: 0 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@ static ArchiveHandle *_allocAH(const char *FileSpec, const ArchiveFormat fmt,
6969
SetupWorkerPtrTypesetupWorkerPtr);
7070
staticvoid_getObjectDescription(PQExpBufferbuf,constTocEntry*te);
7171
staticvoid_printTocEntry(ArchiveHandle*AH,TocEntry*te,boolisData);
72-
staticchar*sanitize_line(constchar*str,boolwant_hyphen);
7372
staticvoid_doSetFixedOutputState(ArchiveHandle*AH);
7473
staticvoid_doSetSessionAuth(ArchiveHandle*AH,constchar*user);
7574
staticvoid_reconnectToDB(ArchiveHandle*AH,constchar*dbname);
@@ -3684,42 +3683,6 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, bool isData)
36843683
}
36853684
}
36863685

3687-
/*
3688-
* Sanitize a string to be included in an SQL comment or TOC listing, by
3689-
* replacing any newlines with spaces. This ensures each logical output line
3690-
* is in fact one physical output line, to prevent corruption of the dump
3691-
* (which could, in the worst case, present an SQL injection vulnerability
3692-
* if someone were to incautiously load a dump containing objects with
3693-
* maliciously crafted names).
3694-
*
3695-
* The result is a freshly malloc'd string. If the input string is NULL,
3696-
* return a malloc'ed empty string, unless want_hyphen, in which case return a
3697-
* malloc'ed hyphen.
3698-
*
3699-
* Note that we currently don't bother to quote names, meaning that the name
3700-
* fields aren't automatically parseable. "pg_restore -L" doesn't care because
3701-
* it only examines the dumpId field, but someday we might want to try harder.
3702-
*/
3703-
staticchar*
3704-
sanitize_line(constchar*str,boolwant_hyphen)
3705-
{
3706-
char*result;
3707-
char*s;
3708-
3709-
if (!str)
3710-
returnpg_strdup(want_hyphen ?"-" :"");
3711-
3712-
result=pg_strdup(str);
3713-
3714-
for (s=result;*s!='\0';s++)
3715-
{
3716-
if (*s=='\n'||*s=='\r')
3717-
*s=' ';
3718-
}
3719-
3720-
returnresult;
3721-
}
3722-
37233686
/*
37243687
* Write the file header for a custom-format archive
37253688
*/

‎src/bin/pg_dump/pg_dump.c‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2609,11 +2609,14 @@ dumpTableData(Archive *fout, const TableDataInfo *tdinfo)
26092609
forcePartitionRootLoad(tbinfo)))
26102610
{
26112611
TableInfo *parentTbinfo;
2612+
char *sanitized;
26122613

26132614
parentTbinfo = getRootTableInfo(tbinfo);
26142615
copyFrom = fmtQualifiedDumpable(parentTbinfo);
2616+
sanitized = sanitize_line(copyFrom, true);
26152617
printfPQExpBuffer(copyBuf, "-- load via partition root %s",
2616-
copyFrom);
2618+
sanitized);
2619+
free(sanitized);
26172620
tdDefn = pg_strdup(copyBuf->data);
26182621
}
26192622
else

‎src/bin/pg_dump/pg_dumpall.c‎

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1447,7 +1447,13 @@ dumpUserConfig(PGconn *conn, const char *username)
14471447
res=executeQuery(conn,buf->data);
14481448

14491449
if (PQntuples(res)>0)
1450-
fprintf(OPF,"\n--\n-- User Config \"%s\"\n--\n\n",username);
1450+
{
1451+
char*sanitized;
1452+
1453+
sanitized=sanitize_line(username, true);
1454+
fprintf(OPF,"\n--\n-- User Config \"%s\"\n--\n\n",sanitized);
1455+
free(sanitized);
1456+
}
14511457

14521458
for (inti=0;i<PQntuples(res);i++)
14531459
{
@@ -1549,6 +1555,7 @@ dumpDatabases(PGconn *conn)
15491555
for (i=0;i<PQntuples(res);i++)
15501556
{
15511557
char*dbname=PQgetvalue(res,i,0);
1558+
char*sanitized;
15521559
constchar*create_opts;
15531560
intret;
15541561

@@ -1565,7 +1572,9 @@ dumpDatabases(PGconn *conn)
15651572

15661573
pg_log_info("dumping database \"%s\"",dbname);
15671574

1568-
fprintf(OPF,"--\n-- Database \"%s\" dump\n--\n\n",dbname);
1575+
sanitized=sanitize_line(dbname, true);
1576+
fprintf(OPF,"--\n-- Database \"%s\" dump\n--\n\n",sanitized);
1577+
free(sanitized);
15691578

15701579
/*
15711580
* We assume that "template1" and "postgres" already exist in the

‎src/bin/pg_dump/t/002_pg_dump.pl‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1907,6 +1907,27 @@
19071907
},
19081908
},
19091909

1910+
'newline of role or table name in comment'=> {
1911+
create_sql=>qq{CREATE ROLE regress_newline;
1912+
ALTER ROLE regress_newline SET enable_seqscan = off;
1913+
ALTER ROLE regress_newline
1914+
RENAME TO "regress_newline\nattack";
1915+
1916+
-- meet getPartitioningInfo() "unsafe" condition
1917+
CREATE TYPE pp_colors AS
1918+
ENUM ('green', 'blue', 'black');
1919+
CREATE TABLE pp_enumpart (a pp_colors)
1920+
PARTITION BY HASH (a);
1921+
CREATE TABLE pp_enumpart1 PARTITION OF pp_enumpart
1922+
FOR VALUES WITH (MODULUS 2, REMAINDER 0);
1923+
CREATE TABLE pp_enumpart2 PARTITION OF pp_enumpart
1924+
FOR VALUES WITH (MODULUS 2, REMAINDER 1);
1925+
ALTER TABLE pp_enumpart
1926+
RENAME TO "pp_enumpart\nattack";},
1927+
regexp=>qr/\n--[^\n]*\nattack/s,
1928+
like=> {},
1929+
},
1930+
19101931
'CREATE DATABASE regression_invalid...'=> {
19111932
create_order=> 1,
19121933
create_sql=>q(

‎src/bin/pg_dump/t/003_pg_dump_with_server.pl‎

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,22 @@
1616
$node->init;
1717
$node->start;
1818

19+
#########################################
20+
# pg_dumpall: newline in database name
21+
22+
$node->safe_psql('postgres',qq{CREATE DATABASE "regress_\nattack"});
23+
24+
my (@cmd,$stdout,$stderr);
25+
@cmd = ("pg_dumpall",'--port'=>$port,'--exclude-database=postgres');
26+
print("# Running:" .join("",@cmd) ."\n");
27+
my$result = IPC::Run::run \@cmd,'>'=> \$stdout,'2>'=> \$stderr;
28+
ok(!$result,"newline in dbname: exit code not 0");
29+
like(
30+
$stderr,
31+
qr/shell command argument contains a newline/,
32+
"newline in dbname: stderr matches");
33+
unlike($stdout,qr/^attack/m,"newline in dbname: no comment escape");
34+
1935
#########################################
2036
# Verify that dumping foreign data includes only foreign tables of
2137
# matching servers
@@ -26,7 +42,6 @@
2642
$node->safe_psql('postgres',"CREATE SERVER s2 FOREIGN DATA WRAPPER dummy");
2743
$node->safe_psql('postgres',"CREATE FOREIGN TABLE t0 (a int) SERVER s0");
2844
$node->safe_psql('postgres',"CREATE FOREIGN TABLE t1 (a int) SERVER s1");
29-
my ($cmd,$stdout,$stderr,$result);
3045

3146
command_fails_like(
3247
["pg_dump",'-p',$port,'--include-foreign-data=s0','postgres' ],

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp