[VIM] Interesting Scry stuff

Steven M. Christey coley at mitre.org
Tue Apr 25 01:10:45 EDT 2006


Issues:

 various issues in Scry 1.1, index.php p parameter

Note - the package hasn't been updated since 2004.

Refs:

  BUGTRAQ:20060421 Scry Gallery Directory Traversal & Full Path
  Disclosure Vulnerabilites
  http://www.securityfocus.com/archive/1/archive/1/431716/100/0/threaded

  BUGTRAQ:20060424 Scry Gallery XSS Vulnerability
  http://www.securityfocus.com/archive/1/archive/1/431853/100/0/threaded


With the index.php/p vector, the above 2 disclosures covered these bug
types:

 - directory traversal
 - path disclosure
 - XSS

Since I'm on my XSS-hides-other-bugs kick, I grabbed the source code
to take a look.

First, I noticed that the XSS is not exclusively resultant from a
failed directory traversal, thanks to verbose unfiltered error
messages:

  if ($VIEW == 'list') {
    $IMAGE_DIR = $_GET['p'];
  } else {
  ...
  ...
  $PATH         = "$CFG_path_images/$IMAGE_DIR/$IMAGE_FILE";
  $PATH_BASEDIR = "$CFG_path_images/$IMAGE_DIR";
  ...
  if (!is_readable($PATH)) { // FS READ
  die("$PATH does not exist or is not readable by the webserver - please verify settings in setup.php");

So we have application-controlled XSS, which is good enough in CVE's
book for a separate item.

But, before we got to the XSS above, we skipped over the following
code:

  path_security_check($PATH, $CFG_path_images);

That sounds interesting enough, especially since the developer's front
page says that the code was designed with security in mind.

I can see how the XSS got through, if it's just checking for paths
under an expected web root.  But what about the directory traversal?

  // function path_security_check(string $victim, string $test)
  //
  // the resolved path of $victim must be below $test on the filesystem
  //
  function path_security_check($victim, $test) {
    
    if (eregi("^" . rtrim('/', $test) . ".*", rtrim('/', realpath($victim)))) {
      return true;
    } 
  
    die("path security check failed: $victim - $test");
  } // function path_security_check

Well, we see here with the "die" command another vector for
application-controlled XSS.

But that eregi() call seems to be looking for "/" characters and,
presumably, would barf if certain substrings don't match.

It's even using realpath(), which you'd like to see for directory
traversal tests.

Looking up rtrim() in the PHP online manual, we see that it's intended
to strip all whitespace at the end of the string.  An optional
argument allows you to specify any bag of characters to strip.  So,
this code is apparently trying to strip a "/" from the end of the
string.

Except the attacker probably could provide pathname arguments that
don't end in a string.

And - much more relevant to this situation - the PHP manual says that
the characters to trim are specified in the *second* argument, not the
first - like we see in the code above.

So, because of the switched arguments, the rtrim('/', $test)
expression would likely return "", which means we get a regexp of:

  ^.*

which sounds very likely indeed to match whatever comes back from the
realpath argument, thus most any inputs would pass the sanity check.

... except, for some reason, when you go to the developer's web site
and click on the "1.1 demo album link", you get a verbose error
message that generates a failed path_security_check - but prints out
$victim and $test variables that appear to be equal!


- Steve


More information about the VIM mailing list