Is it save to use the session cookie PHPSESSID - php

When I read about something "PHP Session vers Cookie" often I found cookies are not mentioned to be save because they are stored at the client side in the browser. And of course a hacker can get access to the PHPSESSID cookie and get the session_id.
So meanwhile I am a little bit confused about the recommondation to run PHP always with the php.ini statements "session.use_cookies = 1" and "session.use_only_cookies = 1".
What could a hacker do if he get this cookie PHPSESSID whigh includes automatically the session_id?
Would it help to make a statement "session_regenerate_id();" after "session_start()"?
Even then the session cookie will be written to the client side and could be read by a hacker.
Am I right to say this makes the idea of a session cookie - which will identify the user even if the browser will be closed - useless?
This is really confusing.
I am a beginner with the security questions of PHP and Sessions. May be I could find some help here to understand this concept. I read already many post but I did not yet found the answer to my specific question.

The short answer is $_SESSION variables cannot be accessed client side e.g. $_SESSION['variable'] -> NOT stored on client. The $_SESSION id which is used to associate those variables to a client can be accessed as it's stored as a cookie which can be easily manipulated. So for example, if I created a login system which validated a user's credentials, it's common practise to then use this $_SESSION id or a session variable ($_SESSION['loginSuccess']) as the identifier that this login was a success so it can be allowed to access "Locked" pages. A client $_SESSION cookie is only active when the browser is open, if you close the browser down, your $_SESSION cookie will be forced to expire.
The huge security risk is if someone was able to gain access to your session variable using techniques like 'Man in the Middle' attacks (MitM for short). All they would need to do is manipulate there own session id cookie by replacing it with the authenticated cookie and then refresh the page. To get around this, just make your website has an SSL certificate installed from trusted CA (certificate authority e.g. GoDaddy) and enforce your web server to only allow HTTPS connections. This means that all your data transferred from server to client and vice versa is 1-to-1 encrypted.
Even after you have enforced HTTPS, it's worth noting that it's still possible for a MitM attack to be successful and access your encrypted data. This is usually done by the MitM software initiating the SSL acknowledgement on the clients behalf, after that, MitM presents a different SSL certificate (usually self-signed) to the client. By doing this, MitM software can see all encrypted traffic from client and server using 2x SSL certificates. Users would get an error in browser stating the certificate does not match the domain used or is not trusted (because of being self-signed), but as we know, some end users will no doubt accept this.
To overcome this issue, most banks check the validity of the client-side certificate using JS and then confirm server-side if it's valid. I've personally not had to go this length for the security of my sites but I'm sure it wont be long before this becomes best practise.
For MitM Info: https://security.stackexchange.com/questions/65794/it-is-possible-to-decrypt-https-traffic-when-a-man-in-the-middle-proxy-is-alread
For SSL JS: Within a web browser, is it possible for JavaScript to obtain information about the HTTPS Certificate being used for the current page?
For Session Hacking: Can session value be hacked?

Related

How to protect the cookies generated by the PHP after logging in

After logging in, the cookie is set by the PHP. But the text in the cookie is same for the user. So if someone gets the cookie then one can easily login by using the user's cookie he got.
Although I found that it is not possible to set or edit a cookie in the browser. But if someone (probably a hacker) happens to succeed in editing/replacing the cookies, then he can login easily.
I have tried XOR encryption but that doesnot make any difference.
How can I better protect my website?
Exploiting authentication process using cookies is part of session hijacking. You should learn that it is not only cookies which make your scripts vulnerable to this kind of attacks.
The impenetrable solution is HTTPS. The compromise for using cookies to store your login information is using HTTPS along side.
One doesn't have to have access to your PC to sniff your cookies and hijack the session. It can be done in a LAN or even in public wi-fi using simple programs as long as all your data are not fully encrypted end-to-end.
Warning: Header only encryption is not enough. See FiresSheep section of the following article
Session Hijacking

WebSockets + PHP (Ratchet) login system

