2

Lets say I have a php generated javasrcipt file that has the user's name, id number and email adress that is currently logged in. Would a simply document.location.href look up prevent remotes sites from determining the currently logged in user?

Would this be safe?

if(window.document.location.hostname == 'domain.com')
var user = {
          name:'me',
          id:234243,
          email:'email@email.com'
};
else alert('Sorry you may not request this info cross sites.');

Initially it appears safe to me.

EDIT: I had initially thought this was obvious but I am using cookies to determine the currently logged in user. I am just trying to prevent cross domain access to the users info. For example if the if statement was removed malicious site A could embed the javascript file and access the users info. By adding the if statement the user js object should never appear. Cross site ajax isn't supported therefore only through javascript insertion could the malicious site attempt to determine the currently logged in user.

EDIT 2: Would checking my http_refer using php be safe? What if caching is also enabled for the client? For example if the user visits my site A where the user script is downloaded and then later visits site B malicious site would the script be cached, therefore bypassing the need for the server to check the user's http_refer?

Lime
  • 13,400
  • 11
  • 56
  • 88
  • 1
    why need to put user info into javascript? php is server-side and already secured. anyway you might wanna use https :) – dragonjet May 07 '11 at 04:54
  • I am setting up a live ajax application and it is there for convenience. – Lime May 07 '11 at 05:03
  • then you just need to generate, re-fetch the user_info again on the ajax-loaded page. now that i know that you will use ajax to pass the user variable, then it is NOT safe. – dragonjet May 07 '11 at 05:32
  • Its not clear what attack you are trying to prevent. If this is CSRF, then answer is: **NO**. – rook May 07 '11 at 19:59
  • @Rock Then how would you advise fixing it? – Lime May 07 '11 at 20:25

3 Answers3

4

You're basically saying "here's the keys to the bank vault, here's the guard's schedule, and here's the staff schedule. But hey, if you're not from the Acme Security Company, pretend I didn't give this to you".

"oh, sure, no problem, lemme just pretend to shred this note and go rent a large truck haul away your vault contents with"

Marc B
  • 356,200
  • 43
  • 426
  • 500
1

You really just don't want to try something like this. Suppose I'm running an evil site; what do I do?

<script>
RegExp.prototype.test = function() { return true; };
</script>
<script src="http://yoursite.example.com/dynamicjs.php"></script>
<script>
alert("Look at the data I stole: " + user);
</script>
servn
  • 3,049
  • 14
  • 8
  • How would you advise linking to the script? Is there any workaround to prevent this? – Lime May 07 '11 at 20:26
  • I have changed the conditional to `window.document.location.hostname == 'domain.com'` and I am considering checking http_referrer. – Lime May 07 '11 at 21:52
  • Checking the referrer server-side is safe. I would be suspicious of anything in JS, although I can't think of anything off the top of my head that would break your check. – servn May 08 '11 at 03:33
  • Would caching allow a malicious site to bypass the referrer check? For example, user visits my site caching the script containing the users info. Then the user visits a malicious site which queries for the script which is already in the users cache, therefore there would be no response sent to my server checking for http_referrer. Would I have to disable caching for the script containing the users info or is there another solution? – Lime May 08 '11 at 03:45
  • I don't think so... but really, the most reliable thing is just not include sensitive information in .js files. If you're using php, you should be able to just server-side include the script into your main pages. – servn May 08 '11 at 18:22
0

No, what you have there is not "safe" in that it will reveal those details to anyone requesting the HTML page containing that JavaScript. All they have to do is look at the text (including script) returned by the server.

What it comes down to is this: Either you have authenticated the other end to your satisfaction, in which case you don't need the check in the JavaScript, or you haven't, in which case you don't want to output the details to the response at all. There's no purpose whatsoever to that client-side if statement. Try this: http://jsbin.com/aboze5 It'll say you can't request the data; then do a View Source, and note that you can see the data.

Instead, you need to check the origin of the request server-side and not output those details in the script at all if the origin of the request is not authenticated.

Update 1: Below you said:

I was specifically trying to determine if document.location.href could be falsified.

Yes, document.location can be falsified through shadowing the document symbol (although you might be able to detect that if you tried hard enough):

(function() {
    var document; // Shadow the symbol

    document = {
      location: {
        href: "http://example.com/foo.html"
      }
    };

    alert("document.location.href = " + document.location.href);
})();

Live copy

Cross-domain checks must happen within the browser's internals, nothing at the level of your JavaScript code can do it securely and robustly.

But that really doesn't matter. Even if it couldn't be falsified, the quoted example code doesn't protect the data. By the time the client-side check is done, the data has already been sent to the client.

Update 2: You've added a note about checking the HTTP_REFERER (sic) header (yes, it really is misspelled). Sadly, no, you can't trust that. HTTP_REFERER can be spoofed, and separately it can be suppressed.


Off-topic: You're probably already doing this, but: When transferring personal details you've promised to keep confidential (I don't know whether you have, but hopefully so), use HTTPS (e.g., SSL). But it's important to remember that while HTTPS ensures that data cannot be read in transit, it does nothing to ensure that the origin of the request is authenticated. E.g., you know the conversation is secure (within reason and current practice), but you don't necessarily know who you're talking to. There's where authentication comes into it.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • But wouldn't you need access to the client computer therefore providing a surplus of potential security threats? I thought javascript prevented cross site ajax. – Lime May 07 '11 at 05:01
  • @Lime: And if someone just requests that URL directly? From a browser or crawler/spider? Or via `curl`, or `wget`? Your code is literally just initializing a `user` object from an object literal, or not, based on the location. But the object literal is there for anyone to look at regardless of whether you use it to initialize `user` or not. – T.J. Crowder May 07 '11 at 05:03
  • I have a php auth system set up. It uses cookies to validate if the user is logged in. If someone requests the script with `wget` I would respond with either a blank page or empty `user` js object. Specifically I am using Kohana. I am just trying to prevent cross domain access to the currently logged in user's info. – Lime May 07 '11 at 05:05
  • @Lime: What it comes down to is this: Either you have authenticated the other end to your satisfaction, in which case you don't need the check in the JavaScript, or you haven't, in which case you don't want to output the details to the response at all. There's no purpose at all to that client-side `if` statement. Try this: http://jsbin.com/aboze5 It'll say you can't request the data; then do a View Source. – T.J. Crowder May 07 '11 at 05:11
  • I was specifically trying to determine if document.location.href could be falsified. – Lime May 07 '11 at 05:13
  • @Lime: It doesn't matter whether it can or not. In your quoted code, by the time you've done the check, the data has ***already*** been sent to the other end. It's too late at that point. And yes, `document.location` can be falsified through shadowing the `document` symbol although you could probably detect that if you tried hard enough: http://jsbin.com/aboze5/3 Cross-domain checks must happen within the browser's internals, nothing at the level of your JavaScript code can do it securely. – T.J. Crowder May 07 '11 at 05:16
  • @Lime: I've updated the answer to contain some of the points from the comments above. – T.J. Crowder May 07 '11 at 05:25
  • Well I am beginning to think the only safe method is checking http_referrer. Servn's code successfully exploits the if statement http://jsbin.com/ugalo4/. I added an edit 2 to the question with an additional route to take. Basically, would checking my http_refer using php be safe? – Lime May 07 '11 at 21:26
  • @Lime: You can't rely on `HTTP_REFERER` for anything related to authentication or security. I've updated the answer. I'm not understanding the problem, though: You're sending JavaScript in response to a request. That request is either authenticated via your authentication mechanism, in which case you can pass back the user details, or it isn't in which case you don't. No further checks are needed. What's the actual underlying problem you're trying to solve? – T.J. Crowder May 08 '11 at 07:28
  • User Logs into site creating cookie and session -> script on page loads user info -> user visits malicious site where the same script is loaded and user info is retrieved from the user object. By checking hostname this should avoid the problem. – Lime May 10 '11 at 06:07
  • @Lime: *"By checking hostname this should avoid the problem."* The fundamental point is that *by the time you're checking, it's **too late***. You've **already** sent the user details at that point. Then there's the fact that the check can be easily hacked around (as @servn and I have both shown, in different ways). – T.J. Crowder May 10 '11 at 06:15
  • How is it to late? Where is the malicious site able to retrieve the users info? Using this question as a source they can't http://stackoverflow.com/questions/1304653. Servn Did have a solution that originally exploited the script but has been fixed through the avoidance of regular expressions and function calls. Your solution hasn't hacked the script. When embedding a script into a site it has **reference to the global window object not the scope you have created** in the function. I don't need the ability to detect if it is being shadowed because it can't. You can't override the document. – Lime May 11 '11 at 02:30
  • @Lime: I'm sorry, I can't explain it any more clearly. The code you've posted in your answer is no more secure than a document which says "If you're not authorised to read further, don't read further" and then lists private info. If that document falls into un-authorised hands, that statement does ***nothing*** to stop the un-authorised person from reading further. Similarly, your `if` statement does ***nothing*** to stop a malicious site looking directly at the JS code and seeing the private details. (And you can retrieve script code without using ajax, without SOP issues. JSON-P for ex.) – T.J. Crowder May 11 '11 at 02:37
  • Just as example facebook currently does this http://developers.facebook.com/docs/reference/api/user/. – Lime May 11 '11 at 02:39
  • @Lime: I'm not an FB dev, and apparently that link is behind a login wall. But again, it doesn't matter. If the details are in the script, it does not matter what control flow you put in the script to protect the details. They are not protected from someone doing a `GET` on the script and just *looking* at it. – T.J. Crowder May 11 '11 at 02:40
  • **It doesn't matter if a script can do a php `GET` to the script because it depends on the users cookie which is only accessible from the browser.** A malicious site can't see the script because 1st it depends on the users cookie for that current domain name and second it the script is somehow cached the domain check would prevent the data from coming through. – Lime May 11 '11 at 02:42
  • @Lime: Again, my central point: Either you trust your authentication (e.g., the cookie or whatever), in which case the `if` is unnecessary, or you don't, in which case you can't output the user details. Full stop. – T.J. Crowder May 11 '11 at 02:49
  • I'm neutral to the current standings. I just attempted to remove my original up vote. I can't change my vote unless the post is reditted. I do appreciate your contribution. – Lime May 11 '11 at 02:59
  • @Lime: Sorry, someone downvoted exactly when we were chatting, and I did what I **always** warn people **not** to do and assumed it was you (didn't think anyone else would be here paying attention). I've removed my comment. Best, – T.J. Crowder May 11 '11 at 03:10