same site content secure policy - redirect

Like a lot of people lattely, I have a few problems with SameSite and secure.
We have a website, where our user must be logged in to buy some stuff.
When our user want to pay, he is then redirected to the payment plateform. Once he has made the payment he is then redirected to our website.
The problem is that with browsers such as chrome he is no longer logged in,; and we can't display the order informations anymore. Many of our user did not understand and attemps to order multiple time.
From what I understood (How can I redirect after OAUTH2 with SameSite=Strict and still get my cookies?), because of the samesite policy is by default Lax, when he is being redirected to the payment interface and then back to our website, the cookies chain is broken and the cookies from our website are not send, and that is why our user is no longer connected.
I could set Samesite to none but then that would means that our website is vulnerable.
I also made a few research with content secure policy and was wondering if using CSP it was possible to set Samesite=none and with CSP to be able to prevent ?

If you don't specify the samesite flag, only Chrome/Edge will treat them as Lax be default. Setting your cookies to SameSite=none will not make them more insecure that they were before "lax by default" in Chromium or in other browsers.
Lax by default protects your users from tracking and CSRF. If you have some other CSRF mitigation in place you are probably not vulnerable when setting SameSite=none. CSP doesn't help you in this case.

Related

Without Same Origin Policy could an evil site read the CSRF token?

From wikipedia about Same Origin Policy
https://en.wikipedia.org/wiki/Same-origin_policy
The same-origin policy helps protect sites that use authenticated sessions. The following example illustrates a potential security risk that could arise without the same-origin policy. Assume that a user is visiting a banking website and doesn't log out. Then, the user goes to another site that has some malicious JavaScript code running in the background that requests data from the banking site. Because the user is still logged in on the banking site, the malicious code could do anything the user could do on the banking site. For example, it could get a list of the user's last transactions, create a new transaction, etc. This is because the browser can send and receive session cookies to the banking site based on the domain of the banking site.
This part i understood but now...
The user visiting the malicious site would expect that the site he or she is visiting has no access to the banking session cookie. While it is true that the JavaScript has no direct access to the banking session cookie ...
Because the session cookie is httpOnly flagged?
... it could still send and receive requests to the banking site with the banking site's session cookie. Because the script can essentially do the same as the user would do, even CSRF protections by the banking site would not be effective.
Same Origin Policy prohibits Cross-Origin reads. Thus, if we assume that SOP is not enforced, the malicious site could read the CSRF token from the response? Is that the reason why wikipedia is saying that even CSRF protections would not be effective?
Yes, you've understood it. Without the SOP, the malicious script would simply request whatever page has the CSRF token, read it, and then use that token to construct its unsafe requests.
So SOP and CSRF protection are both necessary to protect the user in a world where the browser sends authentication cookies with requests from foreign domains.

Is there anyway to authenticate a user with Github without redirecting them within the current page?

I am looking to allow a user to sign in with github for a website I am creating that will be API driven. However, I am running into a problem that there seems to be no way of authenticating a user and getting their email and name without redirecting them on the current page to github. I have tried to create a popup, but there is no way for me to get the necessary data from the popup, namely an api token to be used for the next calls.
The answer to the question as framed is "use a different grant flow" but your questions tell me you don't understand OAuth grant flows so you may be better served by a lecture on OAuth.
Popups and iframes are specifically designed to prevent code running outside them from fishing out data, because if you could do it so could invisible iframes in dodgy ads. Give up on that approach because in the unlikely event that you find a way, browser makers will immediately take steps to prevent your solution from working.
The behaviour you describe sounds to me like implicit grant flow.
Here's a walkthrough of the various ways OAuth2 can work.
Why so many ways?
Implicit grant is a flow that uses redirection to deliberately take control away from your code - which might be compromised or impersonated - and give it to a trusted third party, the OAuth provider: GitHub in this case. You pre-register the point to which control is returned after authentication, the point of which is the token is always given to your code.
Amnesia, popups, and what was I doing before we were so rudely interrupted?
There are flows that use popups. Usually this is the authorisation code grant flow. Popups are not suitable for mobile devices and this led to the creation of the implicit grant flow.
The usual reason for not liking redirection is the amnesia it causes. The solution is to store app state persistently prior to passing control to the OAuth provider, and to write a return-from-oauth handler that unpacks the JWT from the redirect parameter and then restores the app state you saved.
Note to self
If the user is anonymous prior to authentication serialise your state to a string and put it in a cookie or in localStorage.
If the user is not anonymous and is authenticating to elevate privilege you'll have to send any privileged data to the server and just persist a retrieval token on the browser. You must ensure that retrieval of this state requires both a valid OAuth token and a valid state token, and that it discards the state after honouring a request so that a replay attack will be conspicuous (you'll have to handle the fallout).
Having acquired a valid token you can use it to request profile information from GitHub. A very small amount may already be present in the JWT; you'll probably have the email address that served as a login, but this isn't necessarily the right one for correspondence.
GitHub OAuth documentation
It appears GitHub only supports code grant auth. That means you have to do the popup/iframe thing. Here's their doco:
https://developer.github.com/v3/oauth/
Code grant - why?
This flow doesn't give you an encoded token, it gives you a code you can redeem for an encoded token. The idea is that when the token expires you can use the code to get a refresh token without sending credentials over the wire.
Not only you have a redirection, but starting Dec. 2020, you also have:
OAuth 2.0 Device Authorization Flow now GA
GitHub Apps and OAuth Apps now feature GA support for the OAuth 2.0 Device Authorization Grant, in addition to the existing Web Application Flow.
This allows any CLI client or developer tool to authenticate using a secondary system with a browser.
GitHub CLI uses this authentication method on the login command.
Read the full documentation on Authorizing OAuth Apps and Authorizing Users for GitHub Apps for more information.
Confirmed March 2022:
Enable OAuth Device Authentication Flow for Apps
From today the OAuth Device Authorization flow feature must be manually enabled for all OAuth and GitHub Apps.
This change reduces the likelihood of Apps being used in phishing attacks against GitHub users by ensuring integrators are aware of the risks and make a conscious choice to support this form of authentication.
If you own or manage an OAuth App or GitHub App that makes use of the OAuth Device Authorization flow, you can enable it for your App via its settings page:
The OAuth Device Authorization flow API endpoints will respond with status code 400 to Apps that have not enabled this feature.
Documentation: "Device flow"