I know how to make a secure login system with PHP including basics like hashing, salting and more complex security measures.
Recently I've been using Ratchet with WebSockets a lot. And I've been wondering if it is possible to create a secure register/login system using WebSockets.
User enters his data in form.
Data is validated and sanitized.
Password is hashed.
Everything is being sent to the server via WebSocket.
PHP stores it in MySQL database and salts the password's hash.
PHP returns a callback that registration finished via WebSocket.
User is granted access to the website.
I see it might work. My doubts are here: how secure is ws:// protocol? How to make sure that after logging in the user is the user that was logged? Some sort of sessions? Tokens?
Are there any frameworks/libraries/implementations of such a thing?
Questions are more out of plain curiosity over a new (kinda) piece of tech. If it doesn't work I'll just go for AJAX POST request. :)
No, it is not possible to set up a secure authentication using any of the current WebSocket servers written in PHP.
They all lack TLS support. (Even mine, though I do have an active development branch devoted to providing TLS support.)
Here is what is required for a secure authentication system with WebSockets:
Basic PHP security first:
Always transmit via TLS or some other secure transport system.
Use bcrypt or scrypt (or a future more secure system) to hash the password for storage in the database. Even a stretched SHA256 password with a salt generated from a cryptographically random source is now considered insecure.
Authentication tokens (such as the session token created by PHP and stored in the session cookie) must be cryptographically unpredictable.
Authentication tokens must not be available to non-TLS traffic or client scripts. (Strict enforcement of the Secure flag AND strict enforcement of the HttpOnly flag.) This explicitly means that a user can not be securely authenticated unless they are in https: and wss: mode.
Session data must be stored in a secure directory or data storage on the server.
Reset the session token as part of authentication. Completely delete the data associated with the old session ID.
PHP's built in algorithm for generating session IDs uses /dev/urandom if it is available on your system. Windows users do not get cryptographically random session IDs, though because most WebSockets implementations would require a Posix environment, this isn't an issue. If rolling your own session ID generator, use openssl_random_pseudo_bytes(), and remember that when it comes to security, it's a bad idea to roll your own.
Also, by default, the PHP session cookie does not have the Secure flag or the HttpOnly flag set. Change these in your php.ini, and yes, this means that people can not authenticate anyone who is not using a secure connection -- but this is true anyways, since without TLS, you can not ensure that anyone is the same user from request to request, even if they're using the same session ID and same IP.
And, by default, the PHP session save path is your system's temp directory. This is readable and writable by anyone. Thus, any rogue process, regardless of escalated privileges, can access and alter any session data. Least access means that only the web server user and, in the case of those of us using WebSockets, the WS server's user needs to access the session save path.
WebSockets specific authentication:
The session cookie is available to the WebSocket server during the handshake. This includes when the cookie has the HttpOnly flag set. (Tested on latest publicly available Chrome on Windows.) (Secure flag not testable yet. Give me a couple months as I get TLS working on my server. If secure cookies are not available, or are available in a non-secure context, I'll be personally raising a holy stink with the browser vendors on your behalf.)
This means that someone who has an authenticated session can also be pre-authenticated on their WebSocket connection without having to pass data through the web document body (no need to embed the session ID in the HTML or in data in a script tag, which would then be re-transmitted through the open WS connection).
As for securely authenticating someone using WebSockets... There is one huge caveat.
Because WebSocket servers have multiple users connected at the same time, the traditional sense of PHP sessions is broken. Which session do we mean?
Thus, the $_SESSION superglobal MUST be strictly off limits, and the session_...() functions should be considered highly dangerous. The only safe and meaningful session functions are the read-only version of session_save_path(), which tells you where to find the session files, session_encode(), and session_decode().
To get the session data, you will need to read the session file, running its contents through session_decode(), and associating the results with the specific connection for that specific user. You will also need to do this periodically, as the session data changes without warning. To persist any data to the session, session_encode() is your friend, of course. Since PHP doesn't care about race conditions on session data, you shouldn't either. Just read the file, change the data, and write to the file, and it'll be all good.
And this brings us to the first real problem: In order to have secure authentication, you need to reset the session token when the user is authenticated. Since client side Javascript can't write to an HttpOnly cookie, you can't change the session ID on the client side.
The status of whether the user is authenticated can easily be updated within the existing session data, of course. That's fairly trivial. However, because we need a new session ID before we persist the new authentication state, and that new session ID must be valid for all of the client's connections immediately, we can't completely perform secure authentication through a WebSocket connection.
A possible work-around to use as much WebSockets as possible (once a PHP WS server supports TLS, that is):
Client sends login information to the server through the WebSocket connection.
Server responds back with a cryptographically random token.
Client responds back with a salt through the WS connection, and with a hashed and salted version of the token through an AJAX request.
Server verifies the salt matches, and using the AJAX request's script, calls session_regenerate_id(true), and returns any appropriate response (just so long as the set-cookie: header is set).
Server updates its internal mapping to the user's new session ID.
Server discards the one-time token completely, and naturally logs any attempted use of any invalid one-time tokens.
(It might be worth it to implement a true Diffie-Hellman exchange to set up a true secure shared secret. I am not a security expert; the above algorithm may not be as secure as I think it is, though because it would already be in two TLS tunnels, it should be secure. (The https: tunnel is separate and distinct from the wss: tunnel, thus there is a need to confirm information sent through one tunnel matches information sent through the other, but should not require secrecy in addition to that already afforded by TLS.))
Bottom line:
Yes, security is hard to get right. But it's worth it.

PHP token security

I wrote a PHP application which requires a login. This application is private so no new users can register. First I used sessions to identify the users but it lead to problems on tablets because they lost their sessions. I think this is because of energy saving operations.
Now I changed my application to generate a random security token. So the authentication is as the follows:
Log in
Generate random security token and save it to disk
Redirect the browser to http://myhost/site?id=[securitytoken]
On the server side I check if the file exists - if yes, user is authenticated
Everything is now working perfectly I am just thinking about security concerns. It is no problem if the user sees the security token. Is it somehow possible to find out the token when I use GET? I am using SSL.
I tried to change the expiration times and cookie lifetimes. On a normal computer it is working as it should. On the table it is also working IF it does not go into standby (meaning the screen gets black). If the screen gets black, the session expires very soon.
There is no vulnerability inherent to using GET instead of, for example, POST from a network perspective.
The only caveat you should keep in mind is that a GET request is more likely to be stored on the client (e.g. browser history) in a way you might not intend. For these reasons, I typically use POST requests for authentication.
The problem you are attempting to solve sounds remarkably similar to "remember me" cookies. The linked blog post might be helpful in mitigating the security risks involved in designing token-base authentication systems.
Generally, web apps are confined to using localStorage and cannot silently read/write to files in the background. How are you accomplishing this?
When you say you're using SSL, do you really mean TLS or do you mean SSL version 3? If SSLv3, I would advise updating your stack and webserver configuration to support current best standards. TLSv1.2 with ECDHE and AES-GCM + SHA2 or ChaCha20-Poly1305 are ideal.
GET is more vulnerable than POST as it can be transmitted and stored:
In server logs by default.
In corporate proxy logs.
In the referer header if your page uses external resources or links to external domains.
In your example you have a http URL (this could be a typo though as you said you are using SSL). Make sure you are using https URLs to protect this data in transit.
This approach could also be vulnerable to Session Fixation as an attacker could get the user to visit a URL containing, or redirecting to, the same session ID as the attacker. When the victim logs in, the shared session will be authenticated meaning the attacker is now also logged in. To protect against this, refresh the session ID upon login and logout.
Cookies are often the preferred approach for session handling as they are harder to attack in the above scenarios.
The issue with in URL variables in the get form means that for one : users can easily modify it (by accident or not) and they stay even when the link is copied somewhere.
If you send someone your link/someone gets your link with the id variable in it,is that a security risk to you?

Is it possible to read 3rd party cookies

Im familiar with reading cookies using php, but i was wandering if there is a way you can read a users browser cookies set by another 3rd party site (ie. not your own.)
Could somthing like this be written to view all of the users set cookies ?
print_r($_COOKIE);
No, it's impossible.
You can only read cookies that come from your own domain. The other cookies are not even sent to your server.
If you could read every cookies the user has, you would be able to obtain personal information such as their facebook password, connection to their bank etc.
It would be a serious breach of privacy, and as such, browsers do not send cookies except those from the same domain.
No
When you visit a website, your web browser requests information from that domain (somedomain.com), and that third-party domain is allowed to set a cookie. Each domain can only read the cookie it created, so there is no way anotherdomain.com could access the cookie created by somedomain.com.
To read a cookie you must match the domain that the cookie was originally created under. Browsers consider this a security principle and will not let a site access any cookies that they did not create.
Note that there are several other security considerations that could potentially circumvent this rule, such as DNSMasq in combination with spoofed browser certificates. This is why DNSSec (and SOPA) were such a hot issue; the security hole DNSSec plugs will also protect your cookies from getting stolen from your cookie jar.
There are real-world examples of security holes that have leaked in the past. See here for an example of an even different security vulnerability from 2008.
No, this is not possible, because browser only sends the cookie that set by your domain, usually, it's attached to header of the HTTP request if previously being set by the domain.
Third party cookie are those cookie that set by another domain in the context of the target domain, for example: while opening example.com it might has a banner from another website (example2.com), at this case, if example2.com set cookie it can't be read by example.com because they are from different Origin that Browser prevent even scripts to access it.
No, of course not. Otherwise your website would know my bank's login cookie, and you'd be able to steal all my money. Cookies are only available to the domain that set them.

User authentication in an SSL iframe

My web application is receiving increased attention and I need to provide additional security to protect my customers.
The biggest problem as I see it is that the user login data is sent as plain text. My goal with this question is to discern if the following approach is an improvement or not.
In extension I will need to get dedicated servers for my service. This proposed solution is temporary until then.
I am currently running my web application on a shared hosting web server which only provides SSL through their own domain.
http://mydomain.com
is equivalent to
https://mydomain-com.secureserver.com
My thought is to have:
http://mydomain.com/login.php
...in which an iframe opens a page from the secure server, something like this:
<iframe src="http://mydomain-com.secureserver.com/ssllogin.php"></iframe>
I authenticate the user in
ssllogin.php with the (hashed+(per
user based-randomly salted))
passwords from the database.
After proper session regeneration set a session verifying the authentication.
This session is then somehow transferred and verified on http://mydomain.com
Is this approach even possible to achieve? Would this be an improvement of my login security or just move the "point of interception of password" for the attacker to another instance?
All feedback is appreciated.
You don't need an iframe. Just make the action of the login form to point to https://yourdomain.com/login.php . In there you may check if user & password are correct, and then redirect again to plain http.
BUT this is not 100% secure. The fact that you are sending the user & password via https may prevent an attacker or sniffer to get that. But if you later revert to plain http, it is possible to this attacker/sniffer to hijack the session of any logged in user sniffing the session cookies of this user.
If you want more security (not 100%, but more than this previous option), stay always in https, for all resources (css, js, images too, not just your php/html files), and even serve the login page via https.
For some reasoning of these points, see firesheep (for the hijacking session problems) or the recent tunisian gov't attack on tunisian facebook/yahoo/gmail users (for serving even the login page via https).
edit: sorry, I misread your question. If the SSL domain is different than the not-ssl domain, you may have problems, as the session cookie only will work against the same domain or subdomains. So, if you do the login and send the session cookie from https://yourdomain.secure-server.com, it will only be sent back by the browser to yourdomain.secure-server.com (or *.secure-server.com if you will), but not to yourdomain.com. I think it's possible to make a wildcard cookie valid for all *.com subdomains, but it's better not to do this (do you want your users' session cookie be sent to evil.com ?)

Categories