Tuesday, March 23, 2010

osCommerce-v2.2 RC2 Authentication Bypass

http://www.milw0rm.com/exploits/9556 exploits an authentication bypass vulnerability in the latest version of osCommerce-v2.2 RC2--allows an attacker to upload and execute an arbitrary file.

file_manager.php is one of many administrative scripts in the "admin" directory. In this PHP script we have:

31: $action = (isset($HTTP_GET_VARS['action']) ? $HTTP_GET_VARS['action'] : '');


$action is set to the value of the "action" parameter passed via the URL.
34: switch ($action) {

50: case 'save':
51: if (isset($HTTP_POST_VARS['filename']) && tep_not_null(basename($HTTP_POST_VARS['filename']))) {
52:     if (is_writeable($current_path) && ($fp = fopen($current_path . '/' . basename($HTTP_POST_VARS['filename']), 'w+'))) {
53:         fputs($fp, stripslashes($HTTP_POST_VARS['file_contents']));
54:         fclose($fp);
55:         ...
56:     }
57: }

One of the possible actions is "save". Save checks for a POST parameter called "filename". Next, a file is created in the current working directory using the value of the parameter as its name. The contents of the "file_contents" POST parameter are written to the file and it is closed.

This doesn't explain how authentication is bypassed. If you try POSTing "filename" and "file_content" to "/path/admin/file_manager.php?action=save" you are redirected to a login page.

The exploit builds a POST URL that looks like "/admin/file_manager.php/login.php?action=save". The "file_manager.php/login.php" part looks kind of weird because file_manager.php isn't a directory, but this is a valid (obscure?) feature of PHP related to the $_SERVER['PHP_INFO
'] variable. We'll come back to this shortly, but first, some script initializations and startup.

file_manager.php requires admin/includes/application_top.php on line 13. application_top.php has the following:

37    $PHP_SELF = (isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME']);


$HTTP_SERVER_VARS is set equal to $_SERVER in line 38 of admin/includes/functions/compatibility.php. $_SERVER['PHP_SELF'] is set to "/admin/file_manager.php/login.php" for the exploit's POST.
132  // redirect to login page if administrator is not yet logged in
133    if (!tep_session_is_registered('admin')) {

We don't have an admin session.
134      $redirect = false;
135  
136      $current_page = basename($PHP_SELF);

Tracing $PHP_SELF back through $_SERVER['PHP_SELF'], this becomes "login.php" using a URL of "/admin/file_manager.php/login.php".
138      if ($current_page != FILENAME_LOGIN) {

...

146        $redirect = true;
147      }

FILENAME_LOGIN is defined as "login.php" on line 30 of admin/includes/filenames.php. We don't enter this if statement.
149      if ($redirect == true) {
150        tep_redirect(tep_href_link(FILENAME_LOGIN));
151      }

$redirect is never set to "true", so we don't redirect to a login.php and the authentication is bypassed.

No comments:

Post a Comment