Jump to content

Archived

This topic is now archived and is closed to further replies.

khaos119

Serious Hole Found in osCommerce!

Recommended Posts

Create a file on the problem server called test.php and just put in it my recommended code adding echo $PHP_SELF; to the bottom (obviously surrounded by <?php ?>) then just run it.

 

I added the following to a test php file:

/**    * Reliably set PHP_SELF as a filename .. platform safe    */
   function setPhpSelf() { 
        $base = ( array( 'SCRIPT_NAME', 'PHP_SELF' ) );
              foreach ( $base as $index => $key ) { 
     if ( array_key_exists(  $key, $_SERVER ) && !empty(  $_SERVER[$key] ) ) {
     if ( false !== strpos( $_SERVER[$key], '.php' ) ) {
       preg_match( '@[a-z0-9_]+\.php@i', $_SERVER[$key], $matches );
       if ( is_array( $matches ) && ( array_key_exists( 0, $matches ) )
                                 && ( substr( $matches[0], -4, 4 ) == '.php' )
                                 && ( is_readable( $matches[0] ) ) ) { 
     return $matches[0];
      }
      }
      }
      }
      return 'index.php';
       } // end method
  $PHP_SELF = setPhpSelf();

<?php echo $PHP_SELF; ?>

browsed to the page and viewed this:

/** * Reliably set PHP_SELF as a filename .. platform safe */ function setPhpSelf() { $base = ( array( 'SCRIPT_NAME', 'PHP_SELF' ) ); foreach ( $base as $index => $key ) { if ( array_key_exists( $key, $_SERVER ) && !empty( $_SERVER[$key] ) ) { if ( false !== strpos( $_SERVER[$key], '.php' ) ) { preg_match( '@[a-z0-9_]+\.php@i', $_SERVER[$key], $matches ); if ( is_array( $matches ) && ( array_key_exists( 0, $matches ) ) && ( substr( $matches[0], -4, 4 ) == '.php' ) && ( is_readable( $matches[0] ) ) ) { return $matches[0]; } } } } return 'index.php'; } // end method $PHP_SELF = setPhpSelf(); /test.php

Share this post


Link to post
Share on other sites

I added the following to a test php file:

 

<?php
   /**
   * Reliably set PHP_SELF as a filename .. platform safe
   */
   function setPhpSelf() {
     $base = ( array( 'SCRIPT_NAME', 'PHP_SELF' ) );
     foreach ( $base as $index => $key ) {
       if ( array_key_exists(  $key, $_SERVER ) && !empty(  $_SERVER[$key] ) ) {
         if ( false !== strpos( $_SERVER[$key], '.php' ) ) {
           preg_match( '@[a-z0-9_]+\.php@i', $_SERVER[$key], $matches );
           if ( is_array( $matches ) && ( array_key_exists( 0, $matches ) )
                                     && ( substr( $matches[0], -4, 4 ) == '.php' )
                                     && ( is_readable( $matches[0] ) ) ) {
             return $matches[0];
           } 
         } 
       }
     } 
     return 'index.php';
   } // end method 

   $PHP_SELF = setPhpSelf();
   echo 'File was: ' . $PHP_SELF;  
?>

Share this post


Link to post
Share on other sites

Sorry about that.

 

I altered the file accordingly. and now viewing the page I get this:

 

File was: test.php

 

Yup and that is all the code is doing so slowing down nothing.

Share this post


Link to post
Share on other sites

Thanks for the quick answer. The RC2a site has the mod from Jack mcs

and my older sites have a much earlier version of the same mod started by Chemo.

http://addons.oscommerce.com/info/2823

Both MS2 sites have good ranking and sales, so i have not bothered updating the add on. I am wanting to upgrade to RC2a, time permitting.

 

Tim

 

Interesting I would have guessed it the other way around as 2-2.2d-5 is significantly broken the stable version is still 2.1d ORIGINAL updated.

Share this post


Link to post
Share on other sites

What does this hack attempt to do? Is it stealing information or just sending out random spam emails? Thanks! I have been hit as well.

I have been hit with this as well. My site is sending out random spam emails. So far I've changed the admin folder name as mentioned above as well as add a password server side to the new admin folder. I'm now working on further suggestions listed above.

I would like to know more about the htaccess scripts. Are these run server side directly in sql?

Share this post


Link to post
Share on other sites

It allows spam to be sent to the customer database. However it isn't the only way of sending spam from osc, nor is spamming the only thing hackers can do with an unsecured osc. You need to take all the measures explained in the various threads/posts listed here to protect your site.


