Securing Ajax Requests in ASP.net via Authenticated Webforms - asp.net

I already read
Securing AJAX Requests via GUID
and
Securing an ajax request
. Now let me explain my scenario, below would be code snippet that may aid at explaining in the subject matter.
[WebMethod[EnableSession = True]
[ScriptMethod]
public static string CreateTitle(string strTitleName)
{
string strResult = "Custom jSon string";
if(Session["Authorized"] == "True" && !String.IsNullOrEmpty(strTitleName))
{
String strTitle = Server.HtmlEncode(strTitleName);
InsertRecordInDB(strTitle);
strResult = "Custom jSOn string" + EncryptMD5("record id");
}
return strResult;
}
and below is the javascript call to send in the parameters. btnCreateTitle_click is the click event of the button client side. txtTitle is the textbox accepting the title name. Validators are created on the page to validate the textbox too.CreateTitle is a page method i call using scriptmanager
function btnCreateTitle_Click(evnt){
if(Page.ClientValidate()){
if($get("txtTitle")){
PageMethods.CreateTitle($get("txtTitle").value,success,failure,context);
}}}
the function success shows a growl message that title was created and shows a link with encrypted record id as query string to the url to view the details of created title.
Now the burning question,
IS this secure enough? What am i missing?
How could i make the process more secure and faster?

While it is trivial to restrict any method to authenticated and authorised users, when you expose db id's in query strings you do open the possibility that an authenticated and authorised user may seek to access records that they aught not. This is particularly so when the db id's are integers or some other easily guessed identifier. Using Guids as db ids may mitigate the risk of this, though not absolutely.
What you always need to remember is DO NOT TRUST INPUT. Security through obscurity (ie encryption etc) is not a reliable technique. Your service should always verify the the current user is allowed to retrieve the records they have requested. Sometimes this is known as row level security. This can only be done programmatically.
eg instead of only determining that someone is authorised to view a record, you need to verify that they have rights in fact to access the record they are requesting.
This means you need some way of relating records to an authenticated user.
BTW: any HTTP request is validated for potentially dangerous input.
Hope this helps,

Related

C#/OWIN/ASP.NET: can I *manually* generate and get a valid bearer token string in my API code?

I am using the OWIN OAuthAuthorizationServer library in an OWIN ASP.NET C# web API to generate and process bearer tokens.
Right now, I have a single endpoint (which you set in the OAuthAuthorizationServerOptions struct) that accepts the grant_type, username and password fields from the frontend. I created a provider class that performs the validation, and then calls context.Validated() or context.SetError() accordingly. The middleware then handles generating the token and returning it to the user, and also "takes over" the login endpoint, doing all the work internally.
Now, I am adding a new feature to my API where the user can change their "role" (e.g. an admin can set themselves as a regular user to view the results of their work, a user can select among multiple roles, etc.) Since I already handle this through the bearer token (I store the user's role there and all my endpoints use the bearer token to determine the current role), I now have a reason to update the contents of the bearer token from the API backend.
What I'm looking to do is to allow the frontend to call an endpoint (e.g. api/set_role) that will accept a parameter. The user requests a certain role, and their current bearer token would accompany the request. The server then would check if the user in question is allowed to use that specific role and, if so, would generate a new token and return it to the user in the response body. The frontend would then update its token in local storage. Or, of course, if the user is not permitted to switch to that role, the backend would return an appropriate error and the frontend would react accordingly.
To do this I basically want to be able to manually generate a token. Similar to how I use identity.AddClaim() in my login provider, I'd like to be able to do that at any arbitrary position within the API's code. The method would take responsibility for transferring over any necessary existing information (e.g. the user's username) into the new token, since it already has the existing one.
Pseudocode for what I want:
if (!userCanUseRole(requestedRoleId)) return Request.CreateErrorResponse(...);
// we have a struct containing parsed information for the current token in the variable cToken
bearerToken newToken = new bearerToken();
newToken.AddClaim(new Claim("user", cToken.user));
newToken.AddClaim(new Claim("role", requestedRoleId));
string tokenToReturnToFrontend = newToken.getTokenString(); // string suitable for using in Authorization Bearer header
return Request.CreateResponse(new StringContent(tokenToReturnToFrontend));
I am not too familiar with "refresh" tokens, but the only way I am using them right now is extending token expiration. To that end the frontend explicitly requests a refresh token and provides its own, which the backend simply copies to a new token and edits the expiry time. The problem with this is that there's a single method for getting a refresh token, and since I have now at least one other reason to refresh a token (and possibly, future developments could add even more reasons to change token contents at various times), I'd then have to deal with storing transient data somewhere (E.g. "when requesting a refresh token, what is the thing the user wanted to do? has it been too long since they requested to do that? etc.) It'd be much easier if I could simply generate a bearer token on demand in the same way that the OAuthAuthorizationServer itself does. (I know it uses the MachineKey to do this, but I don't know exactly how it does it, nor how I would go about doing what I'm trying to do.)
Of note: In another project I provided internal access to the OAuthBearerAuthenticationOptions class that is passed to the authorization server instance, and was able to use that to decode a bearer token inside of a test. I haven't seen anything obvious thought that would let me encode a bearer token this way.
EDIT: I explored the (extremely tersely, almost uselessly documented) OWIN namespace and found the AccessTokenFormat class which appears that it should do what I want. I wrote this code:
Microsoft.Owin.Security.AuthenticationTicket at = new Microsoft.Owin.Security.AuthenticationTicket(new ClaimsIdentity
{
Label="claims"
}
, new Microsoft.Owin.Security.AuthenticationProperties
{
AllowRefresh=true,
IsPersistent=true,
IssuedUtc=DateTime.UtcNow,
ExpiresUtc=DateTime.UtcNow.AddMinutes(5),
});
at.Identity.AddClaim(new Claim("hello", "world"));
string token = Startup.oabao.AccessTokenFormat.Protect(at);
return Request.CreateResponse(HttpStatusCode.OK, new StringContent(token, System.Text.Encoding.ASCII, "text/plain"));
which seems like it should work. (I again allow access to the OAuthBearerAuthenticationOptions class passed to the OAuthAuthorizationServer instance.) However, this code throws an ArgumentNull exception. The stacktrace indicates that it is writing to a BinaryWriter but the OWIN code is passing a null value to the Write method on the BinaryWriter.
Still have no solution.
I did figure out the code to make this work. One could argue I'm "not using OAuth right", but strictly, this code WILL accomplish what I want - to generate a token in code at any arbitrary point and get the string.
First, as I said, I have to provide access to the OAuthBearerAuthenticationOptions class instance. When the OAuth server initializes I'm guessing it populates this class with all of the various objects used for tokens. The key is that we do have access to Protect and Unprotect which can both encode and decode bearer tokens directly.
This code will generate a token assuming that oabao is the OAuthBearerAuthenticationOptions class that has been passed to the OAuthAuthorizationServer instance:
Microsoft.Owin.Security.AuthenticationTicket at = new Microsoft.Owin.Security.AuthenticationTicket(new ClaimsIdentity("Bearer", "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", "http://schemas.microsoft.com/ws/2008/06/identity/claims/role"),
new Microsoft.Owin.Security.AuthenticationProperties
{
AllowRefresh = true,
IsPersistent = true,
IssuedUtc = DateTime.UtcNow,
ExpiresUtc = DateTime.UtcNow.AddDays(1) // whenever you want your new token's expiration to happen
});
// add any claims you want here like this:
at.Identity.AddClaim(new Claim("userRole", role));
// and so on
string token = oabao.AccessTokenFormat.Protect(at);
// You now have the token string in the token variable.

ASP.NET MVC Anti Forgery Token Insecure

I can actually see the verification token key generated by MVC3 framework in plain text when making a request to the server without ssl.
This key is stored in a cookie called: _RequestVerificationToken_Lw__
In mixed security environment it is actually possible to see this token in plain text sent to the server on the initial request to the non ssl site. This token is also static for the duration of the user's session. Then what's the use of having this token when it can easily be stolen by an attacker, because the cookie gets thrown around in plain text.
Shouldn't this cookie be marked as secure and never to be sent across in plain text? Or at the very least be regenerated on every request such that the secure information doesn't leak out of the ssl channel?
I'm talking about this block in MVC 3 AntiForgeryWorker class
private string GetAntiForgeryTokenAndSetCookie(HttpContextBase httpContext, string salt, string domain, string path)
{
string forgeryTokenName = AntiForgeryData.GetAntiForgeryTokenName(httpContext.Request.ApplicationPath);
AntiForgeryData token = (AntiForgeryData) null;
HttpCookie httpCookie = httpContext.Request.Cookies[forgeryTokenName];
if (httpCookie != null)
{
try
{
token = this.Serializer.Deserialize(httpCookie.Value);
}
catch (HttpAntiForgeryException ex)
{
}
}
if (token == null)
{
token = AntiForgeryData.NewToken();
string str = this.Serializer.Serialize(token);
HttpCookie cookie = new HttpCookie(forgeryTokenName, str)
{
HttpOnly = true,
Domain = domain
};
if (!string.IsNullOrEmpty(path))
cookie.Path = path;
httpContext.Response.Cookies.Set(cookie); //Ma, Why isn't this marked as "SECURE"
}
return this.Serializer.Serialize(new AntiForgeryData(token)
{
Salt = salt,
Username = AntiForgeryData.GetUsername(httpContext.User)
});
}
That's quite the inflammatory question title you have there.
The built-in MVC anti-forgery functionality is as secure as the application is configured to be. All cookies written to Response.Cookies will be automatically marked with the "secure" modifier if <httpCookies requireSSL="true" /> is set in Web.config (see MSDN docs). MVC's anti-forgery cookie also gets this behavior if this switch is set.
Combine this with other functionality like setting the HSTS header in your responses, and you're essentially providing a guarantee that the browser will never send sensitive data over plaintext channels.
Additionally, the anti-forgery system does allow storing custom data in the tokens, and you can receive a callback to verify the custom data when the token is validated. See AntiForgeryConfig.AdditionalDataProvider for more information.
With protection against CSRF attacks, an optimal solution is to always use SSL. Without SSL, yes, the nonce--as it is called--is vulnerable to a MITM attack. When using cookies to store the nonce, the cookie must be marked HTTP-only. This prevents JavaScript from reading the cookie. You should also render the nonce as an <input type="hidden" value="nonce"> tag within all <form>s in addition to a cookie.
Anyone with access to the browser itself would be able to read the nonce, and the only way to prevent a replay attack is to have nonces expire the first time after they are validated for the first time by the server. This approach can cause a terrible user experience when the user uses the back button and resubmits a request with the same nonce, however. Because you're using ASP.NET MVC's built-in anti-CSRF protection mechanism, it may not be easy to change its behavior to only allow a nonce to be used once. (EDIT: Thanks to Levi below for informing me that ASP.NET MVC actually makes this quite simple)
If you want better control over generating and validating the nonces then I suggest rolling your own implementation, as I did with my JuniorRoute framework. In fact, feel free to take a look at JuniorRoute's source code to see how I implemented it. It's too much code for a Stack Overflow post.
My Take
a) The form submission is deemed not forged based on comparison of
__RequestVerificationToken cookie &
__RequestVerificationToken form field.
The 2 values are some kind of symmetrically match and hence not same.
b) Cookie can never be marked default must-use-secure-channel by the framework because some applications do not use https.
c) The __RequestVerificationToken implementation is protection against CSRF & cannot help valid user from snooping into process memory:p.

HMAC and WCF Service .net

So I'm very new with HMAC authentication and I really don't know what I'm doing nor reading atm.
I've been trying to understand the following articles / links / discussions properly:
How to implement HMAC Authentication in a RESTful WCF API
http://blogs.microsoft.co.il/blogs/itai/archive/2009/02/22/how-to-implement-hmac-authentication-on-a-restful-wcf-service.aspx
http://buchananweb.co.uk/security01.aspx
With that said I have a few questions:
Understanding the first link, if for example I have a loginAuthentication service created in .net and will be accessed from an iPhone app do I pass an unencrypted username (message) for this and should return just a true / false or should it return an encrypted string in which I will be using later on for other transactions (Delete, Insert services, etc)?
[ServiceContract]
public partial class LoginService
{
[OperationContract]
bool Authenticate(string username) {
// stuffs
}
}
With that said, after I verified the user, and this is where I get lost. Is it better that I save something in the database 'with a timestamp' (someone told me about this and I read some discussions about this too)? Or do I just return it with the encrypted message (dependent on the first question) so that everytime a request is made the timestamp is already attached?
a. And what do I do with that timestamp?
b. Is it going to be used once the message is sent again for another transaction?
Keys and secret message. The way I understood it is that the key will be the password of the user. So if the user sends his username I can open the message using the password of that user? This makes sense if the user already has a session and is just requesting to get data or requesting for a delete, insert, etc. Should it still be the same way if it's just authenticating the username and password of the user?
Thank you for your time!
The first thing I would like to mention is that the WCF Web Api was a beta project which is no longer being developed. It was replaced by ASP.NET Web API which is an awesome framework for developing RESTful services.
If you want to get a good idea how a RESTful service and authentication works the Netflix API would be a great place to start. They have a lot of documentation regarding the security portion and this helped me understand HMAC a lot more.
HMAC creates a hash using a secret key. The client and server both maintain a copy of the secret key so that they can generate matching hashes. This allows you to 'sign' a request which serves as both authentication (you know the person sending it is who they say they are), and message integrity (knowing the message they sent is the original message and has not been tampered with).
A signature is created by combining
1. Timestamp (unix epoc is the easiest to send in urls)
2. Nonce (a random number that can never be used twice to protect against someone re-using it)
3. Message (for a GET request this would be the URL, a POST would be the whole body)
4. Signature (the three previous items combined and hashed using the secret key)
Each of the above can be sent in the query string of the request, then the server can use the first 3 and their copy of the secret key to recreate the signature. If the signatures match then all is good.
In a RESTful API that is over plain HTTP (not using HTTPS over an ssl), I would sign every request sent because again this authenticates and provides message integrity. Otherwise if you just send an authentication token you know the user is authenticated but how do you know the message was not tampered with if you do not have a Message Digest (the HMAC hash) to compare with?
An easy way to implement the server-side checking of the signature is to override OnAuthorization for System.Web.Http.AuthorizeAttribute (Make sure not to use Mvc autorize attribute). Have it rebuild the signature just as you did on the client side using their secret key, and if it does not match you can return a 401. Then you can decorate all controllers that require authentication with your new authorize attribute.
Hopefully this helps clear up some of your confusion and does not muddy the water even further. I can provide some more concrete examples later if you need.
References:
Netflix Api Docs: http://developer.netflix.com/docs/Security#0_18325 (go down to the part about creating signatures, they also have a link which shows a full .NET example for creating the HMAC signature)
.NET class for creating HMAC signatures http://oauth.googlecode.com/svn/code/csharp/OAuthBase.cs
Netflix API Wrapper I wrote: https://bitbucket.org/despertar1318/netflix-api/overview
ASP.NET Web API: http://www.asp.net/web-api
Looking at your questions in turn
...do I pass an unencrypted username (message) for this and should return just a true / false or should it return an encrypted string in which I will be using later on for other transactions (Delete, Insert services, etc)?
If you just returned a boolean, you'd have no way to then match the authentication request to subsequent requests. You'll need to return some sort of authentication indicator, on a classic website this would be the session cookie, in your instance you want to pass a value that will act as shared key.
Is it better that I save something in the database 'with a timestamp'? Or do I just return it with the encrypted message so that everytime a request is made the timestamp is already attached?
Back to the session analogy, you want to store the key from question one somewhere (the database?) with a timestamp that indicates the life of the session/validity of the key. If it's forever then I wouldn't bother with the timestamp, if it's anything else you'll need something to say when it expires.
The way I understood it is that the key will be the password of the user. So if the user sends his username I can open the message using the password of that user? This makes sense if the user already has a session and is just requesting to get data or requesting for a delete, insert, etc. Should it still be the same way if it's just authenticating the username and password of the user?
This is where the HMACing happens. You have your shared secret, you have a message, this is how I usually combine it all together.
Use all of the message as the body of data to be hashed (that way you can be sure that someone's not just copied the hash and part of the message). Hash the body of the message using the key we shared in step one. You could salt this if wanted, I'd use the username.
Finally make sure the message contains a timestamp (UTC preferably), this way you can help prevent replaying the message later. The service that's responding to the message can compare the timestamp to what it thinks the time is. If it falls outside given bounds, fail the message. Because the timestamp will be part of the HMAC, someone can't just update the date and replay the message, the hashes won't match as soon as the message is tampered with.

Return to the page initiated post-back. Best practice

I have ASP.NET MVC site with authentication dialog (login/password) that is accessible on every page. When user provides login/password post-back is initiated to special controller, not the same as the one generated the page with dialog.
I do some authentication stuff and wish to return user's browser to the same page request came from. I do the following (simplified):
protected ActionResult Authorize(string login, string password)
{
...
return Redirect(Request.UrlReferrer.AbsoluteUri);
}
what is the best practice to perform such action?
Thank you in advance!
In the default Membership of ASP.NET they simply use a returnUrl parameter in the query string. I find that this gets the job done quite well. It also allows me to bounce them to a different url if that is what the requirement is.
There is nothing wrong with the way you are doing it now, I just prefer the flexibility of the query string parameter.

Security for Flex app when ssl is not available

So I know the best practice would be to run my Flex app over ssl along with implementing other forms of security however that isn't an option at this point (for monetary reasons and the app simply doesn't need that much security otherwise my sponsors would pay for it). However, I would like to implement some form of security and I'm wondering whether it's even worth it when I don't have ssl to protect the transactions.
So my setup is that I have a ASP.Net server side with a Flex UI. Right now the UI is the only thing that protects access to the sever: the server doesn't do any sort of verification during each request, it just assumes the person is allowed to do it. Obviously, anybody could write a program to generate posts (even if I could use SSL it would be like swiss cheese). Like I said before, security isn't a big deal, this is an internal app and it's nothing critical, however I do believe in doing things right. Would keeping the user info in session be a viable option and then verifying that the given user has permission, etc. Perhaps some sort of token system?
What would your preferred method of protecting this setup be?
...and no, I won't give you the url :)
ASP.NET Session itself is token based security and yes you can easily implement that by doing
[WebMethod(true)]
and yes, any web method requires login to be done first, it should call User.IsAuthenticated, that verifies the session token.
You can easily implement form authentication (let web.config empty, you can use FormsAuthentication in code).
for example,
[WebMethod(true)]
public string DoLogin(
string username,
string password)
{
//.. do your verification
FormsAuthentication.SetAuthCookie(username,false);
return "Login Sucessful";
}
[WebMethod(true)]
public string ChangePassword(
string oldPass,
string newPass)
{
// verify user is logged on or not..
if(!User.IsAuthenticated)
return "Please Login";
// The code below is secure, only
// authenticated user will go through below
// change pass...
return "Password Changed Successfully.";
}
We developed many Flex+ASP.NET sites, we did exactly same thing, but instead of return "string" we usually return a class like following...
public class WSResult<T>{
public bool Successful;
public string Message;
public T Result;
public T[] Results;
}
The convention is simple, if method was successful then you return Success = true, and depending upon whether you want to return an array of items or just single item, you can return either Results or Result. In case if there has been any error or unathorized access you can set Successful=false and set Message as detailed string. As per following example.
[WebMethod(true)]
public WSResult<BusinessUser> DoLogin(
string username,
string password)
{
try{
BusinessUser user = BusinessUser.GetByUsername(username);
if(user==null)
throw new Exception("User not found");
if(user.Password != password)
throw new Exception("Password did not match");
return new WSResult<BusinessUser>{ Result=user };
}catch(Exception ex)
{
// this will even catch any DAL exceptions or any system error as well
// Log Exception... somewhere for tracking...
return new WSResult<BusinessUser>{ Successful=false, Message = ex.Message };
}
}
Unfortunately, I know diddly squat about flex, but I think I can help anyway. I think you have two reasonably good options.
First though, we need to clarify something... Are you saying the server doesn't do any authorization? Does it at least have the ability to authenticate a user? Do you have any control over the server code? If not, I don't think the following suggestions will help. I'm not sure how you're supposed to secure a server with just client side code. Maybe there is a way, but I can't think of it.
1) Use HTTP digest authentication. This requires that the server is configured to understand it and that there is support in the flex api for adding the appropriate auth header to the HTTP request. The server authenticates the user by his password and can check what operations can be performed by said user against some authorization mechanism.
2) Follow the guidelines in this article to implement the authentication scheme that many atom publishing endpoints use. The flex api will have to provide some support for this, maybe there is an existing third party lib though. If you can get access to the HTTP headers you should be able to implement the rest.
Good luck.
How are you commuicating with the server SOAP. REST etc?
If it is SOAP have a look at the answer to this question
General Password Security && Implementation in Actionscript 3
and here's a link how to add the header to the SOAP message
How to add a "flat" message header to a flex web service call?
Hope this helps
Jon

Resources