Well, I understand the concerns with trying to patch all
libs that PHP uses. However mysql seems to be a *major*
extension, as in it is very heavily used. I had to write
this patch anyway for a client, so I will post the patch
here. If people don't like it, they can ignore it. If
enough people do like it, we can discuss committing it.

This patch I think will catch all cases, unless there is
some way that mysql can escape characters (\x44 or
something).

-James
 The University of Vermont

On Mon, 4 Feb 2002, Rasmus Lerdorf wrote:

> The fact that 3rd party libs can load arbitrary files is not a new
> concept.  Every time I give a moderately detailed PHP talk I mention the
> fact that there is a way to load a file through the oci8 libs.  Of course
> it can be done through the mysql libs as well.  This is not a new concept.
> All someone woulod have had to do to learn of this "vulnerability" would
> have been to go to any of the PHP talks I have given in the past 3 years.
>
> We will not scan queries to catch these.  Safe mode is a crappy fix to a
> problem that isn't ours.
>
> -Rasmus
>
>
> On Tue, 5 Feb 2002, Andi Gutmans wrote:
>
> > We have always said that safe mode isn't very safe. I'm sure there are
> > other ways of circumventing it.
> > Unless a few people focus specifically on safe mode I don't think this will
> > change.
> >
> > Andi
> >
> > At 12:26 AM 2/5/2002 -0500, James E. Flemer wrote:
> > >BTW I just noticed that this has been entered as bug
> > >#15375.
> > >
> > >
> > >--
> > >PHP Development Mailing List <http://www.php.net/>
> > >To unsubscribe, visit: http://www.php.net/unsub.php
> >
> >
> >
>
>
>
>
Index: ext/mysql/php_mysql.c
===================================================================
RCS file: /repository/php4/ext/mysql/php_mysql.c,v
retrieving revision 1.115
diff -u -r1.115 php_mysql.c
--- ext/mysql/php_mysql.c       30 Dec 2001 10:00:26 -0000      1.115
+++ ext/mysql/php_mysql.c       5 Feb 2002 21:25:30 -0000
@@ -987,6 +987,66 @@
 /* }}} */
 #endif
 
+/* {{{ php_mysql_safety_check
+ */
+static int php_mysql_safety_check(const char *p, int len)
+{
+       int state = 1;
+       const char *end = p + len;
+       
+       while (p && *p && p < end)
+       {
+               switch (state)
+               {
+               case 0: /* skip word */
+                       while (*p && p < end && *p != ' ' && *p != '\t' && *p != '\r' 
+&& *p != '\n')
+                               p++;
+                       /* FALLTHROUGH */
+               case 2:
+                       /* FALLTHROUGH */
+               case 4: /* move to the end of space(s) */
+                       if (*p && p < end && *p != ' ' && *p != '\t' && *p != '\r' && 
+*p != '\n') {
+                               state = 0;
+                               break;
+                       }
+                       while (*p && p < end && (*p == ' ' || *p == '\t' || *p == '\r' 
+|| *p == '\n'))
+                               p++;
+                       state++;
+                       break;
+               case 1: /* look for "LOAD" */
+                       if (    (*p == 'l' || *p == 'L') &&
+                                       p+3 < end &&
+                                       *(p+1) && *(p+2) && *(p+3) &&
+                                       (*(p+1) == 'o' || *(p+1) == 'O') &&
+                                       (*(p+2) == 'a' || *(p+2) == 'A') &&
+                                       (*(p+3) == 'd' || *(p+3) == 'D') ) {
+                               p += 4;
+                               state++;
+                       } else {
+                               state = 0;
+                       }
+                       break;
+               case 3: /* look for "DATA" */
+                       if (    (*p == 'd' || *p == 'D') &&
+                                       p+3 < end &&
+                                       *(p+1) && *(p+2) && *(p+3) &&
+                                       (*(p+1) == 'a' || *(p+1) == 'A') &&
+                                       (*(p+2) == 't' || *(p+2) == 'T') &&
+                                       (*(p+3) == 'a' || *(p+3) == 'A') ) {
+                               p += 4;
+                               state++;
+                       } else {
+                               state = 0;
+                       }
+                       break;
+               case 5: /* "<space>LOAD<space>DATA<space>" found */
+                       return 0;
+               }
+       }
+       return 1;
+}
+/* }}} */
+
 /* {{{ php_mysql_do_query_general
  */
 static void php_mysql_do_query_general(zval **query, zval **mysql_link, int link_id, 
zval **db, int use_store, zval *return_value TSRMLS_DC)
@@ -1021,6 +1081,15 @@
        } while(0);
 
        convert_to_string_ex(query);
+       
+       /* disallow LOAD DATA if safe_mode on */
+       if (PG(safe_mode)) {
+               if (!php_mysql_safety_check(Z_STRVAL_PP(query), Z_STRLEN_PP(query))) {
+                       php_error(E_WARNING, "MySQL: Statement failed safe mode 
+checks");
+                       RETURN_FALSE;
+               }
+       }
+       
        /* mysql_query is binary unsafe, use mysql_real_query */
 #if MYSQL_VERSION_ID > 32199 
        if (mysql_real_query(&mysql->conn, Z_STRVAL_PP(query), Z_STRLEN_PP(query))!=0) 
{
-- 
PHP Development Mailing List <http://www.php.net/>
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to