Why does Magento use 2 cookies per session? - security

For data security and privacy reasons I want to know why Magento uses two cookies for one frontend session.
All I know is that one of them is being set in Mage_Core_Model_Cookie::set(..) and the other one in Zend_Session::expireSessionCookie(), but still I can't seem to figure out what they are used for.
I just can't think of any reason why one would need a second cookie for the same domain.

I'm going to call this one vestigial code. Varien relies heavily on the Zend Framework as the underpinning for Magento, so many of the classes (Zend_Session for instance) are used as parent classes for Magento implementations.
The Varien-set cookie labeled "frontend" is namespaced for the section of the site you visit (e.g. you will have a separate "admin" cookie if you log in through the backend), whereas the Zend cookie appears to be global.
Also note that I was able to delete the Zend cookie without any apparent deleterious effects (my login session and cart remained accessible, and the cookie was not immediately replaced).

I was able to fix this by reversing the order of the session_start() call and the statement that sets the cookie in Mage_Core_Model_Session_Abstract_Varien::start(..). Those two lines now look like this:
$cookie->set(session_name(), $this->getSessionId());
session_start();
It now only creates one single cookie and it does not seem to have any side-effects.
BTW: The other cookie was not created in Zend_Session as I assumed, but instead both of them came from Mage_Core_Model_Session_Abstract_Varien::start(..).

That is interesting. I just checked on an install of enterprise edition and only "PHPSESSIONID" is set, "frontend" and "admin" are missing even when logged into both. Perhaps this is something still actively being developed.

Related

Launching Custom Applications from the browser

I have been looking around SO and other on-line resources but cant seem to locate how this is done. I was wondering how things like magnet links worked on torrent website. They automatically open up and application and pass the appropriate params. I was wondering how could I create one to send a custom program params from the net?
Thanks
s654m
I wouldn't say this is an answer, but it is actually too long for a comment to fit.
Apps tend to register as authorities that can open a specific scheme. I don't know how it's done in desktop apps (especially because depending on each OS, it will vary), but on Android you can catch schemes or base urls by Intent Filters.
The way it works (and I'm pretty sure the functionality is cross-OS) is:
Your app tells the system it can "read" a specific scheme or base url (it could be magnet:// or even http://www.twitter.com/).
When you try to open a URI (Uniform resource identifier, a supergroup that can contain URLs), the system searches for any application that was registered for that kind of URI. I guess it runs from more specific and complete formats to the base. So for instance, this tweet: https://twitter.com/korcholis/status/491724155176222720 may be traced in this order:
https://twitter.com/korcholis/status/491724155176222720 Oh, no registrar? Moving on
https://twitter.com/korcholis/status Nothing yet? Ok
https://twitter.com/korcholis Nnnnnnope?
https://twitter.com Anybody? Ah, you, Totally random name for a Twitter Client know how to handle these links? Then it's yours
This random twitter client gets the full URI and does something accordingly.
As you see, nobody had a chance to track https://, since another application caught the URI before them. In this case, nobody could be your browsers.
It also defines, somehow, a default value. This is the true key why browsers tend to battle to be your default browser of choice. This just tells you they want to be the default applications that catch http://, https:// and probably some more.
The true wonder here is that, as long as there's an app that catches a scheme, you can set the one you want. For instance, it's a common practice that apps from the same developer contain the same schemes, in case the developer wants to share tasks between them. This ensures the user will have to use a group of apps. So, one app can just offer data such as:
my-own-scheme://user/12
While another app is registered to get links that start with
my-own-scheme://
So, if you want to make your own schemes, it's ok, as long as they don't collide with other's. And if you want to read other's schemes, well, that's up to you to search for that. See? This is not a real answer, but I hope it removes almost all doubt.

How do I protect sensitive information from cross site access?

My web application displays some sensitive information to a logged in user. The user visits another site without explicitly logging out of my site first. How do I ensure that the other site can not access the sensitive information without accept from me or the user?
If for example my sensitive data is in JavaScript format, the other site can include it in a script tag and read the side effects. I could continue on building a blacklist, but I do not want to enumerate what is unsafe. I want to know what is safe, but I can not find any documentation of this.
UPDATE: In my example JavaScript from the victim site was executed on the attacker's site, not the other way around, which would have been Cross Site Scripting.
Another example is images, where any other site can read the width and height, but I don't think they can read the content, but they can display it.
A third example is that everything without an X-Frame-Options header can be loaded into an iframe, and from there it is possible to steal the data by tricking the user into doing drag-and-drop or copy-and-paste.
The key point of Cross Site Attack is to ensure that your input from user which is going to be displayed, is legal, not containing some scripts. You may stop it at the beginning.
If for example my sensitive data is in JavaScript format, the other site can include it in a script tag
Yep! So don't put it in JavaScript/JSONP format.
The usual fix for passing back JSON or JS code is to put something unexecutable at the front to cause a syntax error or a hang (for(;;); is popular). So including the resource as a <script> doesn't get the attacker anywhere. When you access it from your own site you can fetch it with an XMLHttpRequest and chop off the prefix before evaluating it.
(A workaround that doesn't work is checking window.location in the returned script: when you're being included in an attacker's page they have control of the JavaScript environment and could sabotage the built-in objects to do unexpected things.)
Since I did not get the answer I was looking for here, I asked in another forum an got the answer. It is here:
https://groups.google.com/forum/?fromgroups=#!topic/mozilla.dev.security/9U6HTOh-p4g
I also found this page which answers my question:
http://code.google.com/p/browsersec/wiki/Part2#Life_outside_same-origin_rules
First of all like superpdm states, design your app from the ground up to ensure that either the sensitive information is not stored on the client side in the first place or that it is unintelligible to a malicious users.
Additionally, for items of data you don't have much control over, you can take advantage of inbuilt HTTP controls like HttpOnly that tries to ensure that client-side scripts will not have access to cookies like your session token and so forth. Setting httpOnly on your cookies will go a long way to ensure malicious vbscripts, javascripts etc will not read or modify your client-side tokens.
I think some confusion is still in our web-security knowledge world. You are afraid of Cross Site Request Forgery, and yet describing and looking for solution to Cross Site Scripting.
Cross Site Scripting is a vulnerability that allows malicious person to inject some unwanted content into your site. It may be some text, but it also may be some JS code or VB or Java Applet (I mentioned applets because they can be used to circumvent protection provided by the httpOnly flag). And thus if your aware user clicks on the malicious link he may get his data stolen. It depends on amount of sensitive data presented to the user. Clicking on a link is not only attack vector for XSS attack, If you present to users unfiltered contents provided by other users, someone may also inject some evil code and do some damage. He does not need to steal someone's cookie to get what he wants. And it has notnig to do with visiting other site while still being logged to your app. I recommend:XSS
Cross Site Request Forgery is a vulnerability that allows someone to construct specially crafted form and present it to Logged in user, user after submitting this form may execute operation in your app that he didin't intended. Operation may be transfer, password change, or user add. And this is the threat you are worried about, if user holds session with your app and visits site with such form which gets auto-submited with JS such request gets authenticated, and operation executed. And httpOnly will not protect from it because attacker does not need to access sessionId stored in cookies. I recommend: CSRF

Multi-Domain Login

I'm working on a little node.js-project, and while googling alot, I kinda got a bit confused, but maybe some of you are able to point me towards the road again.
Several websites are generated by DocPad (excellent piece of software), and hosted on different domains.
All these websites shall now get a "login module" (which is also written in Node.js, using passport). Visually, it will look similar to the excellent login-slider from Web-Kreation (Here a demo). My plan was to use nginx and route all the /login-requests to the login-app, which is working fine.
The problem is rather related to the multiple domains, and the clientside implementation of it all. All logins use the same database.
Can I somehow use both together, and create the session-cookies from the Login-Module (which could use the same domain all the time)?
I'm answering my own question for reference, in case someone else comes across the same problem.
In the end, I solved my problem by having a bit of a different setup. Instead of a module, using the dns of each page, I use a central login-application for all sites. The sites itself do not require to access any personal information, so that's not a problem.
DocPad is still being used to generate the different websites (works excellent - I know I say this very often, but if there's a brilliant piece of software out, there's no reason to not mention it once in a while) statically, and all static content is delivered to the user using a CDN.
The login-system is a node.js-application using Redis as the only database. It is integrated via a simple iframe on all pages rendered by DocPad on login.example.com.
After successful login in 'login-app' you can create encrypted string with info about current user. You can pass this string back in get/post parameter with redirect to necessary domain. Encription key is known only to the 'login-app' and your websites. You can trust this encrypted data. It is necessary to make sure that every time the key is different for the same user. For example you can add the information about the time of login or random. After decrypting the data you can set authorization cookie for a particular domain.

Fully cached dynamic website

I would like to cache my website with memcache as much as possible. There are rare modifications (somewhat like in a forum) which I am perfectly ok with re-caching once change is made. My only concern is login information (similar to how stackoverflow has a bar on top). This is how I am doing it right now:
$('div#user_bar').load('/login-info/');
(jQuery on a fully cached page loads up userinfo)
However, I think I can do without dynamic pages completely. My idea is this:
On login: create cookie `logged_in`:true
On each page: if JS finds cookie is set: show links to logout, settings, etc
if not: show link to login page
On logoff: delete cookie
No actual userinfo is stored in cookies, not even username.
How secure, reasonable, sane is this? Any ideas? Am I missing something? Thank you.
Disclaimer: This is more of an exercise than a production environment. But I am trying to keep security and performance in mind nonetheless.
About your main target: Caching dynamic pages is reasonable. If you work on the ASP.NET platform, you might want to have a look at the output cache feature which does exactly this, even including dynamic substitutions. 4 Guys from rolla.com have a nice starter article with links to all the details.
Regarding the non-userspecific pages: I doubt that this can work for anything but the most simple pages. Web applications usually allow different operations for different users, and if it's only the change of your password. You probably have to pass specialized content to the client at some point, and that's where the dynamic substitutions of the ASP.NET output cache come into play.

PHP Session Security

Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
What are some guidelines for maintaining responsible session security with PHP? There's information all over the web and it's about time it all landed in one place!
There are a couple of things to do in order to keep your session secure:
Use SSL when authenticating users or performing sensitive operations.
Regenerate the session id whenever the security level changes (such as logging in). You can even regenerate the session id every request if you wish.
Have sessions time out
Don't use register globals
Store authentication details on the server. That is, don't send details such as username in the cookie.
Check the $_SERVER['HTTP_USER_AGENT']. This adds a small barrier to session hijacking. You can also check the IP address. But this causes problems for users that have changing IP address due to load balancing on multiple internet connections etc (which is the case in our environment here).
Lock down access to the sessions on the file system or use custom session handling
For sensitive operations consider requiring logged in users to provide their authenication details again
One guideline is to call session_regenerate_id every time a session's security level changes. This helps prevent session hijacking.
My two (or more) cents:
Trust no one
Filter input, escape output (cookie, session data are your input too)
Avoid XSS (keep your HTML well formed, take a look at PHPTAL or HTMLPurifier)
Defense in depth
Do not expose data
There is a tiny but good book on this topic: Essential PHP Security by Chris Shiflett.
Essential PHP Security http://shiflett.org/images/essential-php-security-small.png
On the home page of the book you will find some interesting code examples and sample chapters.
You may use technique mentioned above (IP & UserAgent), described here: How to avoid identity theft
I think one of the major problems (which is being addressed in PHP 6) is register_globals. Right now one of the standard methods used to avoid register_globals is to use the $_REQUEST, $_GET or $_POST arrays.
The "correct" way to do it (as of 5.2, although it's a little buggy there, but stable as of 6, which is coming soon) is through filters.
So instead of:
$username = $_POST["username"];
you would do:
$username = filter_input(INPUT_POST, 'username', FILTER_SANITIZE_STRING);
or even just:
$username = filter_input(INPUT_POST, 'username');
This session fixation paper has very good pointers where attack may come. See also session fixation page at Wikipedia.
Using IP address isn't really the best idea in my experience. For example; my office has two IP addresses that get used depending on load and we constantly run into issues using IP addresses.
Instead, I've opted for storing the sessions in a separate database for the domains on my servers. This way no one on the file system has access to that session info. This was really helpful with phpBB before 3.0 (they've since fixed this) but it's still a good idea I think.
This is pretty trivial and obvious, but be sure to session_destroy after every use. This can be difficult to implement if the user does not log out explicitly, so a timer can be set to do this.
Here is a good tutorial on setTimer() and clearTimer().
The main problem with PHP sessions and security (besides session hijacking) comes with what environment you are in. By default PHP stores the session data in a file in the OS's temp directory. Without any special thought or planning this is a world readable directory so all of your session information is public to anyone with access to the server.
As for maintaining sessions over multiple servers. At that point it would be better to switch PHP to user handled sessions where it calls your provided functions to CRUD (create, read, update, delete) the session data. At that point you could store the session information in a database or memcache like solution so that all application servers have access to the data.
Storing your own sessions may also be advantageous if you are on a shared server because it will let you store it in the database which you often times have more control over then the filesystem.
I set my sessions up like this-
on the log in page:
$_SESSION['fingerprint'] = md5($_SERVER['HTTP_USER_AGENT'] . PHRASE . $_SERVER['REMOTE_ADDR']);
(phrase defined on a config page)
then on the header that is throughout the rest of the site:
session_start();
if ($_SESSION['fingerprint'] != md5($_SERVER['HTTP_USER_AGENT'] . PHRASE . $_SERVER['REMOTE_ADDR'])) {
session_destroy();
header('Location: http://website login page/');
exit();
}
php.ini
session.cookie_httponly = 1
change session name from default PHPSESSID
eq Apache add header:
X-XSS-Protection 1
I would check both IP and User Agent to see if they change
if ($_SESSION['user_agent'] != $_SERVER['HTTP_USER_AGENT']
|| $_SESSION['user_ip'] != $_SERVER['REMOTE_ADDR'])
{
//Something fishy is going on here?
}
If you you use session_set_save_handler() you can set your own session handler. For example you could store your sessions in the database. Refer to the php.net comments for examples of a database session handler.
DB sessions are also good if you have multiple servers otherwise if you are using file based sessions you would need to make sure that each webserver had access to the same filesystem to read/write the sessions.
You need to be sure the session data are safe. By looking at your php.ini or using phpinfo() you can find you session settings. _session.save_path_ tells you where they are saved.
Check the permission of the folder and of its parents. It shouldn't be public (/tmp) or be accessible by other websites on your shared server.
Assuming you still want to use php session, You can set php to use an other folder by changing _session.save_path_ or save the data in the database by changing _session.save_handler_ .
You might be able to set _session.save_path_ in your php.ini (some providers allow it) or for apache + mod_php, in a .htaccess file in your site root folder:
php_value session.save_path "/home/example.com/html/session". You can also set it at run time with _session_save_path()_ .
Check Chris Shiflett's tutorial or Zend_Session_SaveHandler_DbTable to set and alternative session handler.

Resources