CSRF vulnerability / cookies question - javascript

Just want to get input from people who know. I was considering CSRF vulnerabilities, and the seemingly the most popular method I know to fight against it. That method is to create a token in the returned html and adding a cookie with the same value. So if a script tries to do a post they would have to guess the token thats embedded in the web page for it to be successful.
But if they're targeting a specific website why can't they just use a script that
Calls a get on the page (the cookie will be returned even though the script can't access it)
Parses the html and gets the token
Calls a post with that token in it (the cookie that came back will be sent back)
They've successfully submitted a form without the users knowledge
The script doesn't need to know the contents of the cookie, it's just using the fact that cookies get sent back and forth all the time.
What am I missing here? Is this not possible? I think this is pretty scary if you think about it.
Below this line is not required reading to answer the question :)
This vulnerability banks on the fact that authentication is done based on cookies, which I think is the main way authentication is currently occurring.
Another solution I can think of is making authentication be on the page level. So
when they log in the returned html will have that token in it. every link that they click contains that token so when the web server gets a request it has a way to identify the user/session. The problem with it is that if they use any navigation other than that they will be 'unauthenticated'(e.g. type in a url) , also it doesn't look nice in the url because it would probably look something like this:
https://www.example.com/SuperSecretPage/1/123j4123jh12pf12g3g4j2h3g4b2k3jh4h5g55j3h3
But I do understand that if safety is more important, then a pretty URL is second place.
I don't know everything about cookies but what if user agents were a little more careful with their cookies?
For example, what if the cookies sent depended on the tab? We all surf using tabs by now, right? so what if the scope of the cookie was the tab? so if i have my banking site open on tab 1 and i'm surfing on tab 2, any scripts calling gets/posts on
tab 2 will only send the cookies accrued in tab 2.
Or what if cookies were stored / domain. So while I'm on example.com any cookies that come back go into the example.com cookie collection. and then when i'm on www.mybankingsite.com all the cookies get put into the mybankingsite.com collection. So if I go to example.com and it runs a script that calls a get/post the user agent will only send example.com cookies. This is different than sending the cookies of the requested domain. E.g. if a script calls a get of mybankingsite.com within a web page of example.com the user agent will not send the mybankingsite.com cookies.
I know i have no control over what user agents do, but I'm just exploring possibilities

So I think the problem here becomes the attacker's attempt to get the page's contents. To get the authenticated user's page, the attacker needs to be able to send a request on their behalf and read the contents. AJAX won't send cross-domain requests, iframes won't let you read the response. I am struggling to think of other ways in which an attacker would get the contents first.
A more likely hack is using clickjacking to have the user just submit the form. This technique doesn't seem too likely. (caveat: it's security, we can always be wrong.)

Does anyone care to share some code on this issue as I just hacked my own site (Not in production) with CSRF. All I had to do was the following
At: www.badguy.com/ write the following html
img src="www.goodguy.com/secure/user/delete/5">
What this does
So the admin goes to to www.badguy.com/ and the the image makes a request to
www.goodguy.com/secure/user/delete/5 from the users browser so the admin unknowingly just deleted a user. If you create a loop your in some trouble. Expect I never delete data just change its status :) but still I don't like the looks of this.

The CSRF token has to be unique per session. If a malicious server requests the same page, they will get a different token. If they try to request the contents of the page via JavaScript on the client's machine, the same-origin policy will prevent them.

Related

Cookie migration when changing domain

