Cookies - set across multiple domains - javascript

My company has a setup as follows:
subdomain1.domain1.com
subdomain2.domain1.com
subdomain3.domain1.com
subdomain4.domain1.com
subdomain5.domain1.com
subdomain6.domain1.com
subdomain1.domain2.com
subdomain2.domain2.com
subdomain3.domain2.com
subdomain4.domain2.com
subdomain5.domain2.com
subdomain6.domain2.com
On each site, bearing in mind there can be a hundred sites per subdomain, users can log in. We, as developers, have to test frontends across several browsers, but some work may only be required on a section once logged in.
I have written a userscript which enables us to save a username and password (and other details which I cannot mention because of confidentiality). The script checks to see if the user account exists by filling in the login form and clicking the submit button. If not, it registers for us - thus automating the registration process.
Sharing cookies between subdomains on the same domain is easy. If I am on subdomain1.domain1.com I can save a cookie which can be retrieved by subdomain2.domain1.com. However, I would also like to save these for domain2. I do not appear to be able to get this to work.
I can see two solutions from here - either:
1) attach an iFrame using the userscript, which loads a site on domain2. This then uses the querystring to decide what to set to what, or;
2) use a form with method="POST", and simply post to a file on each domain.
Either way will be resource intensive, particularly if the cookies are updated each time a cookie changes. We also have URL masking in place. So we'd also have to take into account sites like abc.clientdomain1.com, abc.clientdomain2.com etc.
Does anyone know of an easier way to do achieve this?

This answer is a slightly different version of my answer on the question "Set cookie on multiple domains with PHP or JavaScript".
Do what Google is doing. Create a PHP (or any other server language file) file that sets the cookie on all 3 domains. Then on the domain where the login is going to be set, create a HTML file that would load the PHP file that sets cookie on the other 2 domains. Example:
<html>
<head></head>
<body>
Please wait..........
<img src="http://domain2.com/setcookie.php?user=encryptedusername"/>
<img src="http://domain3.com/setcookie.php?user=encryptedusername"/>
</body>
</html>
Then add an onload callback on body tag. The document will only load when the images completely load that is when cookies are set on the other 2 domains. Onload Callback :
<head>
<script>
function loadComplete(){
window.location="http://domain1.com";//URL of domain1
}
</script>
</head>
<body onload="loadComplete()">
Now cookies are set on the three domains.
Source

Create a common domain specifically for your cookies and use it as a getter/setter API.
http://cookie.domain.com/set/domain1
http://cookie.domain.com/get/domain1
http://cookie.domain.com/set/domain2
http://cookie.domain.com/get/domain2
and so on.

Include a script tag from domain2 that sets the cookie using a username and hashed password:
<script type="text/javascript" src="http://domain2.com/cookie_login_page.php?username=johnsmith&hash=1614aasdfgh213g"></script>
You can then check to ensure that the hashed passwords match (one way).
Key points:
Make the hashes in the URL time sensitive by appending a timestamp that will be agreed upon by the server (for example, 16:00, 16:10, etc) before hashing the string. If you're using HTTPS this is less of an issue.
If your passwords are already hashed, it wont hurt to double-hash the passwords assuming the salts are the same on both servers.
Sample PHP code:
src:
<script type="text/javascript" src="/cookie_login_page.php?username=<?php echo $username; ?>&hash=<?php echo md5($password . date('H')); ?>"></script>
dest:
<?php
$password = get_password($_GET['username']);
if($_GET['hash'] == md5($password . date('H')) {
// set the cookie
}

For security reasons, sites cannot set or retrieve cookies on other domains. Scripting the form submit via javascript is likely the easiest to do, and will still store the cooikes you need in the browser cache.

As stated by others, you can't access cookies across domains. However, if you have control of the server code, you can return information in the body, and allow your client to read and store that information per server.
In my case, I'm connecting a single client to multiple servers, maintaining an authenticated connection to each one. I need to know when the session for each one is going to expire, so the authentication service returns the cookie, plus it modifies the body of the response to send the relevant data back, so that I can read that data and set my own cookies.
By doing this, I can manually track what I need. Won't work in every scenario, but might for some like me.

Related

Password_hash() need of pre-hashing before submit?

I'm using the PHP 5.5+ password_hash() function to hash my passwords before storage in the database. So far so good.
What I am a bit uncertain of is the need of pre-hashing the password that it sent from the form to my PHP script.
Now the form submit procedure is (in short terms) done like this:
HTML file which contains the form calls the controller script in form method=".." ->
Controller script recieves the call and picks the correct function ->
function execution and storage to database.
So basically the call is sent through three files from submit to storage.
I am thinking that somewhere along the line the data could be hijacked and seen in plain view since the hashing is done in the third and final file.
Should I be worried and somehow hash the password with some JavaScript during the initial submission of the form or is it safe? The final site will most likely use an SSL certificate but still I'm not 100% sure if I am safe or not.
Your concerns about hijacking the password between controllers are superfluous :
For an attacker to hijack the password while it's passed between different controllers it would mean the attacker has to be able to read the memory of the PHP process, which would require root privileges. If the attacker has root privileges, you have a bigger problem and your solution won't save you because that same attacker can also modify the PHP files to remove your "protection".
As for hijacking the password while it's flying through the Internet, the only solution is to use HTTPS - whatever Javascript cryptography/hashing you would do is pointless since an eavesdropper is also able to alter the page while it's being transmitted and serve a modified version of it without the additional "security" you added; there are many questions about trying to secure a login form without HTTPS on Security.SE, check them out :
https://security.stackexchange.com/questions/73917/techniques-to-make-a-login-page-safe-without-using-ssl
https://security.stackexchange.com/questions/37655/build-a-secure-channel-without-ssl-tls
https://security.stackexchange.com/questions/41845/login-security-without-ssl
https://security.stackexchange.com/questions/8924/what-is-the-best-way-of-securing-a-website-logon-without-ssl-or-preshared-keys

Javascript that will run only one one domain

I would like to create some javascript that will only run on a given domain. We want to give each of our subscribers a bit of javascript that they can only run on their domain. The javascript will create an iFrame and bring in a page, etc.
If the javascript is placed on a different domain, an error is thrown and the script stops and the iFrame page will not load. Before you say this is not possible, it is done by Google Maps.
So, in short, we would like to mimic what Google Maps is doing. You register a domain with Google, they give you code that has a key and if you place this code on any other domain, it will not work. How do they do it?
The hostname property of window.location contains a hostname. It can be faked, so you could try checking the Referer header when serving your script, too – but absolutely do not rely on that.
You could also do a bit of a validity check by making a request to a nonexistent page on that domain – it’ll be blocked by cross-origin policies if the developer is cheating.
Another possible solution is to use the IP address, since the code is placed on a server.
I've made an license script with this method, and so far only 2 mad customers, but that was because they moved their website to another server without me telling it.
I think its good to have a client check, but that can be by-passed, if someone figures out how the script works. So, always do a server-side check.
Here is some code I use for the license check, its server based.
Also, I removed some functions that are specific to my website.
I can't figure out how to post code so I put it on pastebin.
http://pastebin.com/ftEDXhTP
When you give the user their snippet of code, on the server-side, store a specific domain name with an identifier you give to the user. You will likely generate this code automatically, like StackOverflow did with your question. They called it 19850979, so let's use that as the identifier you give to your user for example. When the user puts the snippet in place, when they use the iframe for example, the URL referenced in the iframe must contain the identifier.
Not sure what your server-side technologies are, but generally this concept works across the board:
For example... your server saves this information in its database:
user-example-domain.com,19850979
Your user's iframe ( which you generate and give them ) references:
your-serving-domain.com/iframeloader/19850979
Now, in the code that handles /iframeloader/ and receives 19850979 as the identifier, compare the hostname of the referrer. This is the Referer header, which is an HTTP header field:
http://en.wikipedia.org/wiki/List_of_HTTP_header_fields
If the hostname of the referrer is value, continue loading the iframe. If not, abort and show some kind of informative error message.

Sending Post Data to remote site and displaying the results

I've read quite a few posts here asking roughly the same thing, but usually the person asking has access to the remote site and can use the methods available to achieve this. My situation is a bit different, and I just wanted to see if it was possible before spending time and effort trying to get it to work.
The site that I am trying to access is remote, I have no access to it in anyway, and it's only accessible from a computer logged into OpenVPN.
The tool that I am writing is trying to get the results of a form submit from the remote site. I don't want to parse the results or modify it in anyway. I just want to display the page with the Post Data sent. The remote site uses AJAX for the form submit.
It's code is as such:
<form name="MyForm" action="response_normal.php" method="post" onsubmit="xmlhttpPost('response_ajax_v2.php', 'MyForm', 'response', '<img src=\'pleasewait.gif\'>'); return false;">
Upon submitting on that page, three values are sent:
site : radio1
search : 000000000000
submit : Search Site
Is it possible at all for me to simply send that post data to the page and display it? I am hoping to do this in an iframe - since I can't do it server side due to VPN restrictions.
Since the computer you're accessing your offsite server from is on the VPN that has access to the remote system (and assuming this remote system is under your control), you could have the offsite server return some JavaScript that AJAX-pulls the data–in this case, a full HTML page–it needs from the remote system using a JSONP-like strategy.
I have used this technique for some small projects in the past.
From there, you are free to do with the data what you will–modify it, return it as is, or otherwise.
Personally, I would avoid the use of frames if possible. Of course, when strapped for time, nothing is off limits ;)
However, if the remote system IS NOT under your control (and they don't have a kickass CORS cross-access policy), your only option is, as you said in the body of your question, frames. Here is an example:
<!-- If the remote system is NOT under your control, it CANNOT respond with the X-Frame-Options header set to SAMEORIGIN or DENY! -->
<iframe id="inlineframe" src="http://www.randomwebsite.com" frameborder="0" scrolling="auto" width="800" height="300" marginwidth="5" marginheight="5" ></iframe>
//Depending on the JS you put here, you may get some "unsafe Javascript" warnings from certain browsers
~function()
{
var frame = document.getElementById('inlineframe'),
ref = frame.contentWindow ? frame.contentWindow.document : frame.contentDocument;
// ref is now a reference to the document of the content within the iframe
// You can now do your getElementById/getElementByTagName etc. and otherwise
// manipulate the response as you please.
console.log(ref);
}();
A working example can be found here: http://jsfiddle.net/FTudJ/
The contents of the iframe should be the submitted results of the remote page, or whatever the remote server responds with. If you're not looking to modify anything, then you don't even need the Javascript component.
The key will be the URL you specify as the source of the iframe. Now, if the remote system doesn't support GET requests for form submissions (in your example code I see a "POST" method), coupled with the fact that you have no control over it and your offsite system can't access it in any way, your only other options are:
Instead of supplying the form's submission URL directly, simply supply the form's typical access URL to the iframe. From there, use JavaScript to populate the form with the necessary values, and then submit the form within the iframe as if you were the user. From there, you can scrape the results back into JavaScript or simply display them as is.
Find a way to get your offsite server into the VPN network so that it may communicate with the remote system on your behalf. Of course, if that were easy, I guess you would have done that first!
Redirect your users to the remote site–possibly using a frameset + banner frame like Google used to do, let them do what they need to do there, and then tell them to come back when they're finished.
--
I see that you're using PHP. As long as the server that is executing the PHP has access to the VPN that has access to this remote system–all over traditional HTTP–a simple curl call from the server-side should suffice, as you can use AJAX to pass through the results to the client.
These links may be of some assistance:
http://php.net/manual/en/book.curl.php
What is cURL in PHP?
http://php.net/manual/en/curl.examples-basic.php
Post data and retrieve the response using PHP Curl?

Prevent Browsers from Cacheing certain JavaScript files

I have two types of JavaScript files. One contains static code and the other contains dynamic code which changes from session to session.
The static JavaScript file should be cached whereas the dynamic one should be cached only for that session and then reloaded In next session. The dynamic JavaScript file is generated once per session and I would like the client browser to cache it for the remainder of session.
How do I force the client browser to request a JavaScript file every session? I know that a common practice is to append a request parameter containing a version number, but one can make only so many updates to a file so that you can manually update JavaScript references. You can't really do that with sessions since there can be multiple sessions per day.
I don't see what's wrong with placing a random number at the end of the JavaScript url. For example:
http://www.example.com/myjavascript.js?r=1234
Won't necessarily stop it from cache'n, but if the number is different, the browser will load that js file again.
Could you append the session id to the JavaScript URL? Assuming you're using JSP, it would look kind of like this:
<script src="/script.js?session=<%= // code to get the session ID %>"></script>
I don't know much about JSP, so I can't help with the specifics, but that should give you a single, unique URL for the session.
Just appending a session id or a random number to the file name would solve your user experience problem, but it also clogs up all the HTTP caches with useless entries. It should be a lot easier just to set the HTTP 1.1 Cache-Control header in your response to "no-cache". If you're using Java Servlets, it's done this way:
response.setHeader("Cache-Control", "no-cache");
(If some of your traffic will come from legacy browsers, http://onjava.com/pub/a/onjava/excerpt/jebp_3/index2.html gives some other header settings to really make sure nothing gets cached.)

Cross domain javascript form filling, reverse proxy

I need a javascript form filler that can bypass the 'same origin policy' most modern browsers implement.
I made a script that opens the desired website/form in a new browser. With the handler, returned by the window.open method, I want to retrieve the inputs with theWindowHandler.document.getElementById('inputx') and fill them (access denied).
Is it possible to solve this problem by using Isapi Rewrite (official site) in IIS 6 acting like a reverse proxy?
If so, how would I configure the reverse proxy?
This is how far I got:
RewriteEngine on
RewriteLogLevel 9
LogLevel debug
RewriteRule CarChecker https://the.actualcarchecker.com/CheckCar.aspx$1 [NC,P]
The rewrite works, http://ourcompany.com/ourapplication/CarChecker, as evident in the logging. From within our companysite I can run the carchecker as if it was in our own domain. Except, the 'same origin policy' is still in force.
Update,
I stopped using Isapi Rewrite as the free version does not include a proxy component. I started to use the url rewriter from Managed Fusion.
My current working rewriterule:
RewriteRule /MySecuredSite/CarChecker https://the.actualcarchecker.com [NC,P]
Now I get the error: The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.
I think this occurs because our ssl-certificate is passed on to the carchecker site. How can I configure the reverse proxy so that the certificate of the carchecker site is passed on?
Regards,
Michel
Without knowing a few more details I decided that it might just be helpful to list some of the restrictions you face and some of the tricks you could take advantage of:
I'm not an ASP developer but I'm aware that, as you mentioned, there is some kind of viewstate variable that must be submitted along with a ASP form. I assume that this viewstate can be validated using only the form fields that are to be resubmitted. That's all that I'd expect (unless it's super complex) since the form the browser receives is all it sends back (along with values). So the point is that you'll need a valid viewstate when you submit to the aspx page, but maybe you can grab any viewstate you want from the server so long as the form fields you submit are identical.
You can write a webpage that acts just like your browser does. It can grab the aspx page (thus establishing a valid viewstate), then you can create all of the fields necessary to POST to the aspx page, including the viewstate, and do so. Whatever the results are can be returned from your webpage to the browser. Unless you have the ability to modify the other server I really don't see another option at this point, but maybe someone else can be more helpful.
If you can modify the other server then you have a few other options. One of them involves a trick for passing data between iframes. If you're using a hidden iframe to get the aspx page then you won't be able to get the result back to the parent page due to the cross-domain restriction. But since you can modify the other server (running on the.actualcarchecker.com), you can get around this. To do so just make that server provide JavaScript to submit the form asynchronously and then set the result (serialized to a string) to window.name.
Now to get access to window.name from your domain, you set the iframe's window.location to a page on your domain that will simply call a function you wrote in the JavaScript loaded in the parent window. Like window.parent.process(window.name). Since the iframe loaded a page on your domain it will have access to window.name which will not have been changed even though you changed window locations. Then the process() function in the parent window can deserialize the string, remove the hidden iframe, show the results, do whatever you want, etc.
You won't be able to populate the aspx form that's loaded in the hidden iframe unless you do a similar trick on the other domain's server. That server's JavaScript will need to read from window.name to receive the inputs to populate the form with. However, if both servers are in on the trick then you don't have to write a proxy, you can just pass data via window.name.
Which server side language are you using? Using it you can create a proxy which should easily bypass the one domain policy...
PHP
<?php
$handle = fopen("https://the.actualcarchecker.com/CheckCar.aspx", "r");
$contents = '';
while (!feof($handle)) {
$contents .= fread($handle, 8192);
}
fclose($handle);
echo $contents;
?>
I'd imagine it would be a similar process with other languages.
Why don't you use JSONP approach instead? I.e. use JavaScript to read the values entered into your form and sent it to the server-side handler via a dynamically generated <script> element (<script> and img elements can refer to resources from external domains).
var e = document.createElement("script");
e.setAttribute("type", "text/javascript");
e.setAttribute("src", "https://the.actualcarchecker.com/CheckCar.aspx?input1=value1&input2=value2");
document.getElementsByTagName('head')[0].appendChild(e);
Likely, you will not need any serious URL rewriting at all if you use this approach - just make sure that CheckCar.aspx returns valid JSON.
JQuery even has several convenience functions for this: AFAIK $.getJSON will transparently switch from XHR to dynamic script insertion method if the request is cross-domain. Also, it supports specifying callbacks. See jQuery docs and this IBM article for more info.
Will this method work for you?

Categories

Resources