www.jyoshna.com. Currently using OsC with STS, Super Download Store, Categories Descriptons, Manufacturers Description, Individual Item Status, Infopages unlimited, Product Sort, Osplayer with flashmp3player, Product Tabs 2.1 with WebFx Tabpane and other bits and pieces including some I made myself. Many thanks to all whose contributions I have used!

Share this post


Link to post
Share on other sites

All, or most fixes shown in this thread may not work - may only hide problem.

 

Try this to test it - write

echo 'error';

on the top of mail.php - before application_top.php.

This is to produce error, which proves that mail.php is being called, before fix gets rid of it.

Redirect to login.php works, but harm is done, spam is sent out.

 

You may find that, a good in its merit fix, like:

$hacker_test = strtolower($_SERVER['PHP_SELF']); //reason why should not use a window server - strtolower
if (substr_count($hacker_test,'.php')) > 1 {
 // do something
}

... may fail to work.

 

 

Possible solutions:

 

solution 1

use Apache RewriteEngine - add this code to your admin .htaccess file on the top

RewriteEngine on
RewriteRule ^.*/login.php$ https://%{HTTP_HOST}/admin/login.php

It will rewrite anything to the left of "/login.php" with e.g.: https://www.yourdomain/admin/ giving you https://www.yourdomain/admin/login.php

 

By itself, this solution should prevent any attempts like:

https://www.yourdomain/admin/mail.php/login.php

and also anything like

https://www.yourdomain/admin/mail.php/any_garbage_here.php/login.php

 

 

solution 2 (may, or even should be used with solution 1)

 

step 1. keep fix mentioned above

step 2. move it somewhere below "tep_session_start();" in application_top.php

step 3. use osCommerce own redirect, not "Location ..."

 

$hacker_test = strtolower($_SERVER['PHP_SELF']); //reason why should not use a window server - strtolower
if (substr_count($hacker_test,'.php')) > 1 {

 // do something
    tep_redirect(tep_href_link(FILENAME_LOGIN));

}

 

solution 3

 

Use recent osCommerce code instead of fixes checking for double "php" in URL. It seems to do the job.

 

// redirect to login page if administrator is not yet logged in
 if (!tep_session_is_registered('admin')) {
   $redirect = false;

   $current_page = basename($PHP_SELF);

   if ($current_page != FILENAME_LOGIN) {
     if (!tep_session_is_registered('redirect_origin')) {
       tep_session_register('redirect_origin');

       $redirect_origin = array('page' => $current_page,
                                'get' => $HTTP_GET_VARS);
     }

     $redirect = true;
   }

   if (!isset($login_request) || isset($HTTP_GET_VARS['login_request']) || isset($HTTP_POST_VARS['login_request']) || isset($HTTP_COOKIE_VARS['login_request']) || isset($HTTP_SESSION_VARS['login_request']) || isset($HTTP_POST_FILES['login_request']) || isset($HTTP_SERVER_VARS['login_request'])) {
     $redirect = true;
   	}

if ($redirect == true) {
     tep_redirect(tep_href_link(FILENAME_LOGIN));
   	}

   unset($redirect);
 }

 

 

 

BTW:

 

If someone sees faults with my reasoning, please let me know.

Especially in case of RewriteMode

Share this post


Link to post
Share on other sites

 

If someone sees faults with my reasoning, please let me know.

Especially in case of RewriteMode

 

The fault in your reasoning imo is that you are focusing on the specific mail.php/login.php querystring as opposed to the actual problem.

 

As I've mentioned before ..

 

http://forums.oscommerce.com/topic/348589-serious-hole-found-in-oscommerce/page__view__findpost__p__1467014

 

The issue is that PHP_SELF (in its various forms) is being used in osCommerce to fascilitate acquiring the base filename. PHP_SELF is not reliable for this as it wrongly returns path based uris .. be that a hack like this one or the experimental urls or any other like Ultimate Seo Urls 5.

Share this post


Link to post
Share on other sites

TO: FWR

---------------

You are right.

Your approach is more systematic, but ... and do not get this as a "personal stroll" - I just try to get to the bottom.

 

Problem here is a bit different ... I suppose (suppose, since not much testing done by me so far).

I was overpowered by this exploit twice, eve thou second time, I had this as preventive:

 

