Forums / Upgrading to 1.5.x / Ajax script from 1.3.x hitting 'time_out' page because of action and method

Ajax script from 1.3.x hitting 'time_out' page because of action and method

Views: 1,177

Results 1 to 5 of 5
1 Feb 2013, 12:04 PM
#1
neekfenwick avatar

neekfenwick

New Zenner

Join Date:
Feb 2009
Posts:
101
Plugin Contributions:
0

Ajax script from 1.3.x hitting 'time_out' page because of action and method

Hi guys,

I thought I'd describe what I just encountered and see if there anyone particularly recommends a specific way of working around it. I'm bringing an ajax script over from a 1.3.8 Zen Cart called ajaxHandler.php. It sits in the root of the site and handles GET and POST requests from various bits of javascript I've extended Zen Cart with in our environment.

I've run into trouble with POST requests, because the requests in general look like this:
GET /ajaxHandler.php?action=get_something&param=foo
POST /ajaxHandler.php with post data action=save_something field=whatever

The GET completes just fine, but my POST results in the time_out.php response being sent back to my ajax handler, which obviously blows it up as it's nothing like the nice JSON response it was expecting.

There is code in init_sanitize.php in 1.5.1 that does this:

  if ((isset ( $_GET ['action'] ) || isset($_POST['action']) ) && $_SERVER['REQUEST_METHOD'] == 'POST')
  {
    $mainPage = isset($_GET['main_page']) ? $_GET['main_page'] : FILENAME_DEFAULT;
    if (!in_array($mainPage, $csrfBlackList))
    {
      if ((! isset ( $_SESSION ['securityToken'] ) || ! isset ( $_POST ['securityToken'] )) || ($_SESSION ['securityToken'] !== $_POST ['securityToken']))
      {
        zen_redirect ( zen_href_link ( FILENAME_TIME_OUT, '', $request_type ) );
      }
    }
  }

So, in the case of my POST, if an 'action' $_POST parameter exists, it enters this if block, and will then redirect to the "time_out.php" page if a securityToken session variable doesn't exist.

There seem to be two immediate solutions:

  1. change my 'action' parameter to something else. I've changed it to 'activity' and the offending if block is no longer entered and my script works fine.
  2. somehow make sure a $_SESSION['securityToken'] is set, so that even if this if block is entered, it passes the security test. I don't know anything about securityToken and would appreciate a little advice about how to go forward with it.

It seems to me that this hardcoded behaviour around the 'action' parameter is specific to Zen Cart, and it would be wiser to follow solution 1 and change my script at that logical point rather than to dig deeper. That is, not try to make my script fit into this expected parameter pattern of Zen Cart, because my script is not a core Zen Cart script. This is quite a pain, because all the stuff I'm bringing over from our old 1.3.x site uses the ajaxHandler.php script fairly heavily, so "action=whatever" is coded into many places and makes bringing the scripts into 1.5.1 more painful. I would guess Zen Cart is making sure things like customers.php?action=delete_customer are made to pass a security check.

On the other hand, perhaps I should make my script play nice with Zen Cart and set up a $_SESSION['securityToken']. Unfortunately, debugging this init_sanitize.php point in time during the request, I see no $_SESSION set up at all, even in the GET request to the admin script that loads the page (in my case /admin/product_videos.php, 'admin' is obviously something different).

So, do people generally make sure their ajax scripts don't send an 'action' parameter in their POSTS to avoid this problem, or do you try to make your ajax scripts set up a session and securityToken variable to make this test pass?

Advice appreciated :)
Nick

1 Feb 2013, 1:13 PM
#2
neekfenwick avatar

neekfenwick

New Zenner

Join Date:
Feb 2009
Posts:
101
Plugin Contributions:
0

Re: Ajax script from 1.3.x hitting 'time_out' page because of action and method

Slight update: seems I was wrong before, in my ajaxHandler.php POST there is a $_SESSION set up, and it does have a securityToken, so that is sane. However, the line in init_sanitize.php that reads:

      if ((! isset ( $_SESSION ['securityToken'] ) || ! isset ( $_POST ['securityToken'] )) || ($_SESSION ['securityToken'] !== $_POST ['securityToken']))

