Changeset: 3db848b50ce4 for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=3db848b50ce4
Modified Files:
        sql/ChangeLog.Oct2010
        sql/src/server/rel_updates.mx
Branch: Oct2010
Log Message:

COPY INTO: take security measures when using paths

As reported by Stefan de Konink, COPY INTO can be used to read and write
files in any location on the host the database is running at.  To
prevent people from doing damage, the usage of COPY INTO is restricted
in a number of ways:
- COPY INTO with a path may only be used by the super-user, normal users
  can use STDIN and STDOUT to let their client handle the reading and
  writing of data
- paths used with COPY INTO may only be absolute
- paths used with COPY INTO may not be within the dbfarm
- when COPY INTO is used to write to a file, this file may not already
  exist to prevent files being overwritten


diffs (106 lines):

diff -r a45da51ff57e -r 3db848b50ce4 sql/ChangeLog.Oct2010
--- a/sql/ChangeLog.Oct2010     Mon Dec 13 07:59:39 2010 +0100
+++ b/sql/ChangeLog.Oct2010     Mon Dec 13 18:07:05 2010 +0100
@@ -1,3 +1,12 @@
 # ChangeLog file for sql
 # This file is updated with Maddlog
 
+* Mon Dec 13 2010 Fabian Groffen <fab...@cwi.nl>
+- Security related fixes to the COPY INTO commands: 1) binary COPY INTO
+  is disallowed for non-administrator users, 2) COPY INTO using a path
+  both for reading and writing is disallowed for non-administrator users,
+  3) paths used with COPY INTO may not be relative, 4) paths used with
+  COPY INTO may not be descendants of the dbfarm directory (where the
+  database files reside) and 5) COPY INTO a file may only be writing to
+  a non-existing file
+
diff -r a45da51ff57e -r 3db848b50ce4 sql/src/server/rel_updates.mx
--- a/sql/src/server/rel_updates.mx     Mon Dec 13 07:59:39 2010 +0100
+++ b/sql/src/server/rel_updates.mx     Mon Dec 13 18:07:05 2010 +0100
@@ -587,15 +587,34 @@
        if (!t) 
                return sql_error(sql, 02, "COPY INTO: no such table '%s'", 
tname);
        if (t->readonly) 
-               return sql_error(sql, 02, "COPY INTO: cannot copy into read 
only table '%s'", tname);
+               return sql_error(sql, 02, "COPY INTO: cannot copy into 
read-only table '%s'", tname);
        if (t && !isTempTable(t) && STORE_READONLY(active_store_type))
-               return sql_error(sql, 02, "COPY INTO: copy into table '%s' not 
allowed in readonly mode", tname);
+               return sql_error(sql, 02, "COPY INTO: database is in read-only 
mode");
        if (files) {
                dnode *n = files->h;
+               char realdbfarm[1024];
+               char realfile[1024];
+
+               if (sql->user_id != USER_MONETDB)
+                       return sql_error(sql, 02, "COPY INTO: insufficient 
privileges: "
+                                       "COPY INTO from file(s) requires 
administrator rights, "
+                                       "use 'COPY INTO \"%s\" FROM STDIN' 
instead", tname);
+
+               realpath(GDKgetenv("gdk_dbfarm"), realdbfarm);
 
                for (; n; n = n->next) {
                        char *fname = n->data.sval;
-                       sql_rel *nrel = rel_import(sql, t, tsep, rsep, ssep, 
ns, fname, nr, offset);
+                       sql_rel *nrel;
+
+                       if (fname && *fname != '/')
+                               return sql_error(sql, 02, "COPY INTO: filename 
must "
+                                               "have absolute path: %s", 
fname);
+                       realpath(fname, realfile);
+                       if (strncmp(realdbfarm, realfile, strlen(realdbfarm)) 
== 0)
+                               return sql_error(sql, 02, "COPY INTO: file may 
not "
+                                               "reside in the server's dbfarm: 
%s", realfile);
+
+                       nrel = rel_import(sql, t, tsep, rsep, ssep, ns, fname, 
nr, offset);
 
                        if (!rel)
                                rel = nrel;
@@ -630,6 +649,12 @@
        sql_schema *sys = mvc_bind_schema(sql, "sys");
        sql_subfunc *f = sql_find_func(sys, "copyfrom", 2); 
 
+       if (sql->user_id != USER_MONETDB) {
+               (void) sql_error(sql, 02, "COPY INTO: insufficient privileges: "
+                               "binary COPY INTO requires administrator 
rights");
+               return NULL;
+       }
+
        if (sname && !(s=mvc_bind_schema(sql, sname))) {
                (void) sql_error(sql, 02, "COPY INTO: no such schema '%s'", 
sname);
                return NULL;
@@ -704,6 +729,8 @@
 static sql_rel *
 copyto(mvc *sql, symbol *sq, str filename, dlist *seps, str null_string)
 {
+       char realdbfarm[1024];
+       char realfile[1024];
        char *tsep = seps->h->data.sval;
        char *rsep = seps->h->next->data.sval;
        char *ssep = (seps->h->next->next)?seps->h->next->next->data.sval:"\"";
@@ -720,6 +747,26 @@
        ssep_e = exp_atom_clob(ssep);
        ns_e = exp_atom_clob(ns);
        fname_e = filename?exp_atom_clob(filename):NULL;
+
+       if (filename) {
+               struct stat fs;
+               if (sql->user_id != USER_MONETDB)
+                       return sql_error(sql, 02, "COPY INTO: insufficient 
privileges: "
+                                       "COPY INTO file requires administrator 
rights, "
+                                       "use 'COPY ... INTO STDOUT' instead");
+               realpath(GDKgetenv("gdk_dbfarm"), realdbfarm);
+               if (filename && *filename != '/')
+                       return sql_error(sql, 02, "COPY INTO: filename must "
+                                       "have absolute path: %s", filename);
+               realpath(filename, realfile);
+               if (strncmp(realdbfarm, realfile, strlen(realdbfarm)) == 0)
+                       return sql_error(sql, 02, "COPY INTO: file may not "
+                                       "reside in the server's dbfarm: %s", 
realfile);
+               if (lstat(realfile, &fs) == 0)
+                       return sql_error(sql, 02, "COPY INTO: file already "
+                                       "exists: %s", realfile);
+       }
+
        return rel_output(r, tsep_e, rsep_e, ssep_e, ns_e, fname_e);
 }
 
_______________________________________________
Checkin-list mailing list
Checkin-list@monetdb.org
http://mail.monetdb.org/mailman/listinfo/checkin-list

Reply via email to