You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by David Robinson <dr...@ast.cam.ac.uk> on 1995/07/17 16:59:00 UTC

QUERY_STRING & #exec cmd bugs

1. Shambhala 0.6.1 ignores any QUERY_STRING after a NULL character which
   making the argv vector for a CGI script.
   e.g. script?text%00word

   sets argv to text
   instead it should set it to text\000word

   A patch is supplied.

2. Shambhala applies different shell-escaping from Apache & NCSA 1.3 for
   <!-- #exec cmd--> commands.

   Consider test.shtml which contains <!-- #exec cmd="env" -->
   Calling test.shtml/aa{b?c%7bd gives

   PATH_INFO=/aa\{b
   PATH_TRANSLATED=/opt/httpd/htdocs/aa{b
   QUERY_STRING=c%7bd
   QUERY_STRING_UNESCAPED=c\{d

   whereas NCSA and apache give

   PATH_INFO=/aa\{b
   PATH_TRANSLATED=/opt/httpd/htdocs/aa\{b
   QUERY_STRING=c%7bd
   QUERY_STRING_UNESCAPED=c\{d

   Both of these behaviours a wrong, in my opinion; if escaped
   strings are to be provided, they should be called PATH_INFO_ESCAPED
   and PATH_TRANSLATED_ESCAPED.

   At the very least, the documentation is wrong; it does not mention
   that PATH_INFO and PATH_TRANSLATED are escaped strings.

 David.

--------------- Patch for null characters in QUERY_STRING -------------------
*** httpd.h.orig	Fri Jul 14 11:21:19 1995
--- httpd.h	Mon Jul 17 11:27:26 1995
***************
*** 388,394 ****
  char *escape_uri (pool *p, char *s);
  char *construct_url (pool *p, char *path, server_rec *s);     
  char *escape_shell_cmd (pool *p, char *s);
!      
  int count_dirs(char *path);
  char *make_dirstr(pool *a, char *s, int n);
  char *make_full_path(pool *a, char *dir, char *f);
--- 388,395 ----
  char *escape_uri (pool *p, char *s);
  char *construct_url (pool *p, char *path, server_rec *s);     
  char *escape_shell_cmd (pool *p, char *s);
! extern char *url2shell_escape(pool *p, const char *s);
! 
  int count_dirs(char *path);
  char *make_dirstr(pool *a, char *s, int n);
  char *make_full_path(pool *a, char *dir, char *f);
*** util.c.orig	Sun Jul  9 18:52:43 1995
--- util.c	Mon Jul 17 11:51:10 1995
***************
*** 65,70 ****
--- 65,74 ----
  #include "httpd.h"
  #include "http_conf_globals.h"	/* for user_id & group_id */
  
+ 
+ /* prototypes */
+ static int x2c(const char *what);
+ 
  #ifdef NOTDEF
  extern char** environ;
  
***************
*** 413,418 ****
--- 417,461 ----
      return cmd;
  }
  
+ /*
+  * Converts a URL-encoded string to a shell-encoded string.
+  * This way we are careful with NULL characters in the URL.
+  * We skip bad escape sequences in the URL.
+  */
+ char *
+ url2shell_escape(pool *p, const char *s)
+ {
+     register int x, y, ch;
+     char *cmd;
+ 
+     cmd = palloc(p, 2*strlen(s)+1);  /* Be safe. */
+     for (x=0, y=0; s[x] != '\0'; x++, y++)
+     {
+ 	ch = s[x];
+ 	if (ch == '%' && isxdigit(s[x+1]) && isxdigit(s[x+2]))
+ 	{
+ 	    ch = x2c(&s[x+1]);
+ 	    x += 2;
+ 	}
+ 	if (ch == 0) /* and other control characters, or 0x80-ff? */
+ 	{
+ 	    cmd[y++] = '\\';
+ 	    cmd[y++] = '0';
+ 	    cmd[y++] = '0';
+ 	    cmd[y] = '0';
+ 	} else 	if (ind("&;`'\"|*?~<>^()[]{}$\\", ch) != -1)
+ 	{
+ 	    cmd[y++] = '\\';
+ 	    cmd[y] = ch;
+ 	}
+ 	else cmd[y] = ch;
+     }
+     cmd[y] = '\0';
+ 
+     return cmd;
+ }
+ 
+ 
  void plustospace(char *str) {
      register int x;
  
***************
*** 425,431 ****
      for(x=0;str[x];x++) if(str[x] == ' ') str[x] = '+';
  }
  
! char x2c(char *what) {
      register char digit;
  
      digit = ((what[0] >= 'A') ? ((what[0] & 0xdf) - 'A')+10 : (what[0] - '0'));
--- 468,475 ----
      for(x=0;str[x];x++) if(str[x] == ' ') str[x] = '+';
  }
  
! static int
! x2c(const char *what) {
      register char digit;
  
      digit = ((what[0] >= 'A') ? ((what[0] & 0xdf) - 'A')+10 : (what[0] - '0'));
*** util_script.c.orig	Sun Jul  9 17:30:32 1995
--- util_script.c	Mon Jul 17 11:32:34 1995
***************
*** 80,87 ****
  
      for(x=1;x<n;x++) {
          w = getword(p, &args, '+');
!         unescape_url(w);
!         av[x] = escape_shell_cmd(p, w);
      }
      av[n] = NULL;
      return av;
--- 80,86 ----
  
      for(x=1;x<n;x++) {
          w = getword(p, &args, '+');
!         av[x] = url2shell_escape(p, w);
      }
      av[n] = NULL;
      return av;
*** mod_include.c.orig	Tue Jul 11 23:58:08 1995
--- mod_include.c	Mon Jul 17 11:31:36 1995
***************
*** 417,425 ****
  
      if (r->args) {
          table_set (env, "QUERY_STRING", r->args);
- 	unescape_url (r->args);
  	table_set (env, "QUERY_STRING_UNESCAPED",
! 		   escape_shell_cmd (r->pool, r->args));
      }
      
      error_log2stderr (r->server);
--- 417,424 ----
  
      if (r->args) {
          table_set (env, "QUERY_STRING", r->args);
  	table_set (env, "QUERY_STRING_UNESCAPED",
! 		   url2shell_escape (r->pool, r->args));
      }
      
      error_log2stderr (r->server);

----------------------------- End of file ---------------------------------