..will ensure that you include the current securityToken value in your POST, and that it matches the one in the session that served the originating page.

Unfortunately the originating page in my case is /admin/product_videos.php, which I can see sessions.php assigning one securityToken, and the ajax script that's being called is /ajaxHandler.php, and it seems this is dealt a different securityToken. This, the test of $_SESSION ['securityToken'] !== $_POST ['securityToken'] fails because they aren't the same. As far as I can tell, this is remedied by moving my ajaxHandler.php inside the admin dir, so that the $_SESSION['securityToken'] seen by each is the same, however I'd prefer to leave my ajax script in the root. Perhaps that's not the Zen Cart way, I'll have to see.

The original question about the 'action' request parameter and whether one should try to play nice with the method='POST' and $_SESSION['securityToken'] check stands :)

1 Feb 2013, 7:49 PM
#3
drbyte avatar

drbyte

Sensei

Join Date:
Jan 2004
Posts:
63,515
Plugin Contributions:
176

Re: Ajax script from 1.3.x hitting 'time_out' page because of action and method

For security protection reasons like XSS etc, all admin requests which trigger any CRUD operation (other than perhaps Read) is expected to be passed via POST and be subjected to token validation. Hence the 'action' parameter triggering the validation of POST data.

.
Zen Cart - putting the dream of business ownership within reach of anyone!
Donate to: DrByte directly or to the Zen Cart team as a whole

Remember: Any code suggestions you see here are merely suggestions. You assume full responsibility for your use of any such suggestions, including any impact ANY alterations you make to your site may have on your PCI compliance.
Furthermore, any advice you see here about PCI matters is merely an opinion, and should not be relied upon as "official". Official PCI information should be obtained from the PCI Security Council directly or from one of their authorized Assessors.

2 Feb 2013, 4:06 AM
#4
neekfenwick avatar

neekfenwick

New Zenner

Join Date:
Feb 2009
Posts:
101
Plugin Contributions:
0

Re: Ajax script from 1.3.x hitting 'time_out' page because of action and method

Thank you DrByte, that makes perfect sense. So 1.5.1 enforces stricter security restrictions in its default security handling. I didn't mention before by my ajax script requires includes/application_top.php in its first line, which of course invokes all the usual auto_loaders and init_includes processing that any Zen Cart page request does.

Could you confirm for me that a request to /something.php will experience a different $_SESSION (and therefore $_SESSION['securityToken']) than /admin/something.php? I was confused by this and spent quite some time stepping through the debugger but couldn't see the cause of this difference. It would be nice to know that really is intended, or if that sounds like something is screwing up somewhere. I'm left with the knowledge that my /admin/product_videos.php page experiences one securityToken, yet the /ajaxHandler.php script it invokes via xhr experiences a different securityToken.

In conclusion, it seems that any ajax requests done to our custom scripts from the admin pages of the site must be made to endpoints within the admin URI, so /admin/product_videos.php must make requests to /admin/ajaxHandler.php. Requests to a script in the root of the web server will fail security checks. For me, this means breaking up my ajaxHandler.php into two files, one for the client side and one for the admin side. Not a huge deal but nice to know.

Nick

2 Feb 2013, 4:58 AM
#5
drbyte avatar

drbyte

Sensei

Join Date:
Jan 2004
Posts:
63,515
Plugin Contributions:
176

Re: Ajax script from 1.3.x hitting 'time_out' page because of action and method

Yes. The application_top for admin produces an entirely different session than the non-admin one. Thus your script is connecting to the wrong place and is unable to be authenticated.

If you need to float ajax in your admin and your storefront, you'll need two separate handlers. Much safer to actually locate your admin-specific ajax handler inside your admin folder anyway.

.
Zen Cart - putting the dream of business ownership within reach of anyone!
Donate to: DrByte directly or to the Zen Cart team as a whole

Remember: Any code suggestions you see here are merely suggestions. You assume full responsibility for your use of any such suggestions, including any impact ANY alterations you make to your site may have on your PCI compliance.
Furthermore, any advice you see here about PCI matters is merely an opinion, and should not be relied upon as "official". Official PCI information should be obtained from the PCI Security Council directly or from one of their authorized Assessors.