How do I restrict the WCF service called by an ASP.NET AJAX page to only allow calls for that page? - asp.net

I have an AjaxControlToolkit DynamicPopulate control that is updated by calls to a WCF service. I know I can check the HttpContext in the service request to see if a user of the page (and thus, the control) is authenticated. However, I don't want anyone clever to be able to call the service directly, even if they're logged in. I want access to the service to be allowed ONLY to requests that are made from the page. Mainly, I don't want anyone to be able to programatically make a large number of calls and then reverse-engineer the algorithm that sits behind the service.
Any clever ideas on how this can be done? Maybe I'm over-thinking this?
Thanks in advance.

The simple answer is you can't. The complicated answer is you can fudge it with a lot of work, you could for example
Rate limit based on the IP of the caller.
Drop a cookie based upon the session and rate limit on that.
Drop a cookie based upon the page when the page loads and rate limit upon that.
However none is foolproof, and all can go wrong with legitimate requests.

If you really want to restrict this to just this one server making the request, you could add a certificate to that server and check for that certificate. However, you probably can't really limit access to just a single page calling your service.
You could add a lot of additional elements, like headers etc. - but none will really be totally sound - if someone is determined enough, they'll be able to figure out what you're doing, and replicate that.
So really: why do you need to limit this access this badly?

I solved this with a different approach. Instead of trying to secure the service to a single page, I just secured the service by checking HttpContext to make sure the user making the request is authenticated. This relies on ASP.NET Compatibility being enabled on the WCF service class: http://msdn.microsoft.com/en-us/library/ms752234.aspx
Then I have access to HttpContext within the service and can check that the call came from an authenticated user. =D

Related

Is there a security risk with internal HTTP call

Is there a security risk if an application called page.ashx called internal only page.ashx, can a hacker conclude that another page is called.
I don't want anyone to access this page. it looks stupid I know, but it is a part of more complex problem.
thanks
"I don't want anyone to access this page."
To archive that you need to check if your user is authenticated one inside this page, or this page is in the directory that this roles of authenticated users can see.
The redirects can been read - so if you have some other page that redirect to the one you say, this is visible.
The server transfer however can not bee read and its internal, but I do not know if this can help your case.
By default, an ashx handler can be accessed just the same as an aspx page.
It is unclear what you mean by "internal". If the call is made at server side you can hide the file by removing permissions on the IIS. However, that may indicate you don't need a handler at all, and can probably call the function directly.
If the client need to access it (if it's returning a script or an image, for example), you cannot prevent direct access to it.
If you're looking for security light, you can obfuscate the URL with a hard to guess file or folder name and then use server transfer as Aristos suggested.
If you're looking for fancier security, then implement a web service instead of an ashx that requires authentications from the calling code with application credentials (something the application has that the user doesn't have so that the user can't call the service directly).

Maintaining session information between 2 asp.net calls programmatically?

I'm not sure if I'll be clear enough in my explaination to make you guys understand, but I'll try.
Here's my problem:
We have an external site which the users in our company connect to by giving their corresponding username and password. The external site is an ASP.NET website. We want to integrate this website into our intranet portal so that the users don't have to enter their UN/Pwd to login to the website. Since the target website has no provision for SSO, we are simulating the POST request to login.
So far so good.
We are now required to perform an action after the initial login is done, on an another page. We can simulate the corresponding POST request as well. But the problem is since we are not maintaining any session information in our initial POST request, it always redirects to the login screen!
Is there any way to maintain ASP.NET session information between multiple calls done programmatically? Can we create an ASP.NET session id cookie programmatically and then pass it along with our initial request?
Or this is not possible at all?
Any comments are appreciated.
Thanks for your help.
Regards.
Maintaining the state is the responsibility of the other site (typically in a cookie).
You should perform the actions manually, then use Fiddler to compare the HTTP requests and figure out what's wrong.

Is it possible to authenticate on another website?

If I am on a website#1, and I enter my username/pwd for website#2 on a login page that is on website#1, and website#1, behind the scenes, makes a httpwebrequest to website#2 and posts to the login page. If I then navigate to website#2, should I be logged in?
website#2 uses formsauthentication and I call a httpHandler that is on website#2 and pass it the username/password via the querystring.
Should this work?
What you're trying to do is called Single Signon. The way you're doing it, posting values from one site to another, probably won't work because you're using the same technique a hacker might use to trick user into sharing their login information. It's called a cross-site request forgery attack. IIS is configured not to allow that.
Generally, you need a central authentication system that both sites use to share login information. This can be done in several ways, including a shared database-based login system. Google "asp.net single sign on" for more ideas.
Do site #1 and #2 want their users to have single sign on?
If so, read up on single sign on. It's a bigger project than can be addressed here. There is a good book on it though from Wrox :
http://www.amazon.com/Professional-ASP-NET-Security-Membership-Management/dp/0764596985/ref=cm_lmf_tit_10
Or are we imagining something sinister?
If we are imagining something sinister, then evil site #1 would collect the credentials, then automate a browser on the server side to start checking to see if site #2 uses the same password and user combination. Then the server would have an authenticated session. This wouldn't give the user who accessed site #1 an auth cookie, the HttpWebRequest object on the server would get the auth cookie. Site #2 couldn't really do anything to prevent this because a browser request from one computer looks much alike a browser request from another. A well crafted attack would spoof all elements of the browser's request so that it looks like it came from a browser instead of a primitative HttpWebRequest object, which may not even set the user-agent.
Site #2 should stop using passwords and user Id or use 2 factor ID if they are concerned abut this, or do something that requires javascript for logon because spoofing a browser that is executing javascript is harder than spoofing a browser that just sends and receives http requests and responses.
There are too many security issues trying to auto-authenticate between sites. There needs to be a central security provider that both sites belong to so that hand off is completed securely.
We use CA's Siteminder for cross site authentication. Effectively, web 1 creates a unique session id on the siteminder server and passes any credentials and info to it. Siteminder invokes web2 and passes the information by means of session variables. Web 2 retrieves the data from the session and uses it. There's much more going on there but that's the just of it.
To do something like this, I would strongly consider using an out of the box solution as generally coding up custom security generally falls short.
While this can be done on some cases, in the form of an HTTP request with POST parameters, you will not be authenticated once you browse to site #2.
This is because, generally, these sites store a cookie on your end and these are domain-based, which means that even if you grabbed that and stored it yourself from site #1, the cookie name would not match site #2.
Additionally, site #2 may not be easy to authenticate against and this is usually a security concern that developers are aware of. This can be considered an attempt of XSS as well.
In case you're simply doing this for yourself, I'd recommend LastPass and save most of your info in it.
Please reconsider your goals and how to achieve them, this is not the way.
Edit: Link text.
This could work, depending on the security measures in place on website #2. For a secure website, this would fail.
I would recommend against this purely on the basis of good security and good coding/design practices.
If you are unclear what security measures stop this, you should probably educate yourself so you can prevent the same issues on your own site. See http://www.owasp.org/index.php/Top_10_2007
Since both your sites are using FormsAuthentication you can easily configure both of them to share FormsAuthentication encryption schemes.
This will allow you to do Cross Application Authentication automatically :)

