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

Commitcd5f2a3

Browse files
committed
Reject substituting extension schemas or owners matching ["$'\].
Substituting such values in extension scripts facilitated SQL injectionwhen @extowner@, @extschema@, or @extschema:...@ appeared inside aquoting construct (dollar quoting, '', or ""). No bundled extension wasvulnerable. Vulnerable uses do appear in a documentation example and innon-bundled extensions. Hence, the attack prerequisite was anadministrator having installed files of a vulnerable, trusted,non-bundled extension. Subject to that prerequisite, this enabled anattacker having database-level CREATE privilege to execute arbitrarycode as the bootstrap superuser. By blocking this attack in the coreserver, there's no need to modify individual extensions. Back-patch tov11 (all supported versions).Reported by Micah Gate, Valerie Woolard, Tim Carey-Smith, and ChristophBerg.Security:CVE-2023-39417
1 parent2bdd7b2 commitcd5f2a3

File tree

7 files changed

+79
-15
lines changed

7 files changed

+79
-15
lines changed

‎src/backend/commands/extension.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -996,6 +996,16 @@ execute_extension_script(Oid extensionOid, ExtensionControlFile *control,
996996
char*c_sql=read_extension_script_file(control,filename);
997997
Datumt_sql;
998998

999+
/*
1000+
* We filter each substitution through quote_identifier(). When the
1001+
* arg contains one of the following characters, no one collection of
1002+
* quoting can work inside $$dollar-quoted string literals$$,
1003+
* 'single-quoted string literals', and outside of any literal. To
1004+
* avoid a security snare for extension authors, error on substitution
1005+
* for arguments containing these.
1006+
*/
1007+
constchar*quoting_relevant_chars="\"$'\\";
1008+
9991009
/* We use various functions that want to operate on text datums */
10001010
t_sql=CStringGetTextDatum(c_sql);
10011011

@@ -1025,6 +1035,11 @@ execute_extension_script(Oid extensionOid, ExtensionControlFile *control,
10251035
t_sql,
10261036
CStringGetTextDatum("@extowner@"),
10271037
CStringGetTextDatum(qUserName));
1038+
if (strpbrk(userName,quoting_relevant_chars))
1039+
ereport(ERROR,
1040+
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1041+
errmsg("invalid character in extension owner: must not contain any of \"%s\"",
1042+
quoting_relevant_chars)));
10281043
}
10291044

10301045
/*
@@ -1036,13 +1051,19 @@ execute_extension_script(Oid extensionOid, ExtensionControlFile *control,
10361051
*/
10371052
if (!control->relocatable)
10381053
{
1054+
Datumold=t_sql;
10391055
constchar*qSchemaName=quote_identifier(schemaName);
10401056

10411057
t_sql=DirectFunctionCall3Coll(replace_text,
10421058
C_COLLATION_OID,
10431059
t_sql,
10441060
CStringGetTextDatum("@extschema@"),
10451061
CStringGetTextDatum(qSchemaName));
1062+
if (t_sql!=old&&strpbrk(schemaName,quoting_relevant_chars))
1063+
ereport(ERROR,
1064+
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1065+
errmsg("invalid character in extension \"%s\" schema: must not contain any of \"%s\"",
1066+
control->name,quoting_relevant_chars)));
10461067
}
10471068