if (substr_count($_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI'],'.php')>1) 
 {		
   header('Location: https://'.$_SERVER['SERVER_NAME'].'/admin/login.php');
 }

Taking your reasoning, I should have been fine, as on the very top of application top I tested for intrusion, pretty much the way you vote for.

 

I was not .. and I was not due to funny way server?/php? (unsure still here) handles "doubled" URIs (eg. mail.php/login.php) - again, presumption based on inadequate testing.

 

User may think that if he writes www.domain.com/mail.php/login.php and system takes him to login.php, he's fine.

 

Well ... he is not, as on the way "first" file (mail.php here) is being actually fired before instantaneous redirect to login.php. That momentary "firing" seems to be enough to send a spam.

User sees nothing, but mail.php file is there.

Try to cause error on top of mail.php, you will see it popping up, as it did without "fix".

 

Still escapes me how it bypass fix I pasted above in application_top.php?

 

Since it does, I moved checking one flight up, above php.

That's why I used Rewrite.

 

One more thing:

---------------

This "miraculous" popup of a first in line file in double URI happens only in conjunction with specially treated by system "login.php".

This is the reason I'm concentrating on "login.php".

 

Just noticed another lock-pick file: password_forgotten.php, so below should be added.

 

RewriteRule ^.*/password_forgotten.php$ https://%{HTTP_HOST}/admin/login.php

 

 

The fault in your reasoning imo is that you are focusing on the specific mail.php/login.php querystring as opposed to the actual problem.

 

As I've mentioned before ..

 

http://forums.oscommerce.com/topic/348589-serious-hole-found-in-oscommerce/page__view__findpost__p__1467014

 

The issue is that PHP_SELF (in its various forms) is being used in osCommerce to fascilitate acquiring the base filename. PHP_SELF is not reliable for this as it wrongly returns path based uris .. be that a hack like this one or the experimental urls or any other like Ultimate Seo Urls 5.

Share this post


Link to post
Share on other sites

TO: FWR

---------------

You are right.

Your approach is more systematic, but ... and do not get this as a "personal stroll" - I just try to get to the bottom.

 

Problem here is a bit different ... I suppose (suppose, since not much testing done by me so far).

I was overpowered by this exploit twice, eve thou second time, I had this as preventive:

 

if (substr_count($_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI'],'.php')>1) 
 {		
   header('Location: https://'.$_SERVER['SERVER_NAME'].'/admin/login.php');
 }

Taking your reasoning, I should have been fine, as on the very top of application top I tested for intrusion, pretty much the way you vote for.

 

I was not .. and I was not due to funny way server?/php? (unsure still here) handles "doubled" URIs (eg. mail.php/login.php) - again, presumption based on inadequate testing.

 

User may think that if he writes www.domain.com/mail.php/login.php and system takes him to login.php, he's fine.

 

Well ... he is not, as on the way "first" file (mail.php here) is being actually fired before instantaneous redirect to login.php. That momentary "firing" seems to be enough to send a spam.

User sees nothing, but mail.php file is there.

Try to cause error on top of mail.php, you will see it popping up, as it did without "fix".

 

Still escapes me how it bypass fix I pasted above in application_top.php?

 

Since it does, I moved checking one flight up, above php.

That's why I used Rewrite.

 

One more thing:

---------------

This "miraculous" popup of a first in line file in double URI happens only in conjunction with specially treated by system "login.php".

This is the reason I'm concentrating on "login.php".

 

Just noticed another lock-pick file: password_forgotten.php, so below should be added.

 

RewriteRule ^.*/password_forgotten.php$ https://%{HTTP_HOST}/admin/login.php

 

With the method I suggest mail.php is never loaded it is redirected to login.php by the core osCommerce code in application_top.php.

Share this post


Link to post
Share on other sites

It does work as you say in a scope of this problem (not saying it does not elsewhere, but I did not test it).

But I guess in this case, RewriteEngine surely ensures safety by not relying on php alone, so I'm keeping it.

 

With the method I suggest mail.php is never loaded it is redirected to login.php by the core osCommerce code in application_top.php.

Share this post


Link to post
Share on other sites

It does work as you say in a scope of this problem (not saying it does not elsewhere, but I did not test it).

But I guess in this case, RewriteEngine surely ensures safety by not relying on php alone, so I'm keeping it.

 

mod_rewrite just adds overhead and often misunderstood complexity .. php handling is preferable. Also the method I proposed handles the misshandling of PHP_SELF where as the RewriteRule just handles a redirect of one file login.php

 

PLUS it doesn't work if the site is based in a directory off the root as you set no RewriteBase.

 

PLUS it doesn't work anyway as I can circumvent your .htaccess rule simply by adding a slash /

 

http://www.mysite.com/admin/mail.php/login.php/ 

 

It's nice that you are thinking of this but posting things that don't work simply helps the hackers as someone may use it thinking it works.

Share this post


Link to post
Share on other sites

So, in a nut shell, what is the best way to secure our site?

 

I have posted my view several times. Whether you take my view or others is entirely up to you.

Share this post


Link to post
Share on other sites

I identified the fix for the "login hack" back in July and it is far simpler than the suggestions here.

 

In admin/includes/application_top.php find this code beginning around line 124:

 

// redirect to login page if administrator is not yet logged in
if (!tep_session_is_registered('admin')) {
$redirect = false;

$current_page = basename($PHP_SELF);

 

 

and change to:

 

 

// redirect to login page if administrator is not yet logged in
if (!tep_session_is_registered('admin')) {
$redirect = false;

$current_page = basename($_SERVER['SCRIPT_NAME']);

 

$_SERVER['SCRIPT_NAME'] is reliable on all server types .. all the various connotations of PHP_SELF are known to be "unreliable/hackable/spoofable".

 

osCommerce itself and many contributions (Which is why header tags throws errors with Ultimate Seo Urls 5 in standard mode) .. rely on PHP_SELF and there is a possibility if you have installed a contribution such as this .. or any other that relies on the return of PHP_SELF that you may get problems/redirect loops .. the solution is to replace all instances of $PHP_SELF or $_SERVER['PHP_SELF'] or $HTTP_SERVER_VARS['PHP_SELF'] with basename( $_SERVER['SCRIPT_NAME'] ).

 

PHP_SELF is used (in the main) to return the current file name and for this purpose should NOT be used .. $_SERVER['SCRIPT_NAME'] performs the same function but reliably ..

 

basename( $_SERVER['SCRIPT_NAME'] ) is what will return a valid filename for the currently executing file.

 

 

Yes this is work. http://oscommerce-extra.hu find the same!


:blink:
osCommerce based shop owner with minimal design and focused on background works. When the less is more.
Email managment with tracking pixel, package managment for shipping, stock management, warehouse managment with bar code reader, parcel shops management on 3000 pickup points without local store.

Share this post


Link to post
Share on other sites

Yes this is work. http://oscommerce-extra.hu find the same!

 

Glad it worked for you but I posted a more portable solution a bit further down.

Share this post


Link to post
Share on other sites

Hi Robert

 

In my site I have my admin folder renamed and pass protected via CP. Also have USU5 so i made an extra change in admindfolder/includes/application_top.php adding your code.

 

When not logged is impossible to apply the hack due to renaming&pass but when logged in I can execute the mail.php/login.php thing. Is that behaviour ok, only block redirects when not logged in?

 

Regards

Share this post


Link to post
Share on other sites

Hi Robert

 

In my site I have my admin folder renamed and pass protected via CP. Also have USU5 so i made an extra change in admindfolder/includes/application_top.php adding your code.

 

When not logged is impossible to apply the hack due to renaming&pass but when logged in I can execute the mail.php/login.php thing. Is that behaviour ok, only block redirects when not logged in?

 

Regards

 

 

The purpose of the hack is to bypass the login, if you are logged in you would not be re-directed to login anyway, ie you have requested mail.php, you are logged in so that what u get, regardless of what u put after.


Sam

 

Remember, What you think I ment may not be what I thought I ment when I said it.

 

Contributions:

 

Auto Backup your Database, Easy way

 

Multi Images with Fancy Pop-ups, Easy way

 

Products in columns with multi buy etc etc

 

Disable any Category or Product, Easy way

 

Secure & Improve your account pages et al.

Share this post


Link to post
Share on other sites

Hello everybody,

 

I have not found a solution that realy works...

 

I tried the method:

$hacker_test = strtolower($_SERVER['PHP_SELF']); 
if (substr_count($hacker_test,'.php') > 1 ) {
header('Location: http://www.myserver.com/');
//	tep_redirect(tep_href_link(FILENAME_LOGIN));
}

and it works when 2 .php files are provided in the url, but if I try a URL like www.myserver.com/orders.php/login it fails.

 

I also tried the method provided by FWR and it fails always, either I'm inserting it in the wrong place or it does not work.

 

I changed the half working fix to

$hacker_test = strtolower($_SERVER['PHP_SELF']); 
if (substr_count($hacker_test,'.php') > 1  || substr_count($hacker_test,'.php/') > 0 ) {
header('Location: http://www.myserver.com/');
//	tep_redirect(tep_href_link(FILENAME_LOGIN));
}

and it works, but I'm not sure it is the best approach.

Share this post


Link to post
Share on other sites

Hello everybody,

 

I have not found a solution that realy works...

 

 

 

Can you say which of FWR's code you have tried, the ealier does not cover all servers?

 

Can you also say server type (windows? pinch.gif ) and osC version.


Sam

 

Remember, What you think I ment may not be what I thought I ment when I said it.

 

Contributions:

 

Auto Backup your Database, Easy way

 

Multi Images with Fancy Pop-ups, Easy way

 

Products in columns with multi buy etc etc

 

Disable any Category or Product, Easy way

 

Secure & Improve your account pages et al.

Share this post


Link to post
Share on other sites

×