User roles - why not store in session?

I'm porting an ASP.NET application to MVC and need to store two items relating to an authenitcated user: a list of roles and a list of visible item IDs, to determine what the user can or cannot see.
We've used WSE with a web service in the past and this made things unbelievably complex and impossible to debug properly. Now we're ditching the web service I was looking foward to drastically simplifying the solution simply to store these things in the session. A colleague suggested using the roles and membership providers but on looking into this I've found a number of problems:
a) It suffers from similar but different problems to WSE in that it has to be used in a very constrained way maing it tricky even to write tests;
b) The only caching option for the RolesProvider is based on cookies which we've rejected on security grounds;
c) It introduces no end of complications and extra unwanted baggage;
All we want to do, in a nutshell, is store two string variables in a user's session or something equivalent in a secure way and refer to them when we need to. What seems to be a ten minute job has so far taken several days of investigation and to compound the problem we have now discovered that session IDs can apparently be faked, see
http://blogs.sans.org/appsecstreetfighter/2009/06/14/session-attacks-and-aspnet-part-1/
I'm left thinking there is no easy way to do this very simple job, but I find that impossible to believe.
Could anyone:
a) provide simple information on how to make ASP.NET MVC sessions secure as I always believed they were?
b) suggest another simple way to store these two string variables for a logged in user's roles etc. without having to replace one complex nightmare with another as described above?
Thank you.
Storing the user's role information in a server-side session is safe providing a session cannot be hijacked. Restating this more broadly, it does not matter where user role info is stored if an authenticated session is hijacked.
I advise not putting too much faith in the article you linked to, but the 2002 vintage report linked to from your link is of interest. Here are my take-aways:
Don't accept session IDs embedded in URLs.
Focus your time on eliminating cross site scripting dangers i.e. scan all user supplied data and parse out executable java script.
Issue cookies for complete domains (e.g. myapp.mydomain.com)
Host your domain at a high class DNS operator e.g. one that only allows DNS changes from a preset remote IP address.
Don't issue persistent session cookies.
Reissue a session cookie if someone arrives at a login page with a sessionID already associated with an authenticated session.
Better still, always issue a new session cookie on successful authentication and abandon the prior session. (Can this be configured in IIS?)
The only way to make a secure cinnection is to use SSL. Anything less than that, and you simply have to make the evaluation when it's "safe enough".
A session variable works fine for storing a value, with the exception that the web server may be recycled now and then, which will cause the session to be lost. When that happens you would have to re-authenticate the user and set the session variable again.
The session variable itself is completely safe in the sense that it never leaves the server unless you specifically copy it to a response.
Have you considered setting up a custom Authorize tag in MVC. I gave an example of this in another question.
On initial authorization (sign-in screen or session start) you could seed a session value with the IP address also. Then in your custom authorization, you could also verify that IP's still match up as well. This will help make sure that someone isn't 'stealing' the person's session. Everytime you access your session data just make sure to pass the requester's IP and have some check on it.
Are you trying to control the access to functions at the client level? That is the only reason I would expose the roles and items to control client side functions.
Alternatively, you could create a function to obtain the items that the roles of the user are allowed to use, and then even if the function is called outside of the items given back to the web application, you can prevent the user from accessing them.
4Guys seems to show how to control functions with the roles.
The approach I have used in the past is to use symmetric encryption of a cookie alongside SSL. Encrypt the user information in the reponse and decrypt it in the request. I'm not claiming this is foolproof or 100% secure and I wouldn't want to do this on a banking application, but it is good enough for many purposes.
The main issue with session variables is that if you store them inProc rather than persisting them, then you need to apply 'sticky' sessions to your load balancing in a web farm environment. Guffa is correct that without this persistence session variables will occasionally be lost causing a poor user experience.
Sticky sessions can lead to uneven load balancing, perhaps reducing the value of being able to scale out.
If you are going to be be persisting the sessions so they can be accessed by all servers in your web farm, you may be better off using a Guid to identify the user, encrypting this in a cookie and retrieving the user record from your data store each time.
My obvious question is that why do you want to store a users role in session ?
Here is my answer to your query, how this helps. I have attached a small demo application for you to take a look at and understand my points. When you open this project in visual studio, click on the project tab on the top and select asp.net configuration. From the page that will show up you can do the user administration stuff.
You need to store the roles of a user in some secure manner ? The answer to this question is that there is no need for you to worry about storing the role for any user, when we have the asp.net membership, profiles and roles framework to help us out on this. All you need to do is create a role in the aspnet database and assign that role to the user.
Next you want to store two string in some secure manner. I suggest you user profile for storing user specific information. This way you have the information available to you where ever you want from the profilecommon class.
Also please see the attached demo application placed at the end of my blog http://blogs.bootcampedu.com/blog/post/Reply-to-httpstackoverflowcomquestions1672007user-roles-why-not-store-in-session.aspx
Just a suggestion, you might consider using this little library:
http://www.codeproject.com/KB/aspnet/Univar.aspx
It has a server side implementation of the cookie whereby all cookies can be stored on the server while asp.net authentification is used to identify the user. It supports encryption and is also very flexible making it very easy to switch from one storage type to another.

