Alexis Wilke
Alexis Wilke

Reputation: 20720

Is there a special case in Apache2 when calling a CGI and the URI includes a single query string parameter without a value?

Today I got an error and was very surprised to get it since everything looked just fine...

I have a CGI written in C++ which accepts URIs with a query string. The query string is what selects the page, etc. The CGI is installed in the standard location for an Ubuntu installation:

/usr/lib/cgi-bin/snapmanager.cgi

Today I was finishing up adding a Login screen and once logged in, I wanted to add a logout link. The link simply adds ?logout at the end of the URI:

http://www.example.com/cgi-bin/snapmanager.cgi?logout

That failed.

Checking the error log, I got an error saying that "logout" actually appeared on the command line. Rather surprising, if you ask me! I tried with:

http://www.example.com/cgi-bin/snapmanager.cgi?logout=now

and everything worked as expected. No logout on the command line.

I also tried:

http://www.example.com/cgi-bin/snapmanager.cgi?logout&host=foo

And that worked too. Again, no logout on the command line.

However, if I switch the parameters position it fails again:

http://www.example.com/cgi-bin/snapmanager.cgi?host=foo&logout

So it looks like Apache2 calls my CGI with the logout query string as a parameter on the command line when that one query string name is defined last.

Just in case, I tried to add dashes at the start of the name, and sure enough, that appears as a command line switch in my logs!

error:snapmanager.cgi: option --logout is not supported.

Really scary. This is a huge security risk if you know of a switch that can "tweak things your way"...

Is that documented somewhere?

Upvotes: 1

Views: 63

Answers (1)

Alexis Wilke
Alexis Wilke

Reputation: 20720

I actually found the answer in RFC3875 in paragraph 4.4

4.4. The Script Command Line

Some systems support a method for supplying an array of strings to the CGI script. This is only used in the case of an 'indexed' HTTP query, which is identified by a 'GET' or 'HEAD' request with a URI query string that does not contain any unencoded "=" characters. For such a request, the server SHOULD treat the query-string as a search-string and parse it into words, using the rules

 search-string = search-word *( "+" search-word )
 search-word   = 1*schar
 schar         = unreserved | escaped | xreserved
 xreserved     = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "," |
                 "$"

After parsing, each search-word is URL-decoded, optionally encoded in a system-defined manner and then added to the command line argument list.

If the server cannot create any part of the argument list, then the server MUST NOT generate any command line information. For example, the number of arguments may be greater than operating system or server limits, or one of the words may not be representable as an argument.

The script SHOULD check to see if the QUERY_STRING value contains an unencoded "=" character, and SHOULD NOT use the command line arguments if it does.

Emphasis Mine

Upvotes: 2

Related Questions