PHP change content of session cookie file - php

I´m not sure If I am making a mountains out of molehills ...
I´ve two Servers A + B. I know on Server A exists a PHP Session with a session cookie. I know further in one of the session files (stored in var/lib/php5) exists a unique value like:
$_SESSION['name'] = "1_colourXY"
I can identify this cookie file with php by searching the dir/ files for this value (f.e.: file sess_489b9515146e7390ac03b5dabf36b70e).
I now want Server B to be able to tell A to store a new value to this explicit cookie file. My solution is:
Server B (which is not the client who has started the session!) calls a PHP file on Server A. After B has passed some security checks A should write a new value to this cookie file with file_puts_content. Note, as written Server B has not started the session so I think I cannot simple do
session_start();
$_SESSION['myval'] = "new val";
Therefore I have following questions:
Is there an easier (native session handling) way instead of file_puts… to write the value to the cookie file something like:
write $_SESSION['myval'] = "new val" to
sess_489b9515146e7390ac03b5dabf36b70e
The session Dir var/lib/php5 has chmod 773, to write and search within it I have to change rights to 777 (urrgh). How can I keep 773 but make it useable for php
If I open a cookie file a value looks like this: place|s:6:"Muster"; What does |s:6: mean?
Kind regards,
tony

You should use a DB like MySQL to store your sessions, then abstract all session calls into that database.
see 1.
This is how PHP types are serialized to a string. In this case s:6:"Muster" is a string 6 chars long, which happens to be "Muster".

Related

How to separate 2 PHP apps running on same server from using a common session

I have 2 separate PHP apps running on the same domain server: abc.com/demo & abc.com/live
There is session_start() on almost every PHP page in both these apps. As soon as a single user interacts with the second app, the first app freezes or stops working. I think the same session ID is being used by both, which causes this conflict.
I read on PHP manual that specifying the PHP session name like
session_name("DEMO");
or
session_name("LIVE"); may help.
My question is, do I need to specify the session_name on each and every PHP page in both the apps, or is only required when the session is first created, during the login success process.
Kindly advise. Thanks.
"On each and every ... page" is the right way.
But separate it into another script, and include that in other scripts.
Example
Because you name your sessions "DEMO" and "LIVE",
maybe place logic to decide session in a file which is shared and/or used by both apps.
$isProduction = ...;
session_name($isProduction ? "LIVE" : "DEMO");
session_start();
If you mean that your number of PHP files and you want to access some value that is stored in the PHP session then you should session_start(); for every file
You can separate your session like this
session_name($isAPP_ONE ? "APP_ONE" : "APP_TWO");
like store_session.php
session_start();
$_SESSSION["username"] = "Md Zahidul Islam";
home.php
session_start();
$_SESSSION["username"]; // this will give you Md Zahidul Islam
home-two.php
session_start();
$_SESSSION["username"]; // this will give you Md Zahidul Islam
And if you use work like this, then there is no need to use session_start(); on every file.
like header.php
session_start();
home.php
include("header.php");
$_SESSSION["username"]; // this will return you Md Zahidul Islam and this value will come from the store_session.php file
home-two.php
include("header.php");
$_SESSSION["username"]; // this will return you Md Zahidul Islam and this value will come from the store_session.php file

Can a script that was run by system command, access SESSION data of the running script?

