AJAX login redirecting to returned URL (security) - ajax

I'm working on AJAX login form. On submit it sends login data to back-end. If there is a problem with login, appropriate response is returned. When login data valid, back-end creates a session for user and sends back a URL where user should be redirected. I want to return URL, because it changes depending on multiple user settings (language, personal/business, etc.).
Am I overlooking any security issues with this approach? Is it possible for attacker to redirect user to malicious website when browser trusts URL returned from AJAX call?

No, that's a pretty standard method for handling login via an asynchronous handler (assuming that you're doing this over HTTPS, if not, all bets are off).
And yes, it is possible for an attacker to redirect a user, if you allow the attacker to set where the redirect goes.
So that means that you should validate any user-inputted (and hence potentially attacker set) URLs that you're going to redirect to make sure they are safe. Basically make sure the URL is on your domain, and make sure that it's a valid URL. You can go deeper (check for XSS style attacks, etc), but you usually shouldn't have to as long as you're practicing good security practices in the rest of the application.
But then again, that's just basic application security Filter-In, Escape-Out. So filter the inputted URL, and you should be fine...

Related

Golang - Server Side Login Handling - how to resume request after login?

Currently, I’m developing a web app with server-side rendering using the Gin framework and I’m having a problem with login intercepting. When an HTTP GET request hits an endpoint, middleware is used to check the browser cookie and redirect the traffic to the login page. This works fine and after successful login, the user is always redirected to the dashboard page. My question is how I should redirect the user back to the originally requested URI instead of the dashboard page?
Also, a bit more complex scenario is on HTTP POST. It looks like the HTTP POST method doesn’t work quite well with a redirect. Also, how would I resume the request with the same post request after the user successfully login?
Thanks for the help!
For the HTTP GET scenario, this one is easy, you need to remember the original URL somewhere. The are a few ways you could go about this:
Store the URL in session information(if any is available, you do need sessions for non-authenticated users)
Store it in a query string, for example, redirect to example.com/login?original=https%3A%2F%2Fexample.com%2Fanother-page. Your login page can look for the query parameter and include it in the login form or make sure that the action of the login form matches the given URI. On a successful login attempt you can get the original URL form the query param and set it as the Location.
Store the original URL in a cookie, upon successful login you can just check the cookie value and use that.
As for the HTTP POST scenario. If you just want to redirect the same POST request to a different URL you can use a 307 Temporary redirect. A 307 will preserve the request body and method and not turn it into a GET request like a 303 See Other or 302 Found.
Resuming the original POST after showing the login screen and after a successful login is a little more complex. When you redirect to the login page you interrupt the flow of the user, maybe it is better to let the user re-post their request after logging in, instead of doing it for them.
Having said that, it is technically possible. We require two steps, first is storing all the data to recreate the request. Then after login completion we can render a form with this saved data and use javascript to submit the form. By adding:
<script>document.getElementById("myForm").submit();</script>
After your form, the browser will submit the form after loading the javascript, thus recreating the original POST.
The storage part can be done via the server side session or a cookie.

What's the best way to use HTTP Authentication in an Ajax Application that's not 100% AJAX

