| From: | Kirill Reshke <reshkekirill(at)gmail(dot)com> |
|---|---|
| To: | Japin Li <japinli(at)hotmail(dot)com> |
| Cc: | PostgreSQL mailing lists <pgsql-bugs(at)lists(dot)postgresql(dot)org>, zengman <zengman(at)halodbtech(dot)com> |
| Subject: | Re: BUG #19478: `dblink_close` can be used for injection. |
| Date: | 2026-05-16 04:06:05 |
| Message-ID: | CALdSSPjBpUfY=S2i_3ACqF7YUJ=po1TDwYnDPDx38=j8LKXj7g@mail.gmail.com |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-bugs |
On Sat, 16 May 2026, 06:24 Japin Li, <japinli(at)hotmail(dot)com> wrote:
> On Fri, 15 May 2026 at 01:29, PG Bug reporting form <
> noreply(at)postgresql(dot)org> wrote:
> > The following bug has been logged on the website:
> >
> > Bug reference: 19478
> > Logged by: Man Zeng
> > Email address: zengman(at)halodbtech(dot)com
> > PostgreSQL version: 18.4
> > Operating system: 24.04.1-Ubuntu
> > Description:
> >
> > Hi all,
> >
> > I think we can impose stricter restrictions on the parameters of
> > `dblink_close`.
> > For example, when calling `dblink_close`, certain operations can be
> achieved
> > through SQL concatenation,
> > which I believe is unexpected behavior.
> >
> > ```sql
> > postgres(at)zxm-VMware-Virtual-Platform:~/Z-Xiao-M$ psql
> > psql (19devel)
> > Type "help" for help.
> >
> > postgres=# \c test
> > You are now connected to database "test" as user "postgres".
> > test=# CREATE EXTENSION IF NOT EXISTS dblink;
> > CREATE EXTENSION
> > test=# SELECT dblink_connect('c', 'dbname=' || current_database());
> > dblink_connect
> > ----------------
> > OK
> > (1 row)
> >
> > test=# SELECT dblink_open('c', 'cur', 'SELECT 1');
> > dblink_open
> > -------------
> > OK
> > (1 row)
> >
> > test=# -- CLOSE: CREATE TABLE
> > test=# SELECT dblink_close('c', 'cur; CREATE TABLE hacked(id int); --');
> > dblink_close
> > --------------
> > OK
> > (1 row)
> >
> > test=# \d+ hacked
> > Table "public.hacked"
> > Column | Type | Collation | Nullable | Default | Storage |
> Compression |
> > Stats target | Description
> >
> --------+---------+-----------+----------+---------+---------+-------------+--------------+-------------
> > id | integer | | | | plain |
> |
> > |
> > Access method: heap
> >
> > test=# SELECT dblink_disconnect('c');
> > dblink_disconnect
> > -------------------
> > OK
> > (1 row)
> >
> > test=# SELECT dblink_connect('c', 'dbname=' || current_database());
> > dblink_connect
> > ----------------
> > OK
> > (1 row)
> >
> > test=# SELECT dblink_open('c', 'cur', 'SELECT 1');
> > dblink_open
> > -------------
> > OK
> > (1 row)
> >
> > test=# -- CLOSE: DROP TABLE
> > test=# SELECT dblink_close('c', 'cur; DROP TABLE hacked; --');
> > dblink_close
> > --------------
> > OK
> > (1 row)
> >
> > test=# \d+ hacked
> > Did not find any relation named "hacked".
> > test=#
> > ```
> >
> > This is my SQL for reproducing the problem.
> > ```sql
> > CREATE EXTENSION IF NOT EXISTS dblink;
> >
> > SELECT dblink_connect('c', 'dbname=' || current_database());
> > SELECT dblink_open('c', 'cur', 'SELECT 1');
> >
> > -- CLOSE: CREATE TABLE
> > SELECT dblink_close('c', 'cur; CREATE TABLE hacked(id int); --');
> >
> > SELECT dblink_disconnect('c');
> > \d+ hacked
> >
> > SELECT dblink_connect('c', 'dbname=' || current_database());
> > SELECT dblink_open('c', 'cur', 'SELECT 1');
> >
> > -- CLOSE: DROP TABLE
> > SELECT dblink_close('c', 'cur; DROP TABLE hacked; --');
> >
> > \d+ hacked
> > SELECT dblink_disconnect('c');
> > ```
> >
> > The solution to this problem is also very simple.
> > ```
> > postgres(at)zxm-VMware-Virtual-Platform:~/code/postgres/contrib$ git diff
> > diff --git a/contrib/dblink/dblink.c b/contrib/dblink/dblink.c
> > index 9798cb535bc..0a9334aa160 100644
> > --- a/contrib/dblink/dblink.c
> > +++ b/contrib/dblink/dblink.c
> > @@ -543,7 +543,7 @@ dblink_close(PG_FUNCTION_ARGS)
> >
> > conn = rconn->conn;
> >
> > - appendStringInfo(&buf, "CLOSE %s", curname);
> > + appendStringInfo(&buf, "CLOSE %s", quote_ident_cstr(curname));
> >
> > /* close the cursor */
> > res = libpqsrv_exec(conn, buf.data, dblink_we_get_result);
> > ```
> >
> > This is the feedback from the security team.
> > ```
> > Thanks for your report. We consider dblink_close() to be caller-trusted,
> > and thus this is not considered a security vulnerability. Feel free to
> > resubmit to pgsql-bugs(at)lists(dot)postgresql(dot)org(dot)
> > ```
> >
> > Any thought?
>
> According to the documentation [1], it should be a cursor name. Wrapping
> it
> in quotes can prevent attacks like SQL injection. I think your
> modification
> is correct, and we should add test cases for it.
>
> [1] https://www.postgresql.org/docs/current/contrib-dblink-close.html
>
> > --
> > regards,
> > Man Zeng
>
> --
> Regards,
> Japin Li
> ChengDu WenWu Information Technology Co., Ltd.
>
Well, is there any actual injection? I mean, if user can execute
dblink_close, then user can do an SQL with dblink_open and simply do a SQL?
Unless wierd case when we only granted with close function, I guess
| From | Date | Subject | |
|---|---|---|---|
| Next Message | David G. Johnston | 2026-05-16 04:28:56 | Re: BUG #19478: `dblink_close` can be used for injection. |
| Previous Message | Japin Li | 2026-05-16 01:24:15 | Re: BUG #19478: `dblink_close` can be used for injection. |