When scriptA.php is run by some logged in user, an in turn will call another scriptB.php using a system() or exec().
Is it possible for scriptB.php to get parameters of the SESSION data of the user that run scriptA.php in the first place ?
Thanks!
No, you can't do it in the traditional way (using $_SESSION). The best way would be to pass the data as arguments to the CLI command or to write it to its STDIN (and read them in scriptB.php).
If you have permissions you could also go and read the session file (if you're handling sessions in files)... but that wouldn't be advisable.
If your question is about security concerns:
I'm inclined to say no. The second script won't have access to any of variables from first script.
BUT. If the server is (very) badly mis-configured, script B can try to access serialized session data from the temporary session directory used by PHP (session.save_path in php.ini).
If you want to pass data between script A and script B, you could use other ways to do it, like FIFOs, stdin, etc. Although I can't understand why you would like to execute one script from another one using exec().
If you're using standard file-based sessions, then you could have the parent script pass the session's ID to the child script as a command line parameter, e.g something like
shell_exec('php scriptB.php ' . session_id());
and then retrieve that ID within scriptB:
session_id($argc[1]); // argc contains command line args.
session_start();
I've never tried starting a session in a command-line script, so you may have to deal with cookie errors and the like. But even if you can't use session_start(), you can always access the session file directly and unserialize it, which'd be something along the lines of:
$sess_path = session_save_path() . '/sess_' . $argc[1];
$serialized = file_get_contents($sess_file);
$_SESSION = unserialize($serialized);
For other session systems, like a database, you'd access the database instead of messing with files.

Create temporary file and auto removed

I am writing a anti-leeching download script, and my plan is to create a temporary file, which is named by session ID, then after the session expires, the file will be automatically deleted. Is it possible ? And can you give me some tips how to do that in PHP ?
Thanks so much for any reply
PHP has a function for that name tmpfile. It creates a temporary file and returns a resource. The resource can be used like any other resource.
E.g. the example from the manual:
<?php
$temp = tmpfile();
fwrite($temp, "writing to tempfile");
fseek($temp, 0);
echo fread($temp, 1024);
fclose($temp); // this removes the file
?>
The file is automatically removed when closed (using fclose()), or when the script ends. You can use any file functions on the resource. You can find these here. Hope this will help you?
Another solution would be to create the file in the regular way and use a cronjob to regular check if a session is expired. The expiration date and other session data could be stored in a database. Use the script to query that data and determine if a session is expired. If so, remove it physically from the disk. Make sure to run the script once an hour or so (depending on your timeout).
So we have one or more files available for download. Creating a temporary file for each download requests is not a good idea. Creating a symlink() for each file instead is a much better idea. This will save loads of disk space and keep down the server load.
Naming the symlink after the user's session is a decent idea. A better idea is to generate a random symlink name & associate with the session, so the script can handle multiple downloads per session. You can use session_set_save_handler() (link) and register a custom read function that checks for expired sessions and removes symlinks when the session has expired.
Could you explain your problem a bit more deeply? Because I don't see a reason why not to use $_SESSION. The data in $_SESSION is stored server-side in a file (see http://php.net/session.save-path) BTW. At least by default. ;-)
Ok, so we have the following requirements so far
Let the user download in his/her session only
no copy & paste the link to somebody else
Users have to download from the site, e.g. no hotlinking
Control speed
Let's see. This is not working code, but it should work along these lines:
<?php // download.php
session_start(); // start or resume a session
// always sanitize user input
$fileId = filter_input(INPUT_GET, 'fileId', FILTER_SANITIZE_NUMBER_INT);
$token = filter_input(INPUT_GET, 'token', FILTER_UNSAFE_RAW);
$referer = filter_input(INPUT_SERVER, 'HTTP_REFERER', FILTER_SANITIZE_URL);
$script = filter_input(INPUT_SERVER, 'SCRIPT_NAME', FILTER_SANITIZE_URL);
// mush session_id and fileId into an access token
$secret = 'i can haz salt?';
$expectedToken = md5($secret . session_id() . $fileId);
// check if request came from download.php and has the valid access token
if(($expectedToken === $token) && ($referer === $script)) {
$file = realpath('path/to/files/' . $fileId . '.zip');
if(is_readable($file)) {
session_destroy(); // optional
header(/* stuff */);
fpassthru($file);
exit;
}
}
// if no file was sent, send the page with the download link.
?>
<html ...
<?php printf('a href="/download.php?fileId=%s&token=%s',
$fileId, $expectedToken); ?>
...
</html>
And that's it. No database required. This should cover requirements 1-3. You cannot control speed with PHP, but if you dont destroy the session after sending a file you could write a counter to the session and limit the number of files the user will be sent during a session.
I wholeheartedly agree that this could be solved much more elegantly than with this monkeyform hack, but as proof-of-concept, it should be sufficient.
I'd suggest you not to copy the file in the first place. I'd do the following: when user requests the file, you generate a random unique string to give him the link this way: dl.php?k=hd8DcjCjdCkk123 then put this string to a database, storing his IP address, maybe session and the time you've generated the link. Then another user request that file, make sure all the stuff (hash, ip and so on) matches and the link is not expired (e.g. not more that N hours have passed since the generation) and if everything is OK, use PHP to pipe the file. Set a cron job to look through the DB and remove the expired entries. What do you think?
tmpfile
Creates a temporary file with a unique
name in read-write (w+) mode and
returns a file handle. The file is
automatically removed when closed
(using fclose()), or when the script
ends.
Maybe it's to late for answering but I'm try to share on feature googlize!
if you use CPanel there is a short and quick way for blocking external
request on your hosted files which name is: HotLink.
you can Enable HotLinks on you Cpanel and be sure nobody can has request o your file from another hosting or use your files as a download reference.
To acheive this, I would make one file and protect it using chmod - making it unavailable to the public. Or, alternatively, save the contents in a database table row, fetch it whenever required.
Making it downloadable as a file. To do so, I would get the contents from the protected file, or if it is stored in a database table, fetch it and simply output it. Using php headers, I would, give it a desired name, extension, specify it's type, and finally force the browser to download the output as a solid file.
This way, you only need to save data in one place either, in a protected file or in database. Force client browser to download it as many times as the the conditions meet e.g., as long as the user is logged-in and so on. Without having to worry about the disk space, making any temp file, cronJobs and or auto-deletion of the file.

Looping Through All a Server's Sessions in PHP

Is there a way in PHP to get a list of all sessions (and the variables within each) on the server?
Basically, we have a maintenance function which needs to know which users are currently logged into the site. We already store data for each user in a session variable, but I am hoping that I can loop through each of these sessions and pluck out the data I need.
MY PHP is very limited (I am a .Net developer ussually) but if anyone knows if this is even possible (and how to do it) I'd be very grateful. I googled this, and the results I found tended to inidcate that it WASN'T possible, but I find this very hard to accept.
Still, If you can't you can't but I thought my buddies on StackOverflow could give me a definitive answer!
PHP stores session data for each user in a temporary folder on the server. This folder is defined in the php.ini configuration file under the variable session.save_path. Locate this value from within your php.ini file, or alternatively, create a php file with:
<?php echo "Session Save Path: " . ini_get( 'session.save_path');?>
as it's contents, and open the file in your browser.
Once you find the save path for the session data, open up that folder and you'll notice a fairly simple structure. All sessions are stored in the format: sess_$SESSIONID .
Session data is serialized before being stored on disk. As such, objects stored in the session file would have to be deserialized before being usable. However, if you're using plain text, which is stored as-is, to store your session data (ex. $_SESSION['userid'] = 1234) to store information about your users, it should be easy enough to parse out the data you're looking for from within the files.
One more thing ... I haven't looked into it, but it appears as though the session ID that appears in the filename corresponds directly to, for instance, the name of the PHPSESSID cookie stored on the user's computer. So, with this in mind, it may be possible to loop through the files within the temporary session directory, acquire all the $SESSIONID values, set the current session ID using session_id($SESSIONID), start a session with session_start() and access the data you need through PHP without having to parse the contents files themselves. Can anyone confirm whether or not this would be possible?
Edit: Adjusted post to match Itay's comment.
This will get you the data for all sessions, stored in an array and indexed by session id:
<?php
$allSessions = [];
$sessionNames = scandir(session_save_path());
foreach($sessionNames as $sessionName) {
$sessionName = str_replace("sess_","",$sessionName);
if(strpos($sessionName,".") === false) { //This skips temp files that aren't sessions
session_id($sessionName);
session_start();
$allSessions[$sessionName] = $_SESSION;
session_abort();
}
}
print_r($allSessions);
Here's a more succinct way to get a list of sessions via the stored files:
<?php
print_r(scandir(session_save_path()));
?>
I used the #mgroat method in the ajax call, but there is a problem in the header of the HTTP response that the Set-Cookie header appears multiple times and jQuery reports an error:
Set-Cookie header is ignored in response from url:
mysite.com/admin/ajax/main_ajax. Cookie length should be less
than or equal to 4096 characters.
The solution is to add header_remove("Set-Cookie") right after session_start().

PHP Session data not being saved

I have one of those "I swear I didn't touch the server" situations. I honestly didn't touch any of the php scripts. The problem I am having is that php data is not being saved across different pages or page refreshes. I know a new session is being created correctly because I can set a session variable (e.g. $_SESSION['foo'] = "foo" and print it back out on the same page just fine. But when I try to use that same variable on another page it is not set! Is there any php functions or information I can use on my hosts server to see what is going on?
Here is an example script that does not work on my hosts' server as of right now:
<?php
session_start();
if(isset($_SESSION['views']))
$_SESSION['views'] = $_SESSION['views']+ 1;
else
$_SESSION['views'] = 1;
echo "views = ". $_SESSION['views'];
echo '<p>Refresh</p>';
?>
The 'views' variable never gets incremented after doing a page refresh. I'm thinking this is a problem on their side, but I wanted to make sure I'm not a complete idiot first.
Here is the phpinfo() for my hosts' server (PHP Version 4.4.7):
Thanks for all the helpful info. It turns out that my host changed servers and started using a different session save path other than /var/php_sessions which didn't exist anymore. A solution would have been to declare ini_set(' session.save_path','SOME WRITABLE PATH'); in all my script files but that would have been a pain. I talked with the host and they explicitly set the session path to a real path that did exist. Hope this helps anyone having session path troubles.
Check to make sure you are not mixing https:// with http://. Session variables do not flow between secure and insecure sessions.
Had same problem - what happened to me is our server admin changed the session.cookie_secure boolean to On, which means that cookies will only be sent over a secure connection. Since the cookie was not being found, php was creating a new session every time, thus session variables were not being seen.
Use phpinfo() and check the session.* settings.
Maybe the information is stored in cookies and your browser does not accept cookies, something like that.
Check that first and come back with the results.
You can also do a print_r($_SESSION); to have a dump of this variable and see the content....
Regarding your phpinfo(), is the session.save_path a valid one? Does your web server have write access to this directory?
Hope this helps.
I had following problem
index.php
<?
session_start();
$_SESSION['a'] = 123;
header('location:index2.php');
?>
index2.php
<?
session_start();
echo $_SESSION['a'];
?>
The variable $_SESSION['a'] was not set correctly. Then I have changed the index.php acordingly
<?
session_start();
$_SESSION['a'] = 123;
session_write_close();
header('location:index2.php');
?>
I dont know what this internally means, I just explain it to myself that the session variable change was not quick enough :)
Check to see if the session save path is writable by the web server.
Make sure you have cookies turned on.. (I forget when I turn them off to test something)
Use firefox with the firebug extension to see if the cookie is being set and transmitted back.
And on a unrelated note, start looking at php5, because php 4.4.9 is the last of the php4 series.
Check who the group and owner are of the folder where the script runs. If the group id or user id are wrong, for example, set to root, it will cause sessions to not be saved properly.
Check the value of "views" when before you increment it. If, for some bizarre reason, it's getting set to a string, then when you add 1 to it, it'll always return 1.
if (isset($_SESSION['views'])) {
if (!is_numeric($_SESSION['views'])) {
echo "CRAP!";
}
++$_SESSION['views'];
} else {
$_SESSION['views'] = 1;
}
Well, we can eliminate code error because I tested the code on my own server (PHP 5).
Here's what to check for:
Are you calling session_unset() or session_destroy() anywhere? These functions will delete the session data immediately. If I put these at the end of my script, it begins behaving exactly like you describe.
Does it act the same in all browsers? If it works on one browser and not another, you may have a configuration problem on the nonfunctioning browser (i.e. you turned off cookies and forgot to turn them on, or are blocking cookies by mistake).
Is the session folder writable? You can't test this with is_writable(), so you'll need to go to the folder (from phpinfo() it looks like /var/php_sessions) and make sure sessions are actually getting created.
If you set a session in php5, then try to read it on a php4 page, it might not look in the correct place! Make the pages the same php version or set the session_path.
I spent ages looking for the answer for a similar problem. It wasn't an issue with the code or the setup, as a very similar code worked perfectly in another .php on the same server. Turned out the problem was caused by a very large amount of data being saved into the session in this page. In one place we had a line like this:$_SESSION['full_list'] = $full_list where $full_list was an array of data loaded from the database; each row was an array of about 150 elements. When the code was initially written a couple of years ago, the DB only contained about 1000 rows, so the $full_list contained about 100 elements, each being an array of about 20 elements. With time, the 20 elements turned into 150 and 1000 rows turned into 17000, so the code was storing close to 64 meg of data into the session. Apparently, with this amount of data being stored, it refused to store anything else. Once we changed the code to deal with data locally without saving it into the session, everything worked perfectly.
I know one solution I found (OSX with Apache 1 and just switched to PHP5) when I had a similar problem was that unsetting 1 specific key (ie unset($_SESSION['key']);) was causing it not to save. As soon as I didn't unset that key any more it saved. I have never seen this again, except on that server on another site, but then it was a different variable. Neither were anything special.
Thanks for this one Darryl. This helped me out. I was deleting a session variable, and for some reason it was keeping the session from committing. now i'm just setting it to null instead (which is fine for my app), and it works.
I know one solution I found (OSX with Apache 1 and just switched to PHP5) when I had a similar problem was that unsetting 1 specific key (ie unset($_SESSION['key']);) was causing it not to save. As soon as I didn't unset that key any more it saved. I have never seen this again, except on that server on another site, but then it was a different variable. Neither were anything special.
Here is one common problem I haven't seen addressed in the other comments: is your host running a cache of some sort? If they are automatically caching results in some fashion you would get this sort of behavior.
Just wanted to add a little note that this can also occur if you accidentally miss the session_start() statement on your pages.
Check if you are using session_write_close(); anywhere, I was using this right after another session and then trying to write to the session again and it wasn't working.. so just comment that sh*t out
I had session cookie path set to "//" instead of "/". Firebug is awesome.
Hope it helps somebody.
I had this problem when using secure pages where I was coming from www.domain.com/auth.php that redirected to domain.com/destpage.php. I removed the www from the auth.php link and it worked. This threw me because everything worked otherwise; the session was not set when I arrived at the destination though.
A common issue often overlooked is also that there must be NO other code or extra spacing before the session_start() command.
I've had this issue before where I had a blank line before session_start() which caused it not to work properly.
Adding my solution:
Check if you access the correct domain. I was using www.mysite.com to start the session, and tried to receive it from mysite.com (without the www).
I have solved this by adding a htaccess rewrite of all domains to www to be on the safe side/site.
Also check if you use http or https.
Edit your php.ini.
I think the value of session.gc_probability is 1, so set it to 0.
session.gc_probability=0
Another few things I had to do (I had same problem: no sesson retention after PHP upgrade to 5.4). You many not need these, depending on what your server's php.ini contains (check phpinfio());
session.use_trans_sid=0 ; Do not add session id to URI (osc does this)
session.use_cookies=0; ; ensure cookies are not used
session.use_only_cookies=0 ; ensure sessions are OK to use IMPORTANT
session.save_path=~/tmp/osc; ; Set to same as admin setting
session.auto_start = off; Tell PHP not to start sessions, osc code will do this
Basically, your php.ini should be set to no cookies, and session parameters must be consistent with what osc wants.
You may also need to change a few session code snippets in application_top.php - creating objects where none exist in the tep_session_is_registered(...) calls (e eg. navigation object), set $HTTP_ variables to the newer $_SERVER ones and a few other isset tests for empty objects (google for info). I ended up being able to use the original sessions.php files (includes/classes and includes/functions) with a slightly modified application_top.php to get things going again. The php.ini settings were the main problem, but this of course depends on what your server company has installed as the defaults.

Categories