I have a standard HTML login page, which I would much rather use than the standard HTTP authentication pop-up provided by browsers. Today, I am using session cookies to keep track of the session after logging in, but I'd like to be stateless and pass the HTTP authentication every time. The web services I am hitting already support this, so this is a browser-only issue.
Adding authentication credentials is trivial in jQuery, but I don't know how to keep them around. If you go from the login page (a jsp) to the Home page (another jsp) you clearly don't keep the username and password fields from the login page. I know some browsers will store your HTTP authentication credentials if you enter them from the pop-up, but I don't know if they get stored when using an XHRRequest. If they do, is there much consistency among browsers?
Also, the user needs to be able to "sign out" of the application, too. If the browser stores the authentication credentials, is there a way to clear them using JavaScript.
I feel like I can't be the first person to try to solve this. Is there some jQuery plugin or something that already handles this? Or is it simply not possible to do what I'm trying to do?
You have 2 options:
1) Client-side storage of credentials -- not a good idea. For obvious reasons you don't want to store the username/password on the client. If you had a hashed version of the password, it might not be so bad, but still not recommended. In any case, if you're going to store on the client side, you either have to use a cookie, or HTML5 local storage (which is not widely supported, yet)
2) Server-side storage of credentials -- typically done with sessions. Then the resultant Session ID can be passed back to the client and persisted in either a cookie or in the URL of each subsequent AJAX call (?SESSID=xyz for example)
The server-side approach would be the most secure, reliable, and easiest to implement
Okay, I'll take a stab at helping ...
Firstly, understand how HTTP authentication works. There are two versions - Basic and Digest. Basic transmits in plaintext, digest is encrypted. With these types of authentication, the username/password are passed in the HTTP header with every single request. The browser captures these at login and they are stored in an inaccessible browser session cookie which is deleted when the browser session is closed. So, in answer to one of your questions, you can't access these from javascript.
You could create your own session cookie variables for username and password. The jQuery functions for this are really simple. See jquery-cookie module as one example of how to set session cookies. These could be retrieved from the session cookie and sent with each ajax request and validated in the server. However, this is not a particulary good way to do authentication since sniffing the network will allow anybody to easily grab your auth details. But, it would work.
Using session cookie based authentication where the session ID is sent sent with each request is the best way to do this. At the server side, you need to have a function called for every HTTP request. This function should do the following:
check to see if the session has been authenticated
if no:
redirect to login screen
if yes:
do authorization and allow the user access to the page
Most web frameworks support session cookie authentication and the management of session ids at the server. This is definately the way to go.
This is interesting one.
Manage user sessions on server by use of cookies. Create a session when user first accesses the login page and pass the session id/key as value to one of the cookie via response. When the user is authenticated put user "key" info in cookie and "values" in application context at server. Once user is logged, any subsequent request will be authenticated based on session cookie value at server. Authorization will be done based on user "key" passed as cookie value.
On logout clear the session based cookies from server and refresh the site to default page.
Cookies are bizarre with different browsers - just a note ;)
Hope this helps.
Update
The answer below was posted in 2012 and the links are mostly dead. However, since then, a more elegant standards-based approach to the same solution appeared using JSON Web Tokens. Here is a good blog post explaining how to use them.
Most answers miss the point, which is to avoid having any server-side session. I don't want any application state in the server. I'll award the bounty to answer that came closest, but the real credit goes to the rest-discuss group and Jon Moore for the correct answer and to Mike Amundsen for helping me to actually understand it.
The best answer I've gotten is to use a cookie, but not the typical automatic session id cookie given to you by most application servers. The cookie (which will automatically be sent with each subsequent request) is a user identifier and time signed by the server. You can include an expiration time with the cookie so it simulates the typical 30 minute session on a server (which means you have to push it forward with subsequent requests) as well as keeps the same cookie from being valid forever.
The XHR/AJAX part is a red herring. This will work whether you are doing XHR requests or an old-fashioned page-by-page web application. The main points are:
The cookie is automatically sent on subsequent requests so there's no
special scripting required - it's just how browsers work already.
The server does not need to store any session for the user, so the user
can hit any server in a cluster and not have to re-authenticate.
Slightly interesting in that you consider pushing some of the authent to the client. If you want a conventional solution, KOGI's server-side suggestion is the way to go.
But you also seem to be asking questions about memory leaks involving your user supplied secrets. Good questions. But to take a general stab at answering that I'd say it would have to be browser specific. It's browser internals, javascript engine internals -dependent where a client side application (i.e., the browser, or js in the browser) is storing the values the user inputs.
Most likely those values are not replicated needlessly throughout memory, but there's no way to guarantee that. Apart from responsible javascript coding practices, there's nothing you can do to guarantee the limit of locations of user inputs.
Slight digression
The basic point is if you store it on the client it is not really secure -- unless, the serve stores encrypted information on the client with a key that only the server (or the user via their correct credentials), has. So you could conceivably code a JS application to do some authent on the client -- much the same as how bank card (used to?) do POS authent by checking the PIN to the PIN on the card, and not back at the DB. It's based on the (somewhat flimsy) assumption the user has no direct read/write access of the "dark area" cookie/local storage on client / mag strip on bank card. So I would only advise this as disqualifier for false authents and not as a sole qualifier for the credentials.
Main point
If you do want to be stateless, just store user credentials in localstorage, or as a cookie but encrypt them with a server key. When you need them send an XHR with the encrypted / use stored credentials to the server over HTTPS, let your server decrypt them and send them to the callback. Then pass those cleartext of HTTPS to do your authent.

Ajax, PHP and Security?

