Skip to content

Commit 3855e5b

Browse files
committed
Ignore attempts to \gset into specially treated variables.
If an interactive psql session used \gset when querying a compromised server, the attacker could execute arbitrary code as the operating system account running psql. Using a prefix not found among specially treated variables, e.g. every lowercase string, precluded the attack. Fix by issuing a warning and setting no variable for the column in question. Users wanting the old behavior can use a prefix and then a meta-command like "\set HISTSIZE :prefix_HISTSIZE". Back-patch to 9.5 (all supported versions). Reviewed by Robert Haas. Reported by Nick Cleaton. Security: CVE-2020-25696
1 parent ac8f624 commit 3855e5b

File tree

5 files changed

+41
-0
lines changed

5 files changed

+41
-0
lines changed

src/bin/psql/common.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -921,6 +921,13 @@ StoreQueryTuple(const PGresult *result)
921921
/* concatenate prefix and column name */
922922
varname = psprintf("%s%s", pset.gset_prefix, colname);
923923

924+
if (VariableHasHook(pset.vars, varname))
925+
{
926+
pg_log_warning("attempt to \\gset into specially treated variable \"%s\" ignored",
927+
varname);
928+
continue;
929+
}
930+
924931
if (!PQgetisnull(result, 0, i))
925932
value = PQgetvalue(result, 0, i);
926933
else

src/bin/psql/variables.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,32 @@ SetVariableHooks(VariableSpace space, const char *name,
362362
(void) (*ahook) (current->value);
363363
}
364364

365+
/*
366+
* Return true iff the named variable has substitute and/or assign hook
367+
* functions.
368+
*/
369+
bool
370+
VariableHasHook(VariableSpace space, const char *name)
371+
{
372+
struct _variable *current;
373+
374+
Assert(space);
375+
Assert(name);
376+
377+
for (current = space->next; current; current = current->next)
378+
{
379+
int cmp = strcmp(current->name, name);
380+
381+
if (cmp == 0)
382+
return (current->substitute_hook != NULL ||
383+
current->assign_hook != NULL);
384+
if (cmp > 0)
385+
break; /* it's not there */
386+
}
387+
388+
return false;
389+
}
390+
365391
/*
366392
* Convenience function to set a variable's value to "on".
367393
*/

src/bin/psql/variables.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ bool DeleteVariable(VariableSpace space, const char *name);
9090
void SetVariableHooks(VariableSpace space, const char *name,
9191
VariableSubstituteHook shook,
9292
VariableAssignHook ahook);
93+
bool VariableHasHook(VariableSpace space, const char *name);
9394

9495
void PsqlVarEnumError(const char *name, const char *value, const char *suggestions);
9596

src/test/regress/expected/psql.out

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,10 @@ select 10 as test01, 20 as test02, 'Hello' as test03 \gset pref01_
8484
select 10 as "bad name"
8585
\gset
8686
invalid variable name: "bad name"
87+
select 97 as "EOF", 'ok' as _foo \gset IGNORE
88+
attempt to \gset into specially treated variable "IGNOREEOF" ignored
89+
\echo :IGNORE_foo :IGNOREEOF
90+
ok 0
8791
-- multiple backslash commands in one line
8892
select 1 as x, 2 as y \gset pref01_ \\ \echo :pref01_x
8993
1

src/test/regress/sql/psql.sql

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ select 10 as test01, 20 as test02, 'Hello' as test03 \gset pref01_
4848
select 10 as "bad name"
4949
\gset
5050

51+
select 97 as "EOF", 'ok' as _foo \gset IGNORE
52+
\echo :IGNORE_foo :IGNOREEOF
53+
5154
-- multiple backslash commands in one line
5255
select 1 as x, 2 as y \gset pref01_ \\ \echo :pref01_x
5356
select 3 as x, 4 as y \gset pref01_ \echo :pref01_x \echo :pref01_y

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy