From HTTP to HTTPS, the sooner the better? - https

If I have this page in "http://example.com/login" with GET verb:
<form action="https://example.com/login" method="post">
<input type="text" name="login"/>
<input type="password" name="pass"/>
<input type="submit" value="Login"/>
</form>
Is it a security flaw? I mean, the page is HTTP but when sending the data it uses HTTPS. I have read several times that I should require HTTPS already in the login page, but I don't clearly see why.

Yes, it's flawed. What you have is secure as far as it goes, as long as it's your login form the user is seeing.
Because your login form isn't secured, I can come along and substitute my own spoof login form and collect your users' login details, eg. via a man-in-the-middle attack. A login system is only secure if both the login form and the target page use SSL.
Also, it doesn't look secure to the user. Users look for the padlock symbol on the login form, and yours doesn't have one.

Yes, it is a security flaw.
Since the form is served over HTTP, it is subject to being edited along the way. This edit could be, for example, the additional of JavaScript that sends the credentials to a server that the attacker controls as well as letting the browser log in normally.

Related

Why need for redirect uri when requesting OAuth access token from Google?

I am trying to request an access token from Google do I can access a Google Drive account, to upload files.
I can make a an Auth request ...
<form method="POST" action="https://accounts.google.com/o/oauth2/auth">
<input type="hidden" name="scope" value="[YOUR SCOPE]"/>
<input type="hidden" name="client_id" value="[YOUR CLIENT ID]"/>
<input type="hidden" name="response_type" value="code"/>
<input type="hidden" name="redirect_uri" value="[YOUR RETURN URL]"/>
<input type="hidden" name="access_type" value="offline"/>
<input type="submit"/>
</form>
Why do I need the redirect_uri if I am making an HTTP request to obtain the access token. Wouldn't the token be returned within the response body?
My app does not involve any user interaction so I am not sure why a redirect is even necessary. I don't wish to use an SDK or library, rather I would just like to use HTTP via Postman.
My app does not involve any user interaction
Oauth2 does require user interaction to authenticate to a users account then your going to have to request access from them. A consent screen is displayed and the code is returned to the redirect uri
back to the basics of form submit ( without javascript), the form data will be sent to the uri you set in the action and the page will be redirected to what the server set it to, or page gets "reloaded" with a page that shows the response od the server.
I never tried Google OAuth2, but in general for this case, usually if your form submit is successful, it will redirect to your redirect_uri with the token appended on the uri as hash.
just realized u are using code grant type. so the flow is after this form submit, it will get redirected to Google IDM to authenticate and accpt consent, then redirect to redirect_uri with the auth code appended. then u can get the token by requesting it from the token endpoint with the code you obtained.

Laravel - Remember me not working as expected

Using Laravel 5.5, and Laravel's built-in authentication system.
Confused about the Remember me option, this is my remember view
<div class="col-xs-6">
<div class="checkbox checkbox-primary" style="margin: 0;">
<input id="checkbox-remember" type="checkbox" name="remember" {{ old('remember') ? 'checked' : '' }}>
<label for="checkbox-remember">Remember me</label>
</div>
</div>
When checked, it does add the remember_token token in the User database, so that part works. But it doesn't seem to 'remember' anything? All users whether they have a remember_me token or not can access the website straight away if they close the website/open it again. All users need to re-enter their email/password if they sign out and the remember-me box is not checked whether they have the remember_me token or not.
Tried both the file and the cookie session driver.
Struggling to see what exactly does it remember?
The remember me functionality from Laravel provides an automatic login for users who signed in with the remember me checkbox checked. This way users who closed their browser or killed their session don't have to login again.
Contrary to other websites (or some browsers, for that matter) who remember the credentials and put them in the login for you, Laravel doesn't do that.
As Laravel states in it's documentation:
If you would like to provide "remember me" functionality in your application, you may pass a boolean value as the second argument to the attempt method, which will keep the user authenticated indefinitely, or until they manually logout.

Cross site forgery on AJAX service

I'm a little confused as to how to prevent cross site forgeries. Still. I know there is a wealth of information out there, but I'm confused.
In Steven Anderson's post he describes a form like this:
<body onload="document.getElementById('fm1').submit()">
<form id="fm1" action="http://yoursite/UserProfile/SubmitUpdate" method="post">
<input name="email" value="hacker#somewhere.evil" />
<input name="hobby" value="Defacing websites" />
</form>
</body>
On someone else's site.
The solution given is a "anti-forgery" token, generated by the server, that is POST-ed back to with any requests in a hidden form. That's cool, but what is to stop the hacker just downloading the form page, extracting the token and POSTing it?
My application for this is: On the sign-up for to my website I'd like a AJAX function that sends the currently entered Username to the server which should respond "True/False" if it is available or not. This happens onKey so the user can pick a username that has not been used already. The Submit button will enable when all the conditions for "new user" are met.
Clearly this is an opportunity for a hacker to use the service to "test" lots of usernames to see if they available - I know it's not exactly internet-banking level sort of risk, but I'd still like to service only requests from my application, not a hacker.
Any ideas how about these queries?
UPDATE:
So in my scenario. I generate a Token (say some hashed value of the client's IP address) and the service expects to receive this back if it is give the information about whether the username is available or not.
-- The problem remains, someone off domain simply calls the service e.g. /generateToken This looks at the client's IP... could be a hacker who knows.
Returns
{ token: 4uru32br }
Which is then submitted to the /isUsernameAvailable?token=4uru32br&partialUsername=usernam
Where does that get me?
what is to stop the hacker just downloading the form page, extracting the token and POSTing it?
The same-origin policy, that's what.
I'd like a AJAX function that sends the currently entered Username to the server which should respond "True/False" if it is available or not.
That's a user-enumeration vulnerability right there.
Any ideas how about these queries?
Here's your new process:
Use email addresses for usernames.
Use CAPTCHA to prevent automation on registration forms.
Email username does not exist:
Show "success" message. Send email to address with one-time link. Register user after returns to your site with that link.
Email username does exist:
Show "success" message. Send email to that address with message saying "someone is trying to create an account with this address but it already exists".
You're mixing up CSRF and user enumeration.
The solution given is a "anti-forgery" token, generated by the server,
that is POST-ed back to with any requests in a hidden form. That's
cool, but what is to stop the hacker just downloading the form page,
extracting the token and POSTing it?
Say Bob is a normal user on your site.
Chuck is an evil attacker.
Bob goes on your site and submits the comments form (in your code example). If there is CSRF protection, a token is included in this form too:
<input type="hidden" name="csrf_token" value="zxcvbnnmm1235152" />
Bob's session has token zxcvbnnmm1235152 stored for him server-side.
Chuck also has a login to your site because he has registered.
However, when he goes to this page he gets this token instead:
<input type="hidden" name="csrf_token" value="lklkljlk898977" />
If Chuck downloads the page, gets Bob somehow (e.g. sends him an email) to access this page on Chuck's server, because the csrf_token doesn't match Bob's, Chuck can't post the message as Bob.
Bob can continue just fine, because the token in the form matches the one associated with his session.
CSRF is about stopping Chuck from submitting stuff as Bob, using Bob's browsing session.
My application for this is: On the sign-up for to my website I'd like
a AJAX function that sends the currently entered Username to the
server which should respond "True/False" if it is available or not.
This happens onKey so the user can pick a username that has not been
used already. The Submit button will enable when all the conditions
for "new user" are met.
Clearly this is an opportunity for a hacker to use the service to
"test" lots of usernames to see if they available - I know it's not
exactly internet-banking level sort of risk, but I'd still like to
service only requests from my application, not a hacker.
Yes, this is your user enumeration vulnerability.
Have username as email, and follow this answer on how to make this secure.
The anti-forgery token is not a random code. Nor a reused token for several requests.
Rather, the server couples the token with the callers ip-address or session, for example by encrypting the ip+salt with a server-key.
Thus, if the attacker tries to download the token from your site, it won't be usable by the real client

Client, Auth Server and Logout

So, i have a standalone OAuth2 auth server and client app (web-based), all using Spring OAuth2.
I have a login form host on the Auth server with redirection etc from the client app using Spring setup (via the login form).
All good so far.
I added a logout setup on the client:
.and()
.logout()
.addLogoutHandler(oauth2LogoutHandler())
.logoutSuccessUrl("/")
.clearAuthentication(true)
.deleteCookies("JSESSIONID")
.invalidateHttpSession(true)
.permitAll()
That all 'seems' to be fine.
However, if i then hit the 'login' link on my client, when it redirects to the Authorisation app i dont get the login screen, but simply the redirection handshake occurs and i'm back in the client app.
So, the question is, what is it need to 'clear' in the Auth server when i logout on the client app? Somehow session info is persisting on the auth app but i cant find how that session is being picked up when i hit login? is there a clean way to propagate a 'logout' to the Auth Server?
Many Thanks
Martin
https://spring.io/blog/2015/02/03/sso-with-oauth2-angular-js-and-spring-security-part-v#the-logout-experience describes essentially the same problem for a notoriously tricky problem.
The Logout Experience
If you click on the “logout” link you will see that the home page changes (the greeting is no longer displayed) so the user is no longer authenticated with the UI server. Click back on “login” though and you actually don’t need to go back through the authentication and approval cycle in the authorization server (because you haven’t logged out of that). Opinions will be divided as to whether that is a desirable user experience, and it’s a notoriously tricky problem (Single Sign Out: Science Direct article and Shibboleth docs). The ideal user experience might not be technically feasible, and you also have to be suspicious sometimes that users really want what they say they want. “I want ‘logout’ to log me out” sounds simple enough, but the obvious response is, “Logged out of what? Do you want to be logged out of all the systems controlled by this SSO server, or just the one that you clicked the ‘logout’ link in?” We don’t have room to discuss this topic more broadly here but it does deserve more attention. If you are interested then there is some discussion of the principles and some (fairly unappetising) ideas about implementations in the Open ID Connect specification.
Here's a PR I submitted on github for an Spring-based OpenID Connect (an extention of OAuth2) project to implement an "End Session Endpoint" on the Authorization Server: https://github.com/mitreid-connect/OpenID-Connect-Java-Spring-Server/pull/972. It implements part of the https://openid.net/specs/openid-connect-session-1_0.html#RPLogout spec for RP-initiated (or client-initiated) logout.
I don't think Spring has a built-in mechanism for this. There are other specifications, other than the one I partially implemented, for logout. Whichever you chose, it's probably a good idea to follow a documented spec.
You should enable the logout extending the WebSecurityConfigurerAdapter and create a logout page that send a post to /logout in the Authorization App
Logout page: (resources/templates/logout.ftl)
<html>
<head>
<title>Logout Page</title>
</head>
<body>
<form role="form" action="logout" method="post">
Logout
<input type="hidden" id="csrf_token" name="${_csrf.parameterName}" value="${_csrf.token}"/>
<input type="hidden" id="redirect" name="redirect" value="${RequestParameters['redirect']!'/login'}"/>
<button type="submit">Logout</button>
</form>
</html>
The redirect input hidden will redirect to the client application after logout

How to protect cross site form submit

Does anyone know how to protect cross site form submit? For example if I have register page and user have to enter there own email and password and I do not want anyone submit email and password value from other site to myweb site.
Store secret randomly generated key inside users session. When user will open page with form put inside form hidden input with that value. Check if both match while validating received data after form is submitted.
If you mean you don't want people to be able to submit data in a form hosting on another website to your server one way of preventing that would be to check the Referrer HTTP header however this is not going to work all of the time as it relies on data being sent by the browser and is easily faked.
You would also end up causing hassle to those who turn off HTTP Referrer sending.
Another way to get this to work might be sending an <input type="hidden" value="dsahdbashdbhas[keyboard mash]" /> which will have a value you generate (when the user requests the page) based on their IP address. Then when you process the form you can check for this value and if it isn't correct you can drop the request.
If this is to prevent automated form filling then you should use CAPTCHA
In the web security world, this is a vulnerability known as Cross-site Request Forgery (CSRF). You should be sure to read the Cross-Site Request Forgery Prevention Cheat-Sheet --and other pages-- at OWASP

Resources