Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Convert newlines to spaces in names written in pg_dump comments.
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 23 Feb 2012 20:53:24 +0000 (15:53 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 23 Feb 2012 20:53:24 +0000 (15:53 -0500)
pg_dump was incautious about sanitizing object names that are emitted
within SQL comments in its output script.  A name containing a newline
would at least render the script syntactically incorrect.  Maliciously
crafted object names could present a SQL injection risk when the script
is reloaded.

Reported by Heikki Linnakangas, patch by Robert Haas

Security: CVE-2012-0868

src/bin/pg_dump/pg_backup_archiver.c

index c1adf0853cad4d90630dc90dd73e3fa8a777b276..b31ed90b493b757040a50062f3bb7b0221d4ef45 100644 (file)
@@ -89,6 +89,7 @@ static ArchiveHandle *_allocAH(const char *FileSpec, const ArchiveFormat fmt,
 static void _getObjectDescription(PQExpBuffer buf, TocEntry *te,
                      ArchiveHandle *AH);
 static void _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isData, bool acl_pass);
+static char *replace_line_endings(const char *str);
 
 
 static void _doSetFixedOutputState(ArchiveHandle *AH);
@@ -2876,6 +2877,9 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isDat
    if (!AH->noTocComments)
    {
        const char *pfx;
+       char       *sanitized_name;
+       char       *sanitized_schema;
+       char       *sanitized_owner;
 
        if (isData)
            pfx = "Data for ";
@@ -2897,12 +2901,39 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isDat
                ahprintf(AH, "\n");
            }
        }
+
+       /*
+        * Zap any line endings embedded in user-supplied fields, to prevent
+        * corruption of the dump (which could, in the worst case, present an
+        * SQL injection vulnerability if someone were to incautiously load a
+        * dump containing objects with maliciously crafted names).
+        */
+       sanitized_name = replace_line_endings(te->tag);
+       if (te->namespace)
+           sanitized_schema = replace_line_endings(te->namespace);
+       else
+           sanitized_schema = strdup("-");
+       if (!ropt->noOwner)
+           sanitized_owner = replace_line_endings(te->owner);
+       else
+           sanitized_owner = strdup("-");
+
        ahprintf(AH, "-- %sName: %s; Type: %s; Schema: %s; Owner: %s",
-                pfx, te->tag, te->desc,
-                te->namespace ? te->namespace : "-",
-                ropt->noOwner ? "-" : te->owner);
+                pfx, sanitized_name, te->desc, sanitized_schema,
+                sanitized_owner);
+
+       free(sanitized_name);
+       free(sanitized_schema);
+       free(sanitized_owner);
+
        if (te->tablespace && !ropt->noTablespace)
-           ahprintf(AH, "; Tablespace: %s", te->tablespace);
+       {
+           char   *sanitized_tablespace;
+
+           sanitized_tablespace = replace_line_endings(te->tablespace);
+           ahprintf(AH, "; Tablespace: %s", sanitized_tablespace);
+           free(sanitized_tablespace);
+       }
        ahprintf(AH, "\n");
 
        if (AH->PrintExtraTocPtr !=NULL)
@@ -2995,6 +3026,27 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isDat
    }
 }
 
+/*
+ * Sanitize a string to be included in an SQL comment, by replacing any
+ * newlines with spaces.
+ */
+static char *
+replace_line_endings(const char *str)
+{
+   char   *result;
+   char   *s;
+
+   result = strdup(str);
+
+   for (s = result; *s != '\0'; s++)
+   {
+       if (*s == '\n' || *s == '\r')
+           *s = ' ';
+   }
+
+   return result;
+}
+
 void
 WriteHead(ArchiveHandle *AH)
 {