Recently I'm moving my website to a new domain, and I want to migrate user cookies to the new domain too, so they don't have to log in again.
After some research, I found there are two potential ways to do it:
Land user first on old-domain.com, update all cookies with new-domain.com so they can be accessed from new-domain.com, then do a browser redirect to new-domain.com;
Alternatively, on the new-domain.com, I can inject an iframe from old-domain.com, to let it write cookies to the new website...
I'm not sure if these two can achieve my goal to migrate cookies between domains. Is there a suggestied ways to do it, so that user doesn't have to sign in again to use the new domain?
I think something like #2 can work.
On the new page, check if the cookies are already set. If not, inject an iframe like:
<iframe src="http://old-domain.com/getcookies.html" style="height: 0; width: 0;">
getcookies.html will just contain Javascript that gets the cookies and uses postMessage() to send them to the new page. Javascript on the new page will receive the message and then set the cookies that it receives.
There are some potential issues with this:
Loading the iframe and having it send the cookies is asynchronous. What should the page do while it's waiting?
If you use cookies on the server, the above code doesn't set them until the client receives the page from the server. The server will need to deal with non-migrated users specially, by first sending them the script that copies the cookies, and it then redirects them back to the server script.
You have to deal with users that were never on the old domain. getcookies.html should detect that none of the cookies are set, and send back a message indicating this.
I suggest you add a new cookie migrated=yes that can be used to detect whether the user needs to go through any of this.

How does XSS Work - Especially when we have cross domain security?

I read How does XSS work? but I still don't get this point .
Scenario :
I run mybank.com site and an end user logs in to the site .
Someone "injects" malicious code by submitting a GET that gets printed or echoed back .
As far as I know your requests always goes to mybank.com because of cross domain request's disallowed by default .
So how do I actually manage to sent contents to mysite.com assuming mysite is a malicious user's site who wants to exploit mybank.com's XSS vulnerabilities ?
If I can't change point 3 , then probably there is no way I could do 4 . But if 4 can be done is it done by changing window.location.href or document.location i.e breaking assumption 3 ? Now it behaves like it is mysite.com ?
Or is there any other way you could hijack site without 4 ?
Once the code gets injected, there is no "security", the browser thinks that all the code that is running on the site belongs there.
Think about what you can do in your own web pages when you code. You can have JavaScript click on buttons, submit forms, click links, etc. You can have the code inject elements, more code, remove things, etc.
So imagine what a developer can do to an email app or a bank account. They could send emails or transfer money. Just need to fire the right steps.
Now how can they transfer information out? As simple as making a GET or POST request. They set up an end point somewhere and make a request to it. The end point logs the data. Requests can be made with AJAX, images, form submissions, loading up ifrmaes, etc.
Cross Domain requests are allowed if the other domain you want to talk to allows it.
GET requests are simple requests you can make just by loading a URL. Suppose the vulnerable page allows you to send a money order to someone using a pure GET request like this:
http://bank.com/sendmoney?user=attacker&amount=everything
Just by navigating to the URL means you want to send all of your money to the attacker (lol)... Suppose the only security is that you must be logged into bank.com
Now suppose you visit this attacker's website while logged into bank.com and he has an img element with the src attribute set to that URL. Just by visiting the page you've sent all of your money to the attacker. That's it in a nutshell.
Usually XSS means you are able to actually inject code directly onto the page because of the logic used on the server-side echo's the contents of a GET-request variable directly onto the page without sanitizing the input. Hopefully this helps you understand a little better.

How to log in remotely with AJAX?

I'm making a google-chrome-extension for a certain website, and want the browser_action to display the number of notifications a user has received on said website.
Currently, I am using an ajax request to retrieve the HTML from the website/messages page, and then I am using jQuery to count the number of "#unread > li" elements in that HTML (each one representing a new message.)
Now, I take this number and display it on the browser_action icon.
All works perfectly, the correct amount of messages are notified, BUT the user must be logged in on the site (not my site) for it to work properly, otherwise they will think that they have no messages.
I was thinking that I could detect if the user is logged in, and if not display a red ! exclamation mark on the icon. Then, when the user clicks to show the pop-up, it asks them to log in.
However, I have no idea how to actually log the user in to the website using this method: how do I send the credentials across? Or does the website have to support a request like this?
TL;DR
How can I log a user into a website I don't own remotely?
Disclaimer: I've never done a google chrome extension, but based on the rest of your question, it sounds like it's just working with JavaScript like any other web page, so I'll go ahead and answer it.
In any case, working with cookies in JavaScript can be somewhat of a pain:
https://developer.mozilla.org/en-US/docs/Web/API/document.cookie
http://www.perlscriptsjavascripts.com/js/cookies.html
I'm assuming that your server side already works with and expects cookies, so I won't try to suggest any alternatives. That being the case, your server is what needs to validate the cookie, so, IMHO, might as well set the cookie on the server side. If the server handles it, on the JS side, you simply post the username/password to a server-side page, e.g.
$.post("/user/login",{"Username":"foo","Password":"bar"},callback);
That server-side page validates the username/password and then, if successful, generates the cookie and sends a response back to the JavaScript (e.g. {"IsSuccess":true}). Upon receiving a successful response rather than an error, you just start calling the other web services to retrieve your data assuming you are logged in and build out the page.
Assuming that your web services will return HTTP error codes that help you determine a problem with the session, if you get a 401 error code, you take the user back to the login page. If you get a 403 error code, you let the user know they can't access that data...etc., all depending on your app.
Ultimately, JavaScript doesn't know whether a user is actually logged in, so you have to rely on the server to send you information in a way that is understandable so that you can direct/prompt the user as necessary.
[Edit: 2014-11-21]
You didn't answer my other question: what do you get back? If they don't set the cookie themselves at the login, then you need to get back the session token from the response they send...if they don't send you a session ID, you're SOL. If they do send you an session token/session ID, then you need to know what to name it (e.g. PHP uses something like PHPSESSID as the cookie name, but it can be whatever the coders of that domain decided on). Beyond that, you have to be able to set the cookie for THAT domain name (3rd party cookie). This may have mixed results depending on the user's settings--if they block 3rd party cookies--however, since this is a google extension and not a website, maybe it's able to bypass that kind of restriction. I know that FireFox's developer toolbar is able to manipulate cookies for all domains, so it would be a reasonable assumption you would be able to as well.

access cookies from email?

Is it possible to access cookies from an email? My fear is that one can for instance steal facebook login cookies simply by sending an email.
I know it's possible to redirect a user to an url without him to be aware of it. For instance, I used to display a 1x1 gif to redirect the user to a url (I used that to make email opening stats). What if on the target url I create a malicious js script: will I be able to access the user's cookies?
Or to put it differently, if there is a link in the email and the user clicks the link, is the target website able to access user's cookies?
I read this; does anyone have more details on the subject?
#user3345621
Thanks for your answer, it seems correct to me.
But to take on the facebook example again, I have a couple more questions:
I may be wrong, but I think the cookie encryption does not help in this case.
The cookie encryption will help to hide the password in case for instance I access
your local machine and look in the cookies directly.
However, if I steel the encrypted cookie, I will be able to use them,
and let facebook do the uncryption work.
So in other words, I think it does not matter whether or not cookies are encrypted,
as long as the application (facebook in this example) will decode them for you.
Now, same remark about the fact that the cookie is recreated.
I think this is a direct consequence of using session_regenerate_id function.
But anyway, my understanding (which may be wrong) is that even if the cookie is recreated,
if the hacker send you a malicious email, he will get the newest version of the cookies
anyway since in the technique I'm describing, you're redirected to a malicious website,
so that website, when opening would have access to the current cookies (if possible).
?
I might be incorrect, since I'm fairly new to application security.
Here goes my best shot, concerning cookies now:
Cookies are domain specific (FACT), when you have a facebook cookie storing your user ID and your email (perhaps?) only the facebook domain has access to that cookie. Also, in most cases, the information in your cookie, especially in enterprise systems such as facebook, is encrypted, in other cases a hash is used to mask the information (Sort of fact).
So let's take facebook as an example, since they use a strong encryption format (FACT). If for instance you were able to get hold of a users facebook cookie, you would need to de-crypt the information to start off with, for it to be of any use to you. By that time a new cookie would have been generated (darn facebook adddicts).
Onto the security issue, if by some means you were able to get hold of a users cookie that does NOT belong to your domain, it would be a hack (do'h!), and you would need to check for any browser (Yes you should be exploiting the browser), that has such an exploit, or look for one yourself..
So here they are:
Browser Exploit, hack a specific browser.
De-crypt (or de-hash) the cookie, if it's encrypted.
And do this all be for the cookie has expired.
And the world is yours.
I tried to send me an email with the following image:
<img src="http://localwebsite/js.php" />
On my local machine, I created a page at this url:
http://localwebsite/js.php
Which would alert("something") using javascript.
Sending the email to myself,
I expected that the mail client would open a web browser page and open the js popup,
but that's not the case at all.
What happened is that since it's not really an image,
my mail client (using mail on mac) did display a blue square exclamation mark,
indicating that he could not display that image.
Even if I click on "load images".
Then nothing more happens:
I presume the mail client goes to the url and tries to display the expected image in the message,
but since there is no image, nothing changes.
The url wasn't open in the browser at all, everything was done in the background.
Reading more about javascript in emails, it seems that generally, javascript is not interpreted at all
in emails.
I tested that too: sending an email containing:
<script type="application/javascript">alert("pou")</script>
Mail (mac) does not execute the script.
So to answer the question,
I believe that the only thing a hacker can do with mail is:
sending a link, then if you click on that link, anything can happen
create an image that he can use to track whether or not you've opened the mail
So if you're cautious enough, mail are'nt a big threat.
I was paranoid…

How to start a valid user session inside an iframe

I need to setup a Master Site that would embed Site 1 and Site 2 in iframes, login and start user sessions within them.
Site 1 (RoR) and Site 2 (unknown framework) has got their own authentication (username, pass, cookies, usual framework security).
Master Site (PHP) server has direct access to Site 1 database and I know the password hashing algorithm so I can validate Master Site's login password against Site 1. Site 2 can get their passwords to be changed accordingly if needed, but no access to db nor framework.
I cannot change anything in either Site 1 or Site 2, unfortunately. I can only build around it though full read access to Site 1 is present.
I've sketched a quick diagram to better show what I mean/need:
a busy cat http://gettaxi.me/public_img/help.png
I need to start a user session inside an iframe. The login credentials of Site 1 are identical to Master Site's as they come from the same db, credentials for Site 2 will be assumed same (might just show login failed if they're not).
Idea list so far:
I could record the login credentials into Master Site cookie and use it to populate the iframe fields. Maybe store an encrypted version and decrypt when needed? But still, storing a password in cookies (even encrypted) seems absurd.
Same as above but store it in Master Site session variable.
The idea of cross-domain cookies seem useless here because every site has to set it's own session cookies, one website can't set it for another...
I've never dealt with anything cross-domain like this so before. So before I go and start coding things like a mad man that might or might not work - I turn to you for help and advice! How would you go about accomplishing this? Is this possible at all?
Additional questions:
Do cookies set by Site 1 and 2 from within iframes behave the same? Are they persistent and if I'd open the same website NOT in an iframe later, would they be accepted?
If storing credentials (cookies/session) is the only way to go: how would I then populate the login fields in an iframe and submit the form? Javascipt? Some neat GET/POST/redirection trick?
Thanks in advance!
Ok, it turned out to be quite simple. And to stick it to the downvoters ... face - I'll post my own solution here, who knows, maybe someone will find it useful.
User logs in to Master Site
Validate credentials
Generate a random client token
Encrypt the password with that token and store the crypto in a session variable
Set a cookie and store that token in users browser
jQuery actions when Link to Site 1 or 2 is clicked:
Send an ajax request to server with that token
Validate user session and decrypt stored password on success
Send the password back to client and pre-fill username and password fields of a hidden form that mimics the iframed website's login form
Submit that form with target="iframe"
Clear those form pre-filled form fields
Vuala, a working cross-domain iframe auto-login...
Of course there's more going on like hiding, unhiding divs on button clicks, session timeouts, token expiry renew upon any user action and so on, but the main thing is that it works! Yes, the password is sent in plain 3 times but none of those websites have HTTPS in place anyway. The password is not stored in plain either.
Update:
Spoke too soon. There are issues with IE and Safari when iframe content returns Access-Control-Allow-Origin headers. Their stronger security policies treat iframe content with caution and do not allow session cookies to be saved. It can either be fixed by dropping privacy setting by a notch in IE, allowing 3rd party cookies in Safari or simply detecting the browser and if it's one of the above - open it in a new tab/window.
Otherwise, works fine in: Chrome, Firefox, Opera and Maxthon

Categories

Resources