My question is that suppose, in my web app, I use ajax to call upon methods on the server side, isn't it creating a security hole in the app? Like, say I have an option for the user to deactivate the account, which can be done by clicking a button. This is done via Ajax.
So, can't a hacker send a request to the server to deactivate the account instead of the user?
HELP!!!
My question is that suppose, in my web app, I use ajax to call upon methods on the server side, isn't it creating a security hole in the app?
From a security perspective, there is no difference between an HTTP request that involves JavaScript and one which doesn't (e.g. that uses a regular form, or is handcrafted).
… but you can't call methods from the client, you can only make requests to URIs. The server might cause a method to be called based on receiving a request to a specific URI.
So, can't a hacker send a request to the server to deactivate the account instead of the user?
They could, which is why you need (trustworthy) authentication / authorisation and CSRF protection (just like you would for a request to disable an account that didn't involve Ajax).
This is not a problem with AJAX alone, but with any arbitrary HTTP request that wants to authenticate/maintain a session. The user needs to be authenticated in some way in order to make requests, this is usually done with cookies. Using AJAX does not make the matter any worse though because it is still a HTTP request.
Authentication alone is not enough though, someone could always be listening on the wire and capture the authentication cookie, and thus get hold of the session - "become you". The only solution here is to encrypt the connection on a lower OSI layer level (using SSL/TLS). This is why you should always use SSL when it comes to authentication.
This Ruby on Rails security guide has a great explanation on how to deal with AJAX requests that could be potentially exploited. It's not specific to RoR so the concepts can apply to any platform.
One way to reduce the risk of cross site requests is to use POST for actions that modify or delete data.

Securing an ajax request

i have a website that uses session cookies for security. it works fine and all, but any ajax requests right now are not secure. example being lets say a user is on a page. they can only get to this page if they are logged in with a session - so far so good. but now the ajax request they ask for is
ajaxpages/somepage.php?somevar=something&anothervar=something
if any other user decides to just go to that link themselves (without a session) they still get the same ajax output that was meant for logged in people.
so obviously im going to have to pass session data across when i send an ajax request. anyone have any tips for the best way of doing this? ive never done this before and would rather use trusted methods than make up my own.
The ajax requests work just like any other request to your website and should return the same session cookies as the non-ajax request. This is pointed out in this question. If you aren't getting the session cookie, perhaps something else is wrong.
Having an ajax output isn't necessarily a vulnerability. It entirely depends on what data is being transmitted. I am not sure what platform you are using, but most web application development platforms have a session variable that can maintain state between requests.
What you should have in place is way of marking the user as being logged in from the server side. I php this would look like:
if(login($user,$password)){
$_SESSION['logged_in']=true;
}
Then you can check in a header file if they are allowed to access the page:
if(!$_SESSION['logged_in']){
header("location: http://127.0.0.1/");
die();
}
(If a variable isn't set it is also false.)
There are a few things you need to keep in mind. This is a vulnerability:
if(!$_COOKIE['logged_in']){
header("location: http://127.0.0.1/");
die();
}
The user can control $_COOKIE, so they can tell you that they are logged in.
Another vulnerability:
if(!$_COOKIE['logged_in']){
header("location: http://127.0.0.1/");
}
header() doesn't kill the script. In fact it still runs, so it will still output but it won't be displayed in a browser, you can still use netcat/telnet/wireshark to see the data.
Use the same security check on the pages that handle the ajax request.
Since that is a PHP page, I don't see why you couldn't perform authentication on the PHP side. If authentication is successful, send back the data. Otherwise, send back an error message. AJAX aren't that different from any other request.
Just let ajax carry the session cookie, there is no problem with that, but you must check if the user is logged or not at the end, and you might want to add some CSRF token for your request, just in case ...
And try to validate the referrer, so you can check if the request was sent from your website, and your website only, it's not a good practice to let user open your request url for ajax in their browser ....
And if you have query in your script, to get some data from your database or else ... don't forget to sanitize the input, and escaping the output, based on what kind of data that you need, once more just in case ...

Login page uses SSL, unencrypted pages don't see encrypted session cookie (Grails, Acegi)

Setup: Grails 1.1, Acegi/Spring Security plug-in
I want users to log in over SSL, so I have '/login/**' in my channelConfig.secure[] list, but almost everything else is in channelConfig.insecure[]. Every request for /login gets redirected to https:// and every other request is redirected to http://.
My problem is that the login process sets the cookie to "Send over encrypted connections only," so when the login page redirects to /home, the home page doesn't see the cookie and redirects me back to the landing page. When I try to log in again, the login page sees the cookie and redirects me...etc.
I hunted through this page about SecurityConfig to see if there is an option to allow cookies created over SSL to be read over unencrypted HTTP, but I found nothing. Is there some option I can set to make my login cookie available to my unencrypted controllers?
This would be a vulnerability.
Any man-in-the-middle that can see the session cookie would be able to make requests as the user. This is almost as bad as the password being intercepted. The man-in-the-middle wouldn't be able to establish new sessions on his own, but he would be able to do anything the user can do once a user logs in.
Using SSL does a lot more than simply hiding the user name and password at login.
First, it provides confidentiality for all messages between the client and server. It's easy to recognize the password as sensitive data, but it might not be as obvious which application features use sensitive data as well. Protecting any user input and dynamically generated content is safer and easier than trying to carefully evaluate the privacy issues of each data field used in your application. Static content such as images, help pages, etc., probably isn't as sensitive, but by analyzing requests for that content, an attacker might get a good idea of what a user is doing on the site.
Second, SSL provides integrity for every request. This prevents an attacker from modifying or appending their own nefarious input to user requests, or modifying the results produced by the server.

Resources