php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #69582 Sessions are not read from CLI
Submitted: 2015-05-06 06:23 UTC Modified: 2015-06-24 13:09 UTC
Votes:3
Avg. Score:4.3 ± 0.9
Reproduced:2 of 2 (100.0%)
Same Version:2 (100.0%)
Same OS:2 (100.0%)
From: me at spinov dot net Assigned:
Status: Analyzed Package: Session related
PHP Version: 5.4.40 OS: CentOS 6
Private report: No CVE-ID:
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: me at spinov dot net
New email:
PHP Version: OS:

 

 [2015-05-06 06:23 UTC] me at spinov dot net
Description:
------------
Session is created by Apache user ( apache ) via web interface. Everything is good and nice.

Then session is accessed via CLI and here is the problem:

If I access session from the same user ( apache ), then everything works.
If I access session from root user - I get:
PHP Warning: Unknown: Failed to write session data (files). Please verify that the current setting of session.save_path is correct (/var/lib/php/session) in Unknown on line 0

What I've tried:

- I can write/read file directly, under any of users mentioned.
- I've tried setting mode to 777 on directory/file.
- Same code worked in PHP 5.3. No changes to configuration has been made.

Test script:
---------------
<?php

# Create session from web and then try to execute the following script by root user

session_id(*session_id_here*);
session_start();



Expected result:
----------------
Receive session data in $_SESSION variable

Actual result:
--------------
PHP Warning: Unknown: Failed to write session data (files). Please verify that the current setting of session.save_path is correct (/var/lib/php/session) in Unknown on line 0

Patches

Add a Patch

Pull Requests

Pull requests:

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2015-06-11 01:53 UTC] yohgaki@php.net
-Status: Open +Status: Feedback
 [2015-06-11 01:53 UTC] yohgaki@php.net
I cannot reproduce by PHP-5.4 branch's PHP.
Sounds like you have selinux problem. Try

sudo setenforce 0

see if this helps.
 [2015-06-11 06:29 UTC] me at spinov dot net
-Status: Feedback +Status: Open
 [2015-06-11 06:29 UTC] me at spinov dot net
SELinux is disabled by config on boot. So it's not SELinux.

# getenforce                                                           
Disabled

I've also tried 5.5, 5.6 branches. Issue persists. If I rollback to 5.3 - everything works.
 [2015-06-11 06:44 UTC] rasmus@php.net
-Status: Open +Status: Analyzed
 [2015-06-11 06:45 UTC] rasmus@php.net
This doesn't sound like a PHP issue. Run:

  strace -o out.txt php your_script.php

And look through out.txt and and find where it tries to open the session file. That should give you a hint as to what could be wrong.
 [2015-06-11 07:04 UTC] me at spinov dot net
I did that as well, but strace doesn't show anything wrong. Here is part of strace with commands:
session_id("tsbet8evtiii516f15sk90if87");
session_start();

open("/var/lib/php/session/sess_tsbet8evtiii516f15sk90if87", O_RDWR|O_CREAT|O_N
OFOLLOW, 0600) = 3                                                             
fstat64(3, {st_mode=S_IFREG|0600, st_size=34530, ...}) = 0                     
getuid32()                              = 0                                    
geteuid32()                             = 0                                    
close(3)                                = 0                                    
gettimeofday({1434005695, 403384}, NULL) = 0                                   
gettimeofday({1434005695, 403464}, NULL) = 0                                   
open("/var/lib/php/session/sess_tsbet8evtiii516f15sk90if87", O_RDWR|O_CREAT|O_N
OFOLLOW, 0600) = 3                                                             
fstat64(3, {st_mode=S_IFREG|0600, st_size=34530, ...}) = 0                     
getuid32()                              = 0                                    
geteuid32()                             = 0                                    
close(3)                                = 0                                    
write(2, "PHP Warning:  Unknown: Failed to"..., 176PHP Warning:  Unknown: Faile
d to write session data (files). Please verify that the current setting of sess
ion.save_path is correct (/var/lib/php/session) in Unknown on line 0           
) = 176

Here is file info:

# stat /var/lib/php/session/sess_tsbet8evtiii516f15sk90if87                                                
  File: `/var/lib/php/session/sess_tsbet8evtiii516f15sk90if87'                                                     
  Size: 34530           Blocks: 72         IO Block: 4096   regular file                                           
Device: 801h/2049d      Inode: 175886      Links: 1                                                                
Access: (0600/-rw-------)  Uid: (  500/silveredge)   Gid: (  500/silveredge)                                       
Access: 2015-06-11 10:53:05.318976435 +0400                                                                        
Modify: 2015-06-11 10:53:04.417976479 +0400                                                                        
Change: 2015-06-11 10:53:04.417976479 +0400

If I change owner to root, everything works. Here is strace for that case:

open("/var/lib/php/session/sess_tsbet8evtiii516f15sk90if87", O_RDWR|O_CREAT|O_NOFOLLOW, 0600) = 3                  
fstat64(3, {st_mode=S_IFREG|0600, st_size=34530, ...}) = 0                                                         
flock(3, LOCK_EX)                       = 0                                                                        
fcntl64(3, F_SETFD, FD_CLOEXEC)         = 0                                                                        
fstat64(3, {st_mode=S_IFREG|0600, st_size=34530, ...}) = 0                                                         
pread64(3, "user-admin|a:11:{s:2:\"id\";i:5;s:"..., 34530, 0) = 34530                                              
mmap2(NULL, 266240, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb699e000                           
gettimeofday({1434006320, 576258}, NULL) = 0                                                                       
gettimeofday({1434006320, 576348}, NULL) = 0                                                                       
pwrite64(3, "user-admin|a:11:{s:2:\"id\";i:5;s:"..., 34530, 0) = 34530                                             
close(3)                                = 0

As you see, it looks a bit differently than previous one, cause file is not opened twice. But open call is the same with same result.
 [2015-06-11 07:10 UTC] me at spinov dot net
Also, as you see, in successful call, there is flock(), fcntl64(), pread64() calls, which are not present in case when session file is not owned by root.
 [2015-06-11 20:34 UTC] rasmus@php.net
So you are probably hitting this check:

https://github.com/php/php-src/blob/PHP-5.4/ext/session/mod_files.c#L190-L196

The file needs to be owned either by root or by the same user id your script is running as to avoid session hi-hacking. So I don't understand why it wouldn't work as root. The is checking sbuf.st_uid and it is it 0 it should skip right past that block. But I am also confused. Your original report said it didn't work as root, but your latest update says, "If I change owner to root, everything works." That's exactly what I would expect.
 [2015-06-14 07:38 UTC] me at spinov dot net
Ok, just to clarify root/not-root stuff:
- When session file is owned by non-root, and process is owned by root, it doesn't work ( first strace ).
- When session file is owned by root ( this is my phrase "If I change owner to root, everything works." ) and process is owned by root - everything works. ( second strace ).

Sorry if I confused you here.

Now with regards to your comment about hi-jacking: I believe it should be OS driven ( like in PHP 5.3 ): if OS allows to read session - PHP reads it. In case file is owned by UID #1 and I'm trying to access it with UID #2 - it will fail on OS level, cause session file is with 600 permission.

In my case - root can read the file on OS level, but PHP is not allowing it to do that. It doesn't make any sense, as I can still hi-jack session by changing ownership of session file ( as I'm root ). And I'm actually doing this workaround: chown-to-root(), read-session(), chown-back().

So the line you've referred seems to be the case as condition is true for session file owned by non-root and process owned by root. 

Probably this condition should be added with clause process owner is root. Cause you do have this for a file (sbuf.st_uid != 0)
 [2015-06-24 11:47 UTC] me at spinov dot net
Added 4 Pull Requests for branches 5.4, 5.5, 5.6, master.
 [2015-06-24 12:50 UTC] yohgaki@php.net
It may be better to update/add error message.

I think Stas' point is "only allow access root created session data when root is the user".

If you have root access, you can do 'su - user -s /bin/bash' to access the user's session file. Accessing by different user could cause problems like creating root owned session data files.

CLI has builtin web server also. We should be careful. 
Just my thought for now.
 [2015-06-24 13:09 UTC] me at spinov dot net
As for me, everything is pretty simple: if session will be created by root and then accessed by non-root user - this condition will stop script execution with error about reading/writing session data.

Regarding warning message or something with respect to current issue - there is nothing wrong happens: root accesses session of non-root on the host.

Use case: session is created by Apache ( non-root ), but later on accessed by backend service, that is running under root, due to requirement to execute root commands. I cannot allow Apache to be root user, cause this is insecure. So what options do I have in case of updated/added message?

Speaking more globally: I'm not sure if it is correct to override OS permissions. Cause in current edition of that condition there will be issue with accessing session data for groups. It is pretty rare situation, but probably somebody has use case for it. 

So I would fix this even in more radical way: if user that is running the script can read/write to session file he is requesting, on OS level - let him access it. Cause this limitation doesn't help with hi-jacking in any way as could be easily overriden.

And I believe this is the reason this condition was initially added as per comment.
 [2015-08-23 08:22 UTC] cpuidle at gmx dot de
+1 for fixing this. Daemon task running as root fails updating the session (php 5.4, 5.6) on debian. Currently stops me from upgrading our platform. 

Is there any progress on the PRs?
 
PHP Copyright © 2001-2017 The PHP Group
All rights reserved.
Last updated: Tue Aug 29 15:01:52 2017 UTC