简体   繁体   中英

Cookie without httpOnly, how insecure it is?

Im developing a web application which requires cookie to be set httpOnly = false .

Since, I find no other way to pass authentication cookies(for checking whether user has logged in successfully) from server side to be accessible via Javascript in my front end. This cookie is then used to send an AJAX request to my server side(added to the header). (Please do correct me if Im wrong and suggest me any other way)

My question:

How insecure is httpOnly = false ? Is it safe enough with just forcing it to use cookieSecureOption = true so that it will always be send via HTTPS.

How can I protect it from XSS attack?

A "non-HttpOnly cookie" isn't a vulnerability in itself.

An "HttpOnly cookie" mitigates the risk of an XSS attack. That is, any attacker injected scripts into your website will not be able to grab the value of this cookie, thus protecting the session.

If your application requires the use of the cookie value to add as a header, then you cannot mark this cookie as "HttpOnly". You can change the request handler to look for the value in the cookie rather than in the header (so you can set the flag), however this may put your site at risk of CSRF . The most secure approach is for your handler to check authorisation via a "HttpOnly" cookie, and to use another token value in a header ("non-HttpOnly") to check for CSRF. If these values are different, eg in the encrypted token pattern or the synchronizer token pattern , then there isn't much value in attacker in only retrieving the one value via XSS because they can't use it to authorise requests. Note that any XSS vulnerability is usually a bigger problem than a CSRF vulnerability, because the attacker could always use their XSS attack in order to submit requests directly from your site, however it is a much harder attack to accomplish. At least with "HttpOnly" they cannot grab the auth cookies from your site in order to remotely login.

The other cookie flag you mentioned is the secure flag . This will limit the cookie scope to https connections only, and is recommended if you are using https (which is also recommended). This does not affect whether JavaScript can access the value though.

If you do use a "non-HttpOnly cookie" then you can still mitigate the threat of XSS as follows.

  1. Move all script code into external js files and set a Content Security Policy to prevent any inline scripts from executing.

  2. Set the anti-XSS response header to mitigate reflected XSS attacks:

    X-XSS-Protection: 1; mode=block

  3. Make sure you are correctly encoding all user input when output (eg < becomes &lt; in HTML) and run a web security scanner against your application.

If you do not have HTTPOnly flagged, your users are still more vulnerable to XSS than they otherwise would be, as the cookie can still be accessed from JavaScript. From your description, you should not need access to the variable from JavaScript, simply access the cookie from the server side (which is still possible with HTTPOnly flagged, cookies are sent with every request including AJAX calls) to retrieve authentication information. The Secure flag and HTTPOnly flag defend against completely different attacks.

There is a hybrid way of doing this. I say hybrid because it involves half of what your doing and a mix of what bksi mentioned in a comment.

Since I do not know your full scenario this answer assumes you are just looking for a way to authenticate the user before allowing them to make changes or start a process server side; login, viewing an account page, and so on. You should never rely solely on httpOnly = false I would recommend using it with what is below.

A Solid Solution
Set a normal cookie when a user logs in successfully, this does not need to be sent over HTTPS although it would be nice. This cookie should be a randomly generated token for their session. I usually hash (md5 encrypt in PHP) their user id (assuming you use a database) and a time stamp of when they logged in. This insures the token is unique.

Now that you have a token saved on their local machine as a cookie also make sure to save this token in a PHP session which is server side. Now any time they visit a page or an AJAX request is sent you can compare the local cookie to the PHP session value server side. This is the fastest way you can authenticate a user interacting with your server. If the values match they are legitimate.

Now this is not entirely secure. The local cookie can always be edited which is something we usually don't care to much about because this will only harm the user by invalidating their session. On the flip side a crafty hacker could alter the PHP sessions and that could invalidate other users because their session was erased or hijacked. A hacker would have to get a legitimate session token and make a cookie to match.

The Better Solution(s)
1) On the server side you could use a database instead of PHP sessions. The process remains the same but now you need to do a bit more work of keeping the sessions table in your database up to date. Usually this is done by saving the token with a time stamp and updating this time stamp every time the token is checked. If the token is checked and the last time stamp is really old (you decide how long that is) you can un-authenticate the user by destroying their local cookie and having them sign in again. This is more resource intensive though and can slow down sites with large traffic loads.

2) Use a form of double authentication. This would be using PHP session 90% of the time for simple things but when an extremely important process comes up, say updating personal information or providing credit card information, check with the database as well. This would require two different cookies to be saved on the users machine. One if for checking PHP session for authentication and the second is for checking the database. This scenario would be really hard for a hacker to break through to the more important things because they would need to figure out both tokens and the database one is not easy to steal.

Final Thoughts
This is a fairly secure answer but you should still implement extra security precautions. It seems you are misunderstanding how cookies work in general; your recent comment sounds like your using cookies and ajax backwards but maybe I'm misunderstanding. Here is how I do it:

[User]-> Tries logging in to website with a login form
[Server]-> Checks this information against the database Pass, log 'em in.
[Server]->  Generate and set a random token as a cookie

I use PHP here and usually store this cookie with a name like sessionToken. This cookie immediately exists now on the users computer and we, the server, always have access to it server side; we can call it up any time. This is not really secure though because people could copy the cookie without the person knowing/ steal it as we send it to them. I'll deal with that in a minute.

[Server]-> Create a PHP session (session id: abc123) server side that has this same token.

This is step one in security. PHP sessions are not as easy to steal or hack. So even if someone steals our users token cookie when they try to use it on their computer it will fail. Here is a vaild user:

[User]-> (PHP session id: abc123) Tries to access secured page or content. PHP session is called up and is checked against the cookie token. If they equal each other this attempt passes.

Here the user has a session on the server they don't know about that recognizes who they are and can be accessed only by the server; usually. It is here where your AJAX request come into play. Every time the user tries to do something that you want to see if they are even allowed to do, send a request via AJAX to a PHP script that authenticates the user. All it does is send back PASS or FAIL. Then you can use AJAX or Javascript to do whatever you need. Here is a hacker exmaple:

[Hacker]-> Steals a cookie from a user over a cafe's wifi.
[Hacker]-> Tries to access the website you are on with it.
[Server]-> (PHP session id: ???) Doesn't have one, destroy the cookie and ask this user (the hacker) to login again.

This is as much information and help I can give. Your latest comments are starting to sound like new questions you should post on Stackoverflow.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM