Mailing List Archive

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 ---------------------------------
Re: QUERY_STRING & #exec cmd bugs [ In reply to ]
Date: Mon, 17 Jul 95 14:59 BST
From: drtr@ast.cam.ac.uk (David Robinson)
Precedence: bulk
Reply-To: new-httpd@hyperreal.com

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.

Hmmm... backslash-octal escaping doesn't work for me in the
shell-escape context ("cat > /tmp/foo\000bar" gives me a file named
/tmp/foo000bar; the backslash simply gets elided). Are there other
programs which will treat this sort of backslash escape correctly?
(If not it seems silly to try to use it --- anything which really
requires %00 to work correctly, it can always just use QUERY_STRING in
the CGI context, or QUERY_STRING_UNESCAPED for SSI <!--#exec-->s).

Of course, the whole argv business has always been the shakiest part
of the CGI spec --- the conditions for when argv is even supplied are
vague, and the actual code is at variance with the standard. Still,
if someone else thinks this is a good fix, I have no *fundamental*
objections, and it'll go in...

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

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.

Hmmm... the only thing now available to SSI execs in both escaped and
unescaped versions is QUERY_STRING --- and the unescaped version of
that is QUERY_STRING_UNESCAPED, not QUERY_STRING. Changing PATH_INFO
to be unescaped would break anyone who was counting on escaping there
for safety, and would not be symmetric with treatment of QUERY_STRING
either. On both counts, adding a new PATH_INFO_UNESCAPED variable
seems like a better solution, if you know anyone who actually wants
one.

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

That might be helpful..

rst
Re: QUERY_STRING & #exec cmd bugs [ In reply to ]
Date: Tue, 18 Jul 95 17:40 BST
From: drtr@ast.cam.ac.uk (David Robinson)

>From: rst@edu.mit.ai (Robert S. Thau)

>Hmmm... backslash-octal escaping doesn't work for me in the
>shell-escape context ("cat > /tmp/foo\000bar" gives me a file named
>/tmp/foo000bar; the backslash simply gets elided).

Not a reasonable test; you can't have filenames with null characters!
And \xxx escapes aren't valid in shell redirections. (I know not why.)

It works ok in command arguments, which is it is used for a script. e.g.

echo 'foo\000bar' > file

works for me.

That's odd... I can't get it to work at all with SunOS tcsh, csh, or
sh. What I get, with all of those, is indeed a file containing
foo\000bar --- but od says that the characters in that file are:

rst@volterra>od -c /tmp/fu
0000000 f o o \ 0 0 0 b a r \n
0000013

Note that the \000 sequence yields four characters; '\', '0', '0', '0'.

I suspect there is little demand for PATH_INFO_(UN)ESCAPED.

I likewise...

rst
Re: QUERY_STRING & #exec cmd bugs [ In reply to ]
>From: rst@edu.mit.ai (Robert S. Thau)
>Date: Mon, 17 Jul 95 12:20:49 EDT

>Hmmm... backslash-octal escaping doesn't work for me in the
>shell-escape context ("cat > /tmp/foo\000bar" gives me a file named
>/tmp/foo000bar; the backslash simply gets elided). Are there other
>programs which will treat this sort of backslash escape correctly?
>(If not it seems silly to try to use it --- anything which really
>requires %00 to work correctly, it can always just use QUERY_STRING in
>the CGI context, or QUERY_STRING_UNESCAPED for SSI <!--#exec-->s).

Not a reasonable test; you can't have filenames with null characters!
And \xxx escapes aren't valid in shell redirections. (I know not why.)

It works ok in command arguments, which is it is used for a script. e.g.

echo 'foo\000bar' > file

works for me.

I suspect there is little demand for PATH_INFO_(UN)ESCAPED.


David.
Re: QUERY_STRING & #exec cmd bugs [ In reply to ]
>> echo 'foo\000bar' > file
>
> works for me.
>
>That's odd... I can't get it to work at all with SunOS tcsh, csh, or
>sh.

Oh well. Further experimentation shows that this is a System-V feature.
Digital unix supports it; bsdi does not.

In which case it is probably not worth trying to fix.

David.