[PHP-DB] $_SESSION issues - possible security hole?
I have built an application where users have to log in (the user data is stored in MySQL). I have 3 levels of rights for users; 1-normal rights, 2-admin rights, and 3-super user rights. When a user logs in, I set the $_SESSION['rights'] variable accordingly so I can reference it thru out the site. I have around a dozen pages where the login session information and the user rights piece work just fine. However, I'm creating an administration page where admins have some functionality but super users have all functionality and I've run into issues. I was using the session rights variable in a number of different IF statements to display and during a simple test I hit the refresh button on my browser and found that when I did so it CHANGED my session rights to those of a different user!?!? I have looked thru my code until I'm blue in the face and have even boiled the code down to the simpest display possible, yet when I hit refresh, it still changes the user and rights info (note all the other pages work fine). I have been able to determine that there must be something in my USERS query that is causing the issue. I changed the query to get data from a completely different table and show it in a select list and hitting refresh does NOT change the user or the user rights! So.does this mean querying the very table that lists users information (with data like rights and user in it) somehow can change the $_SESSION variables?? That appears to be what's going on, but I thought you had to explicitly assign the $_SESSION variables before they could be changed. Help!!! I have included my code and the database table structure below: ?php /*** Program is only available to admins and super users. This page allows for the adding/editing of user accounts and priveledges as well as allowing for application messages, application lockdown/shutdown, and standard parts administration. / include (php_header.inc); if ($_SESSION['rights'] != super) { header(location: landing.php); exit (); } /** ADMINISTER USERS */ $query1 = select * from USERS order by user; $result1 = mysql_query($query1) or die (Couldn't select all users - super); include (html_header.inc); echo p{$_SESSION['user']}, {$_SESSION['rights']}/p\n pform action='edit_user.php' method='post'Choose a user to edit: select name='user'\n; while ($row = mysql_fetch_array($result1, MYSQL_ASSOC)) { extract($row); echo option value='$user'$fname $lname - $user\n; } echo /select input type='submit' value='Edit User'/form/p\n /body\n /html; ? and here is the included file: ?php / This is the standard header for every page and should be included after the PHP opening tag on each page. This program ensures that all pages can only be accessed by users that are legitimately logged on. This program also allows for administratively disabling the application by super users. After disabling, only superusers can make changes. / session_start(); include (special_characters.inc); /** AUTHORIZATION CHECK */ if ($_SESSION['auth'] != yes) { header (location: index.php); exit(); } if ($_SESSION['rights'] != super) { $query = select * from APP_STATUS; $result = mysql_query($query) or die (Couldn't select APP_STATUS); $app = mysql_fetch_array ($result,MYSQL_ASSOC); if ($app['app_status'] == 2) { $msg = $app['app_message']; die($msg); } } ? my database table for the users looks like this: Field Type user varchar(20) PRIMARY KEY pwd varchar(255) fname varchar(20) lname varchar(20) email varchar(40) rights varchar(20) level varchar(20) credentials text admin varchar(20)
Re: [PHP-DB] $_SESSION issues - possible security hole?
If it changes the value of $_SESSION['rights'], then how come if ($_SESSION['rights'] != super) on line 14 doesn't exit()? Or does that happen when you hit refresh the second time? Or does the user it changes to also have 'super' rights? Why use extract()? Try commenting it out... apart from it being overhead in this case, it seems like a bad idea importing variable names into the symbol table for the global scope. It works since you're skipping the $type parameter and so EXTR_OVERWRITE is used, but this also doesn't seem anything to trust. Debugging PHP with XDebug usually helps me in cases like this. If you can, install it to your test server and do a trace. On Sun, Aug 10, 2008 at 7:34 PM, Darron Butler [EMAIL PROTECTED] wrote: I have built an application where users have to log in (the user data is stored in MySQL). I have 3 levels of rights for users; 1-normal rights, 2-admin rights, and 3-super user rights. When a user logs in, I set the $_SESSION['rights'] variable accordingly so I can reference it thru out the site. I have around a dozen pages where the login session information and the user rights piece work just fine. However, I'm creating an administration page where admins have some functionality but super users have all functionality and I've run into issues. I was using the session rights variable in a number of different IF statements to display and during a simple test I hit the refresh button on my browser and found that when I did so it CHANGED my session rights to those of a different user!?!? I have looked thru my code until I'm blue in the face and have even boiled the code down to the simpest display possible, yet when I hit refresh, it still changes the user and rights info (note all the other pages work fine). I have been able to determine that there must be something in my USERS query that is causing the issue. I changed the query to get data from a completely different table and show it in a select list and hitting refresh does NOT change the user or the user rights! So.does this mean querying the very table that lists users information (with data like rights and user in it) somehow can change the $_SESSION variables?? That appears to be what's going on, but I thought you had to explicitly assign the $_SESSION variables before they could be changed. Help!!! I have included my code and the database table structure below: ?php /*** Program is only available to admins and super users. This page allows for the adding/editing of user accounts and priveledges as well as allowing for application messages, application lockdown/shutdown, and standard parts administration. / include (php_header.inc); if ($_SESSION['rights'] != super) { header(location: landing.php); exit (); } /** ADMINISTER USERS */ $query1 = select * from USERS order by user; $result1 = mysql_query($query1) or die (Couldn't select all users - super); include (html_header.inc); echo p{$_SESSION['user']}, {$_SESSION['rights']}/p\n pform action='edit_user.php' method='post'Choose a user to edit: select name='user'\n; while ($row = mysql_fetch_array($result1, MYSQL_ASSOC)) { extract($row); echo option value='$user'$fname $lname - $user\n; } echo /select input type='submit' value='Edit User'/form/p\n /body\n /html; ? and here is the included file: ?php / This is the standard header for every page and should be included after the PHP opening tag on each page. This program ensures that all pages can only be accessed by users that are legitimately logged on. This program also allows for administratively disabling the application by super users. After disabling, only superusers can make changes. / session_start(); include (special_characters.inc); /** AUTHORIZATION CHECK */ if ($_SESSION['auth'] != yes) { header (location: index.php); exit(); } if ($_SESSION['rights'] != super) { $query = select * from APP_STATUS; $result = mysql_query($query) or die (Couldn't select APP_STATUS); $app = mysql_fetch_array ($result,MYSQL_ASSOC); if ($app['app_status'] == 2) { $msg = $app['app_message']; die($msg); } } ? my database table for the users looks like this: Field Type user varchar(20) PRIMARY KEY pwd varchar(255) fname varchar(20) lname varchar(20) email varchar(40) rights varchar(20) level varchar(20) credentials text admin varchar(20) -- PHP Database Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DB] $_SESSION issues - possible security hole?
Why use extract()? Try commenting it out... apart from it being If you use 'register globals' there's a good chance that a variable $rights exists because it's a key in your $_SESSION array (don't shoot me if I'm wrong, I've never worked with 'register globals'). By using extract() without the $type parameter (so with EXTR_OVERWRITE set), the $type variable is overwritten. So do try commenting it out. -- PHP Database Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DB] $_SESSION issues - possible security hole?
Thanks for your thoughts. To answer your first question, I'm using extract() because this is a page where admins and super users can edit the permissions of others for the site. Therefore, I have to query the database to create a listing of all users, and then have the admin/super user select one to modify (I was planning to serve the 'rights' informatin from the selected user via POST to another page where changes could be made). sometimes the user and rights that I get assigned when I hit refresh are another user with super rights and sometimes one with less than super rights and then I get sent to the 'die' landing page. I'm a real newbie at PHP/MySQL, so if there is a better/easier/more efficient way of creating the select list, I'm just not aware of how to do it. I just tried removing the extract statement and the select list is now empty... I'm using a free PHP/MySQL host online so I don't have access to make register_global changes, but I did find in the documentation that they have it set to on. On a similar note, the variable $_SESSION['rights'] does certainly exist, it exists for the admin/super user logged in and accessing the administration page. What's interesting about this whole thing is that I have changed the query to include non session variables I have set and everything works fine. For instance (to clarify) since I set $_SESSION['user'] and $_SESSION['rights'] when the user logs in, if my query to create the selection list is based on any other table columns (for instance, fname and lname and NOT user or rights) then the weird behavior does not show up. Having gone thru that...somehow, someway, the query of all user info seems to change the session variables. I appreciate your brain power thinking thru this! Any new thoughts? drb On Sun, Aug 10, 2008 at 2:33 PM, Evert Lammerts [EMAIL PROTECTED]wrote: Why use extract()? Try commenting it out... apart from it being If you use 'register globals' there's a good chance that a variable $rights exists because it's a key in your $_SESSION array (don't shoot me if I'm wrong, I've never worked with 'register globals'). By using extract() without the $type parameter (so with EXTR_OVERWRITE set), the $type variable is overwritten. So do try commenting it out.
Re: [PHP-DB] $_SESSION issues - possible security hole?
On Sun, Aug 10, 2008 at 4:23 PM, Darron Butler [EMAIL PROTECTED] wrote: Thanks for your thoughts. To answer your first question, I'm using extract() because this is a page where admins and super users can edit the permissions of others for the site. Therefore, I have to query the database to create a listing of all users, and then have the admin/super user select one to modify (I was planning to serve the 'rights' informatin from the selected user via POST to another page where changes could be made). sometimes the user and rights that I get assigned when I hit refresh are another user with super rights and sometimes one with less than super rights and then I get sent to the 'die' landing page. I'm a real newbie at PHP/MySQL, so if there is a better/easier/more efficient way of creating the select list, I'm just not aware of how to do it. I just tried removing the extract statement and the select list is now empty... I'm using a free PHP/MySQL host online so I don't have access to make register_global changes, but I did find in the documentation that they have it set to on. On a similar note, the variable $_SESSION['rights'] does certainly exist, it exists for the admin/super user logged in and accessing the administration page. What's interesting about this whole thing is that I have changed the query to include non session variables I have set and everything works fine. For instance (to clarify) since I set $_SESSION['user'] and $_SESSION['rights'] when the user logs in, if my query to create the selection list is based on any other table columns (for instance, fname and lname and NOT user or rights) then the weird behavior does not show up. Having gone thru that...somehow, someway, the query of all user info seems to change the session variables. I appreciate your brain power thinking thru this! Any new thoughts? drb On Sun, Aug 10, 2008 at 2:33 PM, Evert Lammerts [EMAIL PROTECTED] wrote: Why use extract()? Try commenting it out... apart from it being If you use 'register globals' there's a good chance that a variable $rights exists because it's a key in your $_SESSION array (don't shoot me if I'm wrong, I've never worked with 'register globals'). By using extract() without the $type parameter (so with EXTR_OVERWRITE set), the $type variable is overwritten. So do try commenting it out. You may want to consider not saving the data for the user rights in the session if its getting funky. Do a general query to the table on each page load where you want to check the data and rely just on the session cookie. Then you can make a simpler check to see if the user still has those permissions. Aslo judging from your post, the biggest hole will likely be that you are referencing the auto number of the user's id that is being changed. Changing that parameter would all changes to another users account easily... I would suggest using a md5 or sha1 hash to offset that possibility. -- Bastien Cat, the other other white meat
Re: [PHP-DB] $_SESSION issues - possible security hole?
There's your answer. With register_globals on $_SESSION['rights'] becomes $rights and when you do extract($row) you are overwritting the $_SESSION variable. A safer way of using your code would be: while ($row = mysql_fetch_array($result1, MYSQL_ASSOC)) { ? option value=?=$row['user']??=$row['fname']? ?=$row['lname']? - ?=$row['user']? ? Thank you, Micah Gersten onShore Networks Internal Developer http://www.onshore.com Darron Butler wrote: Thanks for your thoughts. To answer your first question, I'm using extract() because this is a page where admins and super users can edit the permissions of others for the site. Therefore, I have to query the database to create a listing of all users, and then have the admin/super user select one to modify (I was planning to serve the 'rights' informatin from the selected user via POST to another page where changes could be made). sometimes the user and rights that I get assigned when I hit refresh are another user with super rights and sometimes one with less than super rights and then I get sent to the 'die' landing page. I'm a real newbie at PHP/MySQL, so if there is a better/easier/more efficient way of creating the select list, I'm just not aware of how to do it. I just tried removing the extract statement and the select list is now empty... I'm using a free PHP/MySQL host online so I don't have access to make register_global changes, but I did find in the documentation that they have it set to on. On a similar note, the variable $_SESSION['rights'] does certainly exist, it exists for the admin/super user logged in and accessing the administration page. What's interesting about this whole thing is that I have changed the query to include non session variables I have set and everything works fine. For instance (to clarify) since I set $_SESSION['user'] and $_SESSION['rights'] when the user logs in, if my query to create the selection list is based on any other table columns (for instance, fname and lname and NOT user or rights) then the weird behavior does not show up. Having gone thru that...somehow, someway, the query of all user info seems to change the session variables. I appreciate your brain power thinking thru this! Any new thoughts? drb On Sun, Aug 10, 2008 at 2:33 PM, Evert Lammerts [EMAIL PROTECTED]wrote: Why use extract()? Try commenting it out... apart from it being If you use 'register globals' there's a good chance that a variable $rights exists because it's a key in your $_SESSION array (don't shoot me if I'm wrong, I've never worked with 'register globals'). By using extract() without the $type parameter (so with EXTR_OVERWRITE set), the $type variable is overwritten. So do try commenting it out. -- PHP Database Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DB] $_SESSION issues - possible security hole?
Thanks! In fact I just updated my code to your exact example below and it works! Its a good thing you all fixed this for me...I have very few hairs left! Thanks again everyone...drb On Sun, Aug 10, 2008 at 4:53 PM, Micah Gersten [EMAIL PROTECTED] wrote: There's your answer. With register_globals on $_SESSION['rights'] becomes $rights and when you do extract($row) you are overwritting the $_SESSION variable. A safer way of using your code would be: while ($row = mysql_fetch_array($result1, MYSQL_ASSOC)) { ? option value=?=$row['user']??=$row['fname']? ?=$row['lname']? - ?=$row['user']? ? Thank you, Micah Gersten onShore Networks Internal Developer http://www.onshore.com Darron Butler wrote: Thanks for your thoughts. To answer your first question, I'm using extract() because this is a page where admins and super users can edit the permissions of others for the site. Therefore, I have to query the database to create a listing of all users, and then have the admin/super user select one to modify (I was planning to serve the 'rights' informatin from the selected user via POST to another page where changes could be made). sometimes the user and rights that I get assigned when I hit refresh are another user with super rights and sometimes one with less than super rights and then I get sent to the 'die' landing page. I'm a real newbie at PHP/MySQL, so if there is a better/easier/more efficient way of creating the select list, I'm just not aware of how to do it. I just tried removing the extract statement and the select list is now empty... I'm using a free PHP/MySQL host online so I don't have access to make register_global changes, but I did find in the documentation that they have it set to on. On a similar note, the variable $_SESSION['rights'] does certainly exist, it exists for the admin/super user logged in and accessing the administration page. What's interesting about this whole thing is that I have changed the query to include non session variables I have set and everything works fine. For instance (to clarify) since I set $_SESSION['user'] and $_SESSION['rights'] when the user logs in, if my query to create the selection list is based on any other table columns (for instance, fname and lname and NOT user or rights) then the weird behavior does not show up. Having gone thru that...somehow, someway, the query of all user info seems to change the session variables. I appreciate your brain power thinking thru this! Any new thoughts? drb On Sun, Aug 10, 2008 at 2:33 PM, Evert Lammerts [EMAIL PROTECTED]wrote: Why use extract()? Try commenting it out... apart from it being If you use 'register globals' there's a good chance that a variable $rights exists because it's a key in your $_SESSION array (don't shoot me if I'm wrong, I've never worked with 'register globals'). By using extract() without the $type parameter (so with EXTR_OVERWRITE set), the $type variable is overwritten. So do try commenting it out.