How do CSRF tokens protect from malicious GET followed by POST in another tab

I know I am missing something, but please help me understand. Consider this situation:
I have a website called goodbank.com. URL http://goodbank.com/transfer/ serves a HTML page on GET with a form to transfer money to another account. The form has a random token to prevent CSRF attack. On the server, token validity is checked on POST and the corresponding controller allows only authenticated sessions.
Let's say that in my browser, I login to goodbank.com/. In another tab, I go to robgoodbank.com. As part of the served page, it has javascript to do AJAX request to goodbank.com/transfer/ to get a valid form. It then fills in other fields in the form and does a POST. My account is cleaned out :(
How does existing protection schemes protect against such an attack?
Thanks in advance.
Unless your server allows Cross Origin Resource Sharing, the browser will reject the XMLHttpRequest. As per the link, the XMLHttpRequest sends the Origin header containing the domain from which the request originates. If the server does not respond with Access-Control-Allow-Origin containing a wildcard of that domain, the browser will reject the request. There are actually a number of Access-Control- headers to control access including allowable methods, etc.
For extra protection, your server should check the Origin if it is present and the Referer HTTP header, which will be "http://robgoodbank.com" in your example, and you can also reject the request.
These are by no means foolproof, but do provide extra layers of protection. There are mechanisms (such as extensions) to spoof the Referer, but those would have been employed by the user unless their browser has been compromised in some way. If their browser has been compromised they are in a lot more trouble...

Submitting a form to a secure url from a non-secure page

Suppose I have a form on a page at this location...
http://mydomain.com/myform.htm
And the form looks like this...
<form method="post" action="https://secure.otherdomain.com/handleform.php">
....
</form>
Assuming that there is a valid SSL cert installed on the server which receives this form submission will the contents of that form submission be encrypted?
The POST request will be transmitted over HTTPS (so encrypted if configured properly). Submitting a form from a page obtained over plain HTTP to an HTTPS page is bad practice. The initial page should also be served over HTTPS. The reason for this is that a MITM attacker could intercept the response that loads the page with the form and replace the link to point to another target.
See the first rule here (of course, not specific to login pages):
https://www.owasp.org/index.php/Transport_Layer_Protection_Cheat_Sheet#Rule_-_Use_TLS_for_All_Login_Pages_and_All_Authenticated_Pages
Rule - Use TLS for All Login Pages and All Authenticated Pages
The login page and all subsequent authenticated pages must be
exclusively accessed over TLS. The initial login page, referred to as
the "login landing page", must be served over TLS. Failure to utilize
TLS for the login landing page allows an attacker to modify the login
form action, causing the user's credentials to be posted to an
arbitrary location. Failure to utilize TLS for authenticated pages
after the login enables an attacker to view the unencrypted session ID
and compromise the user's authenticated session.
Assuming a valid SSL/TLS session can be negotiated between the server and the client, then yes. This means that the client must be willing to trust whatever certificate the server presents and that the two parties can negotiate a mutually-agreeable cipher set (what algorithms to use, etc). There are plenty of configuration options you can set to alter what is allowed, but in a "normal" implementation where you don't go messing around with requiring a specific, non-normal, algorithm, requiring client-side certificate authentication, etc, everything should work just fine and you'll have a protected session...and if it fails for some reason, you'll know as your client will receive an error about what went wrong.
Note that, in general, while you can do this, and the transmission would be encrypted, you generally should not. Having an unencrypted/protected page submit to one leaves you vulnerable to a couple types of Man in the Middle attacks. You can see the OWASP article on this, and why it's bad, here.
Yes. It will be transmitted securely.

Disabling cookies

I disabled all the cookies in my browser. And, then I got an error when I tried to login into facebook. How common is it for a user to disable all cookies ? I was trying to test my application. Is this is a valid use case ?
Many people consider cookies a privacy violation and block them by default (especially so-called "third-party" cookies typically used by advertising networks).
Having said that cookies are pretty much essential for any type of login or session control (like shopping carts) so if you need them then use them. Your users can always turn them back on if they want.
The main thing is you should at least attempt to check the user has cookies enabled when they require them and inform them that they will not be able to log in or use that particular feature.
As a general rule cookies are enabled in browsers by default. If a user has turned them off then chances are good they will know how to turn them back on (on unblock your site) when necessary.