How to create a database driven login system

I want to create a website that the login system shouldn't be handled by cookies, but on (a) table(s) in the local (on the server) SQL DB.
Is there a way to do it?
Even no partial way?
What and where should I save instead of the cookie???
ASP.NET uses Session cookies by default to track user requests. If you use Cookieless sessions, you will find the Session ID being appended in all requests from the browser. In many scenarios, this could also be unacceptable.
Even if you decide to hit the database and check for a "LoggedIn" flag upon each request, you still need some way to identify the incoming request as belonging to a particular user. This could be in the form of encrypted values in hidden fields, depending on your security scenario. That said, it's not a much better method than the use of cookies, because any data that comes from the client has the potential to have been tampered with.
Personally, I think Cookies are great to track user requests as long as you encrypt them properly.
You still need some way of telling the users apart. If you don't use cookies, then you will have to transfer that information in url or allow only one user from a single ip address (this is really stupid) ... or something else. Cookies are not that bad :-).
Cookieless ASP.NET
If you need help actually implementing the login system you'll need to include more details about your specific problem.
You can store your usernames and so in a database, but you will still need a way to recognize the user as he/she navigates from page to page. That is the cookies role in this, to persist this login token...
It is possible to implement some other ways of handling this token. One can use the URL or somme hidden fields (as ASP.NET's ViewState) to store this token.
So, yes; it can be done. But it takes some work, since you can't use what ASP.NET already provides you. (ASP.NET has builtin-features to handle this token as a cookie, and also store the credentials in the database.)
Use the SqlMembershipProvider.

Resources