SameSite cookies, frames, sub domains and redirections - google-chrome

The SameSite concept for Cookies is definitely a hard one to grasp...
In preparation for Chrome 80's changes, I'm trying to measure the impact of the absence of SameSite attribute on my cookies. I have the following configuration:
User initially accesses main.mysite.com
main.mysite.com sets SomeCookie (Set-Cookie: SomeCookie=value; path=/; secure; httponly) and redirects to auth.mysite.com
User authenticates on auth.mysite.com and is redirected back to main.mysite.com (POST request)
Because redirections between main.mysite.com and auth.mysite.com are considered as same site and because the absence of SameSite attribute is treated as SameSite=Lax by Chrome 80, this works just fine.
However, when main.mysite.com is embedded in a frame on a page hosted on another site (say othersite.com), SomeCookie is not sent back to main.mysite.com at step 3:
Is this normal and why?

The answer above is just incorrect... Let me clear up some confusions.
1. When are 2 sites the "same site" for the purposes of SameSite?
Regardless of the Domain attribute of a cookie, two sites are considered the same when their eTLD+1 (aka registrable domain) are the same. See my answer here for a more detailed explanation.
So in this case, assuming the eTLD is ".com", we would consider auth.mysite.com and main.mysite.com to be the same site because the eTLD+1 is mysite.com for both of them. On the other hand, anything.mysite.com and othersite.com are always cross-site. This is true whether it is a top-level navigation or a subresource request (like an image or a document in an iframe).
2. What does the Domain attribute mean?
If a cookie is set with Set-Cookie: cookiename=cookievalue; Domain=mysite.com, then the cookie will be sent on requests to any domain matching *.mysite.com (i.e. all subdomains).
This is a way to adjust the scope of a cookie. For example, you could use Domain=mysite.com for a global cookie that all of your domains care about, and Domain=corp.mysite.com for a cookie that all of your company's internal domains care about (but not your external-facing domains, for example).
The default (for cookies that don't explicitly set a Domain attribute) is that cookies are sent only to the domain that set the cookie. (No subdomains.)
You cannot set a Domain attribute that does not match the URL of the request.
(Also, there is no such thing as an "origin" attribute of a cookie.)
3. So what does Domain have to do with SameSite?
Nothing. They are independent cookie attributes. Domain doesn't care about the same-site/cross-site context, and SameSite doesn't care about domain/subdomain scope of the cookie.
4. When mysite.com is embedded in an iframe on othersite.com, why are default-Lax cookies not sent?
This is considered a cross-site context, because the site in the user's URL bar is othersite.com whereas the request is made to mysite.com, and these have two different eTLD+1's.
Because it's in an iframe, this is not a top-level navigation, so all cross-site requests will exclude SameSite cookies.
If it were a top-level navigation (user clicks on a link that takes them from othersite.com to mysite.com), then the request method would matter. In the vast majority of cases this would be a GET request, so a cookie in Lax mode would be sent.
Hope this helps! You can refer to the latest version of the spec for more details.

First of all, I'm assuming that the domain attribute of the cookie is set as auth.mysite.com and not as .mysite.com. If domain attribute of the cookie is auth.mysite.com, then auth.mysite.com and main.mysite.com are not considered as SameSite.
You need to set cookie domain property to .mysite.com so that browser can see the shared origin between the two sites and consider them as same site.
My response to your question: Yes, it is normal that SomeCookie is not sent back to main.mysite.com, when you are using iframes, for the following reasons:
In the absence of sameSite attribute, the value of the attribute is treated as Lax
SameSite=Lax is almost exactly the same as SameSite=Strict, except the fact that SameSite=Lax also allows sending cookie along 'Top-level navigations'. Top-level navigation is the type of navigation when the value inside the URL bar changes. iframe context is not interpreted as a top-level navigation.
If you want make your cookies available to iframe context, you can do two things:
Set sameSite attribute value to none and at the same time, set secure attribute value to true In this way, you explicitly tell the browser your intention ( which is cross site authentication ).
If you set the domain attribute of cookie to .mysite.com, then you can even work with SameSite=Strict, i.e. they will be interpreted as the same site so no extra caution will be required.

Related

What's the use of Content-Type header when the response is an attachment?

If the response header contains Content-Disposition: attachment; filename=image.gif, then the data will automatically be saved by the browser. Does passing Content-Type header make sense in such cases?
Yes it does make sense if you know the what the appropriate Content-Type header is, but NO it is not explicitly required.
RFC6266 Use of the Content-Disposition Header Field in HTTP
According to the original RFC 2616, the disposition type "attachment" only applies to content of type "application/octet-stream". But this restriction has been removed, because recipients in practice do not always check the content type, and it also discourages properly declaring the media type.
So traditionally, we used to have to always specify Content-Type:application/octet-stream to force a download, over time clients evolved and started ignoring it altogether if there was a disposition header header.
Content-Type tells the browser how to interpret the response, but Content-Disposition: attachment tells the browser to treat the response as a file, rather than trying to render it.
But not ALL clients are web browsers, and not all web browsers are equal. By providing the Content-Type as well then you are providing additional information that the client context can use if they choose to, or it will act as a default if for some reason the client does not understand or respect the disposition header, or its value.
By specifying the Content-Type many browsers will use this information to determine the file type restriction to apply on the Save As dialog, which is especially useful if you are NOT also specifying the file name.
Some modern web clients (and extensions for them) will inspect the Content-Type and choose to deliberately pass the content to application or extension that is registered for that type instead of always saving directly to file, even if the Content-Disposition is an attachment. You may have experienced this with PDF viewers.
There are also many older mobile web clients and mini-web browsers embedded within mobile apps that are known to not support Content-Disposition or they deliberately bypass it, instead forcing the content to be rendered directly, so by providing Content-Type when you can then you know that you are providing the most compatible output that you reasonably could.
There is a similar discussion on SO, but not directly a duplicate as this question asks why we might include it Content-Type knowing that it is not likely to be used.
Do I need Content-Type: application/octet-stream for file download?

Fix Not Working: A cookie associated with a cross-site resource was set without the `SameSite` attribute

I maintain an old ASP site for my company.
We have two different domains, A and B. Domain B appears in an iFrame, and we've been getting the SameSite warning.
The solution seems to involve adding "SameSite=None; Secure" to the header.
I added those values, and they show up in Chrome dev tools:
Despite the change:
The warning still shows up.
When enabled, the SameSite experimental features still block the cookie on the host site.
Anyone know what I might be doing wrong here?
What you have showing there is two cookies, one with the session id, and another whose name is SameSite. Neither of these have any SameSite attribute (hence the blank space under the SameSite column).
You're not supposed to set a separate cookie for SameSite=None. SameSite is a cookie attribute, which is meant to be attached to the cookie it refers to.
The way you use it is like this:
Set-Cookie: sessionid=12345; SameSite=None; Secure. Note that this is a single Set-Cookie header. If you use two separate Set-Cookie lines, the browser will interpret it as two separate cookies, which is not what you want.

Cookies without "SameSite" attribute are sent on different sub domains

So I've read about Chrome 80's cookies defaulting to SameSite=Lax and like the rest of you, I'm now trying to mesure the impact this will have on my site.
The site I'm running is split on several sub-domains and each of them uses their own cookie. It looks like this:
first-site.domain.com uses Cookie1 (path=/; secure; httponly)
second-site.domain.com uses Cookie2 (path=/; secure; httponly)
Since these cookies do not specify the SameSite attribute, they are supposed to be treated as Lax on Chrome 80 and therefore should be limited to same-site requests (unless it's a top level navigation).
Then, according to SameSite cookies explained:
If the user is on your-project.github.io and requests an image from
my-project.github.io that's a cross-site request.
So when I enabled the “SameSite by default cookies” and “Cookies without SameSite must be secure” flags, I was surprised to observe that when first-site.domain.com embeds second-site.domain.com in a frame, Cookie2 was still being sent to second-site.domain.com, which seems contradictory.
Surely I must have misunderstood something, but at the moment, I'm still puzzled.
Note: I've verified that when I embed second-site.domain.com in a frame on anotherdomain.com, the cookies are not sent by the browser (as expected).
If "domain.com" is on the public suffix list, then subdomain1.domain.com and subdomain2.domain.com are considered different sites. Otherwise, they are considered the same site.
The relevant notion of "site" when it comes to SameSite cookies is the eTLD+1 (effective Top Level Domain + 1 label). An effective Top Level Domain is something like .com or .co.uk or .github.io. All the eTLD's are listed on the public suffix list.
An eTLD+1 is the effective Top Level Domain plus the 1 label immediately to its left. The eTLD+1 is also called the "registrable domain". The intuition is that two different eTLD+1's are controlled by different entities, and everything that is a subdomain of the same eTLD+1 is controlled by the same entity. For example, mysite.github.io is a different eTLD+1 than yoursite.github.io, because I cannot modify your site, and you can't modify mine. On the other hand, the same company owns both subdomain1.domain.com and subdomain2.domain.com and modify both sites.
If the eTLD+1's are the same for two domain names, they are considered the same site for the purposes of SameSite cookies.

Why does Google Chrome not recognize my SameSite cookie?

I'm trying to explore how Google Chrome handles SameSite cookies. So by using the console (ctrl+Shift+J), I added an aditional key-value pair for the cookie of a certain website I have an account on. I inputted the following code:
document.cookie="SameSite=strict"
I checked the remaining cookie and all original key-value pairs are still there, along with the newly added "SameSite=strict" pair.
Now, the problem is that Chrome doesn't act like it is supposed to according to the specification of the SameSite cookie. For example: when I go to wikipedia.org and click on a link that directs me to the website of the cookie, I'm logged in. Normally I would not be logged in, because Chrome isn't supposed to send along the cookie due to the "SameSite=strict" pair.
Am I overlooking something?
SameSite is not a cookie value. It's a cookie flag, like httpOnly and secure. So you cannot set it like document.cookie="SameSite=strict", because that sets a value.
Try with
document.cookie="mycookie=myvalue;SameSite=strict"
You can then observe in Chrome DevTools on the Application tab under Cookies that your cookie is in fact set as SameSite=strict, as opposed to just a plain cookie.

How to fill a web form inputs using delphi XE3?

I need to know how to fill an web form using Delphi XE3? I have a web form with user name and password, so how to fill it programmatically?
The page is http://batelco.com/portal see only two inputs user name and pass so how to fill and pass them ?
Using Internet Direct (Indy) HTTP client class, you can submit form values to the server using HTTP POST.
The Indy HTTP client will also receive and store cookies which the server sends with its response, if an instance of the TIdCookieManager class has been assigned to the IdHTTP client component.
HTTP cookies are required by many secure web applications when the client makes further HTTP requests to other secured URL on the server. The Indy HTTP client then will send the cookies with the request (if a TIdCookieManager has been assigned to the IdHTTP client component).
So you could send a login POST request on the login URL, providing needed authentication information, and then send a GET request to the download statistics URL to retrieve its HTML.
Regarding your specific login form, which uses ASP, here is a question about programmatically sending POST requests: HowTo deal with cryptic hidden values for ASP Net (__VIEWSTATE)
This article shows how to get and set properties of named elements.
You should get and set value properties. What ID's would form elements have depends upon your page.
Check if Element with ID has a value
This article while asked "how to read" also describes both how to get values and how to set them. Afterall if you can do A := B (read value), then you probably can also do B := A (set value).
read content in webbrowser input field
Now, that the page URL is given in the question we can click on the right top corner login-form elements in WWW browser with right button, and choose "Inspect element" to see its sources. Or, if browser is not modern and does not have Inspect command on menu, we can use another commend, like View page source and find form in the sources of the whole page. For example one of those elements is
<input name="txtUsername" type="text" maxlength="15"
id="txtUsername" tabindex="1" class="inpu-field" onfocus="txtfocus();"
onblur="txtblur();" style="color: gray; background-image: none;">
Thus we know know the ID of 1st element of form, whose "value" attribute we need to get(read) or set(write).
Links above show how to do it, given the known ID.
BTW, you given your page wrong, the real page is https://www.e-services.com.bh/Eservices/login_batelco.aspx
What about your original page, it just does not work with MSIE6 that is TWebBrowser in default mode - for compatibility with all the written applications using Microsoft ActiveX component. See http://imgur.com/ad4wbOI
If can use Google Chrome instead of TWebBrowser.
Or you can reach the ActiveX interface as one of TWebBrowser properties, and acquire new interface and turn off MSIE6-compatibility http://msdn.microsoft.com/en-us/library/aa752510.aspx
However, "how to make this page render in twebbrowser" is another, new question, not the question you asked here.
Actually, the only reason why i do not vote for closing this question as duplicate, is because none of articles above have "set" or "write" or "fill" in their title, so finding them was a bit harder than trivial.
But if the page is not mutating on load and does not have some one-time protection like CAPTCHA or unique form hash-codes, then you can post all the values with single HTTP request without even loading the form.