10481069
/*
@@ -1052,6 +1073,7 @@ execute_extension_script(Oid extensionOid, ExtensionControlFile *control,
10521073
Assert(list_length(control->requires)==list_length(requiredSchemas));
10531074
forboth(lc,control->requires,lc2,requiredSchemas)
10541075
{
1076+
Datumold=t_sql;
10551077
char*reqextname= (char*)lfirst(lc);
10561078
Oidreqschema=lfirst_oid(lc2);
10571079
char*schemaName=get_namespace_name(reqschema);
@@ -1064,6 +1086,11 @@ execute_extension_script(Oid extensionOid, ExtensionControlFile *control,
10641086
t_sql,
10651087
CStringGetTextDatum(repltoken),
10661088
CStringGetTextDatum(qSchemaName));
1089+
if (t_sql!=old&&strpbrk(schemaName,quoting_relevant_chars))
1090+
ereport(ERROR,
1091+
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1092+
errmsg("invalid character in extension \"%s\" schema: must not contain any of \"%s\"",
1093+
reqextname,quoting_relevant_chars)));
10671094
}
10681095

10691096
/*

‎src/test/modules/test_extensions/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ PGFILEDESC = "test_extensions - regression testing for EXTENSION support"
66
EXTENSION = test_ext1 test_ext2 test_ext3 test_ext4 test_ext5 test_ext6\
77
test_ext7 test_ext8 test_ext_cine test_ext_cor\
88
test_ext_cyclic1 test_ext_cyclic2\
9+
test_ext_extschema\
910
test_ext_evttrig\
1011
test_ext_req_schema1 test_ext_req_schema2 test_ext_req_schema3
1112

@@ -15,6 +16,7 @@ DATA = test_ext1--1.0.sql test_ext2--1.0.sql test_ext3--1.0.sql \
1516
test_ext_cine--1.0.sql test_ext_cine--1.0--1.1.sql\
1617
test_ext_cor--1.0.sql\
1718
test_ext_cyclic1--1.0.sql test_ext_cyclic2--1.0.sql\
19+
test_ext_extschema--1.0.sql\
1820
test_ext_evttrig--1.0.sql test_ext_evttrig--1.0--2.0.sql\
1921
test_ext_req_schema1--1.0.sql\
2022
test_ext_req_schema2--1.0.sql\

‎src/test/modules/test_extensions/expected/test_extensions.out

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
CREATE SCHEMA has$dollar;
12
-- test some errors
23
CREATE EXTENSION test_ext1;
34
ERROR: required extension "test_ext2" is not installed
@@ -6,35 +7,35 @@ CREATE EXTENSION test_ext1 SCHEMA test_ext1;
67
ERROR: schema "test_ext1" does not exist
78
CREATE EXTENSION test_ext1 SCHEMA test_ext;
89
ERROR: schema "test_ext" does not exist
9-
CREATE SCHEMA test_ext;
10-
CREATE EXTENSION test_ext1 SCHEMA test_ext;
10+
CREATE EXTENSION test_ext1 SCHEMA has$dollar;
1111
ERROR: extension "test_ext1" must be installed in schema "test_ext1"
1212
-- finally success
13-
CREATE EXTENSION test_ext1 SCHEMAtest_ext CASCADE;
13+
CREATE EXTENSION test_ext1 SCHEMAhas$dollar CASCADE;
1414
NOTICE: installing required extension "test_ext2"
1515
NOTICE: installing required extension "test_ext3"
1616
NOTICE: installing required extension "test_ext5"
1717
NOTICE: installing required extension "test_ext4"
1818
SELECT extname, nspname, extversion, extrelocatable FROM pg_extension e, pg_namespace n WHERE extname LIKE 'test_ext%' AND e.extnamespace = n.oid ORDER BY 1;
19-
extname | nspname | extversion | extrelocatable
20-
-----------+-----------+------------+----------------
21-
test_ext1 | test_ext1 | 1.0 | f
22-
test_ext2 |test_ext | 1.0 | t
23-
test_ext3 |test_ext | 1.0 | t
24-
test_ext4 |test_ext | 1.0 | t
25-
test_ext5 |test_ext | 1.0 | t
19+
extname | nspname| extversion | extrelocatable
20+
-----------+------------+------------+----------------
21+
test_ext1 | test_ext1| 1.0 | f
22+
test_ext2 |has$dollar | 1.0 | t
23+
test_ext3 |has$dollar | 1.0 | t
24+
test_ext4 |has$dollar | 1.0 | t
25+
test_ext5 |has$dollar | 1.0 | t
2626
(5 rows)
2727

2828
CREATE EXTENSION test_ext_cyclic1 CASCADE;
2929
NOTICE: installing required extension "test_ext_cyclic2"
3030
ERROR: cyclic dependency detected between extensions "test_ext_cyclic1" and "test_ext_cyclic2"
31-
DROP SCHEMAtest_ext CASCADE;
31+
DROP SCHEMAhas$dollar CASCADE;
3232
NOTICE: drop cascades to 5 other objects
3333
DETAIL: drop cascades to extension test_ext3
3434
drop cascades to extension test_ext5
3535
drop cascades to extension test_ext2
3636
drop cascades to extension test_ext4
3737
drop cascades to extension test_ext1
38+
CREATE SCHEMA has$dollar;
3839
CREATE EXTENSION test_ext6;
3940
DROP EXTENSION test_ext6;
4041
CREATE EXTENSION test_ext6;
@@ -312,6 +313,13 @@ Objects in extension "test_ext_cine"
312313
table ext_cine_tab3
313314
(9 rows)
314315

316+
--
317+
-- Test @extschema@ syntax.
318+
--
319+
CREATE SCHEMA "has space";
320+
CREATE EXTENSION test_ext_extschema SCHEMA has$dollar;
321+
ERROR: invalid character in extension "test_ext_extschema" schema: must not contain any of ""$'\"
322+
CREATE EXTENSION test_ext_extschema SCHEMA "has space";
315323
--
316324
-- Test extension with objects outside the extension's schema.
317325
--
@@ -358,6 +366,11 @@ DROP SCHEMA test_func_dep3;
358366
--
359367
-- Test @extschema:extname@ syntax and no_relocate option
360368
--
369+
CREATE EXTENSION test_ext_req_schema1 SCHEMA has$dollar;
370+
CREATE EXTENSION test_ext_req_schema3 CASCADE;
371+
NOTICE: installing required extension "test_ext_req_schema2"
372+
ERROR: invalid character in extension "test_ext_req_schema1" schema: must not contain any of ""$'\"
373+
DROP EXTENSION test_ext_req_schema1;
361374
CREATE SCHEMA test_s_dep;
362375
CREATE EXTENSION test_ext_req_schema1 SCHEMA test_s_dep;
363376
CREATE EXTENSION test_ext_req_schema3 CASCADE;

‎src/test/modules/test_extensions/meson.build

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ test_install_data += files(
2727
'test_ext_cyclic1.control',
2828
'test_ext_cyclic2--1.0.sql',
2929
'test_ext_cyclic2.control',
30+
'test_ext_extschema--1.0.sql',
31+
'test_ext_extschema.control',
3032
'test_ext_evttrig--1.0--2.0.sql',
3133
'test_ext_evttrig--1.0.sql',
3234
'test_ext_evttrig.control',

‎src/test/modules/test_extensions/sql/test_extensions.sql

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,20 @@
1+
CREATESCHEMAhas$dollar;
2+
13
-- test some errors
24
CREATE EXTENSION test_ext1;
35
CREATE EXTENSION test_ext1 SCHEMA test_ext1;
46
CREATE EXTENSION test_ext1 SCHEMA test_ext;
5-
CREATESCHEMAtest_ext;
6-
CREATE EXTENSION test_ext1 SCHEMA test_ext;
7+
CREATE EXTENSION test_ext1 SCHEMA has$dollar;
78

89
-- finally success
9-
CREATE EXTENSION test_ext1 SCHEMAtest_ext CASCADE;
10+
CREATE EXTENSION test_ext1 SCHEMAhas$dollar CASCADE;
1011

1112
SELECT extname, nspname, extversion, extrelocatableFROM pg_extension e, pg_namespace nWHERE extnameLIKE'test_ext%'ANDe.extnamespace=n.oidORDER BY1;
1213

1314
CREATE EXTENSION test_ext_cyclic1 CASCADE;
1415

15-
DROPSCHEMA test_ext CASCADE;
16+
DROPSCHEMA has$dollar CASCADE;
17+
CREATESCHEMAhas$dollar;
1618

1719
CREATE EXTENSION test_ext6;
1820
DROP EXTENSION test_ext6;
@@ -210,6 +212,13 @@ ALTER EXTENSION test_ext_cine UPDATE TO '1.1';
210212

211213
\dx+ test_ext_cine
212214

215+
--
216+
-- Test @extschema@ syntax.
217+
--
218+
CREATE SCHEMA"has space";
219+
CREATE EXTENSION test_ext_extschema SCHEMA has$dollar;
220+
CREATE EXTENSION test_ext_extschema SCHEMA"has space";
221+
213222
--
214223
-- Test extension with objects outside the extension's schema.
215224
--
@@ -245,6 +254,9 @@ DROP SCHEMA test_func_dep3;
245254
--
246255
-- Test @extschema:extname@ syntax and no_relocate option
247256
--
257+
CREATE EXTENSION test_ext_req_schema1 SCHEMA has$dollar;
258+
CREATE EXTENSION test_ext_req_schema3 CASCADE;
259+
DROP EXTENSION test_ext_req_schema1;
248260
CREATESCHEMAtest_s_dep;
249261
CREATE EXTENSION test_ext_req_schema1 SCHEMA test_s_dep;
250262
CREATE EXTENSION test_ext_req_schema3 CASCADE;
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/* src/test/modules/test_extensions/test_ext_extschema--1.0.sql*/
2+
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
3+
\echo Use"CREATE EXTENSION test_ext_extschema" to load this file. \quit
4+
5+
SELECT1AS @extschema@;
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
comment = 'test @extschema@'
2+
default_version = '1.0'
3+
relocatable = false

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp