226

Say I have a website called a.com, and when a specific page of this site is loaded, say page link, I like to set a cookie for another site called b.com, then redirect the user to b.com.

I mean, on load of a.com/link I want to set a cookie for b.com and redirect user to b.com.

I tested it, and browser actually received the cookie from a.com/link, but it didn't send that cookie on the redirection request to b.com. Is it normal?

Can we set cookies for other domains?

Shrabanee
  • 2,706
  • 1
  • 18
  • 30
Rasoul Zabihi
  • 2,575
  • 2
  • 18
  • 10

11 Answers11

165

You cannot set cookies for another domain. Allowing this would present an enormous security flaw.

You need to get b.com to set the cookie. If a.com redirect the user to b.com/setcookie.php?c=value

The setcookie script could contain the following to set the cookie and redirect to the correct page on b.com

<?php
    setcookie('a', $_GET['c']);
    header("Location: b.com/landingpage.php");
?>
qbert220
  • 11,220
  • 4
  • 31
  • 31
  • Yet a.com can insert the same data in the form of a header when redirecting to b.com, can it not? Why does this not present a security flaw? – Coder Feb 21 '13 at 02:02
  • 3
    @Coder, the setcookie fuction will result in a cookie header being sent to the browser from b.com. a.com is not able to send a cookie header from b.com. – qbert220 Feb 26 '13 at 13:23
  • yes this is very insecure, but it does work. If the OP owns a.com and b.com and the cookie is pretty trivial, then maybe it is fine. – rocketsarefast Jul 12 '16 at 14:42
  • 7
    it'd better notice in the answer that this is insecure though it works. – Roy Ling Jun 03 '17 at 10:39
  • 3
    how can you say this however youtube is reading cookies created by gmail in order to show their account on youtube? – TAHA SULTAN TEMURI Jul 08 '18 at 08:46
  • Correct me if I misunderstood the question, but it totally is possible. If b.com has the correct CORS Headers to accept cookies from a.com, then can a.com place cookies on b.com domain. – Advena Apr 16 '20 at 22:30
  • 3
    @TAHA Your google account data isn't stored in a cookie. The cookie contains a key to a DB row on Google's servers. YouTube uses oAuth to retrieve the cookie's value in a secure fashion and then uses the key to retrieve your data from the DB. – user10398534 Apr 22 '20 at 08:21
  • @user10398534 thank you for giving me information , I will study this case later. – TAHA SULTAN TEMURI Apr 23 '20 at 10:47
  • 1
    Can anyone tell me why this is insecure? I see no security flaws, if the resource server is protected against unauthorized attacks – Kaushik Ramachandran Dec 01 '20 at 18:34
  • 3
    If this method is insecure, what is the preferred method? – lowcrawler May 18 '21 at 23:16
  • 2
    @KaushikRamachandran; It's insecure as the parameter 'c' could be abused to include new HTTP Headers, resulting in HTTP Header injection (https://portswigger.net/web-security/host-header). Its just difficult to tell from this snippet. – Dominic Zukiewicz Sep 12 '22 at 09:00
  • 1
    @lowcrawler: Review the code in 'setcookie' to ensure the value 'c' is sanitised appropriately, to not result in HTTP Header Injection. – Dominic Zukiewicz Sep 12 '22 at 09:02
58

Similar to the top answer, but instead of redirecting to the page and back again which will cause a bad user experience you can set an image on domain A.

<img src="http://www.example.com/cookie.php?val=123" style="display:none;">

And then on domain B that is example.com in cookie.php you'll have the following code:

<?php
    setcookie('a', $_GET['val']);
?>

Hattip to Subin

Jonathan
  • 8,453
  • 9
  • 51
  • 74
  • 2
    nice hack... :) – yakya Feb 13 '17 at 20:50
  • 37
    Beware that is probably a Very Bad Idea. You're circumventing the very intentional cookie protections by basically letting anyone send a crafted GET request to set that cookie to any value they want. I don't know what you then DO with that cookie, but I hope it doesn't involve a bank balance. – Scott Stafford Aug 29 '17 at 14:43
  • 1
    I can assure you that it didn't involve a bank balance. But good point :) – Jonathan Aug 29 '17 at 14:46
  • 3
    If like in this case everyone can call this domain with their own parameter you can add security by adding another parameter. Create a hash with the data and an additional salt and pass it as parameter. In your cookie.php simply verify the data in $_GET['val'], by recreating the token and comparing them. – Seba M Mar 11 '19 at 07:32
  • 2
    If you're sending the GET this way, you can as well use AJAX. – user10398534 Apr 22 '20 at 08:22
  • @SebaM Beware of creating your own security protocols. If this is standard, send a link to how to do it the right way. – thebiggestlebowski Oct 14 '20 at 15:03
  • @ScottStafford How would this be a security issue as long as the cookie is intended for storing in browser? It is already possible to alter a cookie using developer tools and extensions. Do you mean the security issue associated with "GET" call to save cookies https://security.stackexchange.com/questions/238975/is-it-safer-to-send-cookies-in-headers-than-the-url ? – BEWARB Feb 18 '23 at 20:29
20

Probaly you can use Iframe for this. Facebook probably uses this technique. You can read more on this here. Stackoverflow uses similar technique, but with HTML5 local storage, more on this on their blog

Community
  • 1
  • 1
Ondrej Bozek
  • 10,987
  • 7
  • 54
  • 70
  • 1
    iframe worked perfectly for my solution, simply include the values in the url like a normal get request and respond from server with cookie values – Joel Davis Aug 25 '14 at 08:02
  • Be advised, you must have your Access-Control-Allow-Origin configured properly for this to work. – user10398534 Apr 22 '20 at 08:24
12

You can't, at least not directly. That would be a nasty security risk.

While you can specify a Domain attribute, the specification says "The user agent will reject cookies unless the Domain attribute specifies a scope for the cookie that would include the origin server."

Since the origin server is a.com and that does not include b.com, it can't be set.

You would need to get b.com to set the cookie instead. You could do this via (for example) HTTP redirects to b.com and back.

Community
  • 1
  • 1
Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
  • I know this is an old response, but why would this be a security risk? You can set cookies in your console or in a extention? Why would it matter if you can set a cookie for a different domain? – Timberman Jan 02 '20 at 14:45
  • 3
    @Timberman — The question is about JavaScript running on a website **not** in the developer tools and **not** in an explicitly installed extension. It would be a security risk because anyone visiting `evil-hack.com` could have a cookie set for `their-favourite-website.com` that would change their preferences on that website. – Quentin Jan 02 '20 at 14:49
  • I understand that, but how is it a security risk? I'm pretty sure it does not have anything to do security wise? – Timberman Jan 02 '20 at 15:18
  • @Timberman — If you can't see a problem with an attacker's site changing your preferences for a completely different site then I don't know how to explain it any more clearly. – Quentin Jan 02 '20 at 15:18
  • I see the problem, but I don't see how it is a security risk. I do agree with you that javascript should not be able to set a cookie for a different domain, but how is it a security issue if it was able to? – Timberman Jan 02 '20 at 15:21
  • @Timberman, one of the 3 main properties of Information Security (https://www.nccoe.nist.gov/publication/1800-25/VolA/index.html) is Integrity. The ability to change the content/configuration of a site from another site without the user's consent could be considered a security issue on the grounds of an attack to the Integrity. Everything boils down to the fact that (as per Quentin's example) `evil-hack.com` would be injecting information on your requests to `their-favourite-website.com` without you knowing it. The risk and impact evaluation is a separate matter. – lexotero Mar 21 '22 at 14:05
  • @Timberman https://security.stackexchange.com/questions/238975/is-it-safer-to-send-cookies-in-headers-than-the-url – BEWARB Feb 18 '23 at 20:16
9

In case you have a.my-company.com and b.my-company.com instead of just a.com and b.com you can issue a cookie for .my-company.com domain - it will be accepted and sent to both of the domains.

stop-cran
  • 4,229
  • 2
  • 30
  • 47
  • 1
    is it possible to create a cookie in a.my-company.com for b.my-company.com? – mahesh kajale Nov 08 '17 at 13:16
  • 2
    Unless my-company.com is in the [Public Suffix Black-hole List](https://github.com/publicsuffix) in which case the browser will silently ignore all attempts to set the cookie! :'-( – Michael Jul 22 '18 at 08:00
  • you are definitely right. but if things happen. then we have to find solutions. this is not a solution of this question. don't give an advice just solution – horoyoi o Nov 06 '20 at 02:16
6

see RFC6265:

The user agent will reject cookies unless the Domain attribute specifies a scope for the cookie that would include the origin server. For example, the user agent will accept a cookie with a Domain attribute of "example.com" or of "foo.example.com" from foo.example.com, but the user agent will not accept a cookie with a Domain attribute of "bar.example.com" or of "baz.foo.example.com".

NOTE: For security reasons, many user agents are configured to reject Domain attributes that correspond to "public suffixes". For example, some user agents will reject Domain attributes of "com" or "co.uk". (See Section 5.3 for more information.)

But the above mentioned workaround with image/iframe works, though it's not recommended due to its insecurity.

Community
  • 1
  • 1
Roy Ling
  • 1,592
  • 1
  • 14
  • 31
6

Setting cookies for another domain is not possible.

If you want to pass data to another domain, you can encode this into the url.

a.com  ->  b.com/redirect?info=some+info (and set cookie) -> b.com/other+page
Patrik
  • 2,695
  • 1
  • 21
  • 36
  • 7
    setting a session cookie from a url is a security risk. urls are usually logged and would allow an attacker to steal a users session – Dane Macaulay Jul 01 '16 at 14:54
3

You can't, but... If you own both pages then...

1) You can send the data via query params (http://siteB.com/?key=value)

2) You can create an iframe of Site B inside site A and you can send post messages from one place to the other. As Site B is the owner of site B cookies it will be able to set whatever value you need by processing the correct post message. (You should prevent other unwanted senders to send messages to you! that is up to you and the mechanism you decide to use to prevent that from happening)

cSn
  • 2,796
  • 3
  • 23
  • 29
2

Send a POST request from A. Post requests are on the serverside only and can't be accessed by the client.

You can send a POST request from a.com to b.com using CURL (recommended, serverside) or a hidden method="POST" form (clientside). If you go for the latter, you might want to obfuscate your JavaScript so that the user won't be able to understand the algorithm and interfere with it.

Make a gateway on b.com to set cookies:

<?php
    if (isset($_POST['data']) {
        setcookie('a', $_POST['data']);
        header("Location: b.com/landingpage");
    }
?>

If you want to bring security a step further, implement a function on both sides (a.com and b.com) to encrypt (on a.com) and decrypt (on b.com) data using a cryptographic cypher.

If you're trying to do something that must be absolutely secure (e.g. transfer a login session) try oAuth or take some inspiration from https://api.cloudianos.com/docs#v2/auth

user10398534
  • 145
  • 14
2

Here is what I've used. Note, this cookie is passed in the open (http) and is therefore insecure. I don't use it for anything which requires security.

  1. Site A generates a token and passes as a URL parameter to site B.
  2. Site B takes the token and sets it as a session cookie.

You could probably add encryption/signatures to make this secure. Do your research on how to do that correctly.

thebiggestlebowski
  • 2,610
  • 1
  • 33
  • 30
  • Yes, I was considering to do just this but passing tokens in url is said to be unsafe, since they bypass ssl and they are stored in logs and the browser history. – Barney Szabolcs Nov 06 '20 at 20:25
  • As I commented, this can be made secure. If site A and site B share an encryption secret, then a third party cannot read it. There's more you'd need to do than simply encrypt. You'd probably need to include a nonce to prevent various MITM attacks. This can be secure, but you'd need to do more homework. After all, https is built on top of http. – thebiggestlebowski Nov 07 '20 at 15:54
  • Makes sense. So you do some ajax handshaking first and then you pass the now secured url in the open. – Barney Szabolcs Nov 08 '20 at 11:55
  • If A -> B call is https, then network call is secure over the wire as the URL is encrypted. You can further protect the data by encrypting it. A and B need to share an encryption key. A encrypts the URL token. It's logged encrypted in the browser, which means no one can read it because deencryption key is on the servers, not the browser. Ideally, you'd pass the encrypted info as an http header, so that it's not logged or in the history. Read up on generating oauth tokens for ideas on how to protect further (digital signature and hash to detect tampering), nonce to prevent MITM, etc. – thebiggestlebowski Nov 19 '20 at 19:22
  • I see, it makes sense, thanks. Btw I love your name on Stackoverflow:) Big Lebowski is a favourite movie of mine! – Barney Szabolcs Dec 01 '20 at 12:43
  • 1
    He is a favorite movie character of mine as well. Glad you abide! – thebiggestlebowski Dec 03 '21 at 19:57
0

In this link, we will find the solution Link.

setcookie("TestCookie", "", time() - 3600, "/~rasmus/", "b.com", 1);
Hariharan AR
  • 1,386
  • 11
  • 20
  • 3
    That won't work. See [the specification](https://tools.ietf.org/html/rfc6265#section-4.1.2.3): "The user agent will reject cookies unless the Domain attribute specifies a scope for the cookie that would include the origin server." – Quentin Jan 02 '20 at 14:52