Consider an ASP.NET MVC application using the Salt parameter in the [ValidateAntiForgeryToken] directive.
The scenario is such that the app will be used by many customers. It's not terribly desirable to have the Salt known at compile time.
The current strategy is to locate the Salt value in the web.config.
[ValidateAntiForgeryToken(Salt = Config.AppSalt)]
//Config.AppSalt is a static property that reads the web.config.
This leads to a compile-time exception suggesting that the Salt must be a const at compile time.
An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type
How can I modify the application to allow for a runtime loading of the Salt so that the app doesn't have to be re-salted and recompiled for each customer?
Consider that the Salt won't change frequently, if at all, thereby removing the possibility of invalidating form
The Salt property is meant to be a compile-time constant. It's simply a way to link a particular form to a particular action method. For example, if you have a login form, you may wish to use the salt "Login" for this form so that a token that was valid for the login form can't be used for the change password form, etc.
In all cases, the app's machine key is automatically used as an additional salt value. So an anti-XSRF token for one application can't be used for another application, even if both salt values read "Login". The machine key is settable in the Web.config <machineKey> section.
I had the requirement to have different salts for different customers. In this case, I used Dixin's solution for injecting the salt at runtime.
Anti Forgery Request Recipes For ASP.NET MVC and AJAX at the section titled "Specify non-constant salt in runtime".
Decorate your Controllers with a new attribute:
[ValidateAntiForgeryTokenWrapper(HttpVerbs.Post)]
public class ProductController : Controller
{
// Only HTTP POST requests are validated.
}
This new attribute is defined as:
public class ValidateAntiForgeryTokenWrapperAttribute : FilterAttribute, IAuthorizationFilter
{
public ValidateAntiForgeryTokenWrapperAttribute(HttpVerbs verbs)
{
this._verbs = new AcceptVerbsAttribute(verbs);
this._validator = new ValidateAntiForgeryTokenAttribute()
{
//load from web.config or anywhere else
Salt = Configurations.AntiForgeryTokenSalt
};
}
// Other members.
}
Related
We have an ASP.NET MVC4 web application and in our QA environment we set up different "sites" as WebApplications on the same website, e.g.
www.mysite.co.uk/WebApp1
www.mysite.co.uk/WebApp2
www.mysite.co.uk/WebApp3
For all our cookies, we ensure that the cookie key contains an ID that ties that cookie to the specific Web Application, so there's no cross contamination.
Now this all works perfectly well the vast majority of the time. However, very occasionally in our DEV environment, we find that the GUEST shopper (not authenticated) can access a controller's Action method that is marked with the [Authorize] attribute.
My guess here is that the browser has been used with multiple TABS, each one pointing to a different Web Application, and occasionally the browser/server is getting confused over which ASPXAUTH cookie to use, and is using one from a different Web Application for a shopper who has authenticated. As I said, that's only a guess, but by debugging the site we're definitely hitting a break-point in the code that's supposedly protected with this Attribute.
It's not clear at this point how I may prevent this behaviour.
Thanks
Griff
For all our cookies, we ensure that the cookie key contains an ID that ties that cookie to the specific Web Application, so there's no cross contamination
You are storing the ID within custom cookies, but it appears you are not storing this within the auth cookie that ASP.NET uses to grant access to code marked with the [Authorize] attribute.
You can either add the ID to the encrypted token that gets stored inside the auth cookie and check this per request, or you could encrypt the token with a different key per site.
Fortunately the FormsAuthenticationTicket constructor includes a userdata parameter that can be used for custom data.
public FormsAuthenticationTicket(
int version,
string name,
DateTime issueDate,
DateTime expiration,
bool isPersistent,
string userData
)
You can follow this guide in order to easily store multiple pieces of information using the JSON format like so:-
public static class HttpResponseBaseExtensions
{
public static int SetAuthCookie<T>(this HttpResponseBase responseBase, string name, bool rememberMe, T userData)
{
/// In order to pickup the settings from config, we create a default cookie and use its values to create a
/// new one.
var cookie = FormsAuthentication.GetAuthCookie(name, rememberMe);
var ticket = FormsAuthentication.Decrypt(cookie.Value);
var newTicket = new FormsAuthenticationTicket(ticket.Version, ticket.Name, ticket.IssueDate, ticket.Expiration,
ticket.IsPersistent, userData.ToJson(), ticket.CookiePath);
var encTicket = FormsAuthentication.Encrypt(newTicket);
/// Use existing cookie. Could create new one but would have to copy settings over...
cookie.Value = encTicket;
responseBase.Cookies.Add(cookie);
return encTicket.Length;
}
}
You should also have a custom name for this cookie per site so they can co-exist within your DEV environment.
I'm using the Data Annotation validation extensively in ASP.NET MVC 2. This new feature has been a huge time saver, as I'm now able to define both client-side validation and server-side validation in one place. However, while I was doing some detailed testing, I realized that it's quite easy for someone to bypass the server-side validation if I relied on Data Annotation validation alone. For example, if I defined a required field by annotating the property with the [Required] attribute and placed a textbox for that required field in a form, a user could simply remove the textbox from the DOM (which can easily be done through Firebug) and now the Data Annotation validation will not be triggered on that property during ModelBinding inside of a Controller. To ensure that the "required" validation is triggered, I can repeat the validation after ModelBinding happens, but then I'd be repeating my validation logic.
What is everyone's recommendation on validation? Is Data Annotation validation enough? Or does the validation need to be repeated to ensure that validations get triggered in all situations?
Follow-up comment:
Based on the answers below, it seems that I can't rely on the Model Binder and Data Annotation validation alone. Since we're concluding that additional server-side validation is required, is there an easy way for my Service layer to trigger validation based on what's been defined in the Data Annotations? It seems that this will get us the best of both words...we won't need to repeat the validation code, but we'll still ensure that the validation gets executed even if Model Binder doesn't trigger it.
I'm going to post this follow-up comment as a separate question, as it poses a different question than the original one.
I think to be vigilant concerning security you should choose to you make server validation the priority and ensure that this is always your fallback. Your server validation should work without the client validation. Client validation is more for UX and tho that is paramount to your design, it is secondary to security. With this in mind you will find yourself repeating your validation. A goal is often trying to design your app so that the server and client validation can be integrated as much as possible to reduce the work required to validate on the server and the client. But be assured you must do both.
If bypassing the client validation (by means of DOM manipulation) is avoiding the server validation (which it seems you are indicating) then your server validation for this instance may not be employed appropriately. You should be invoking your server validation again in your controller action or in a service layer. The scenario you describe should not be defeating your server validation.
With the scenario you describe, the DataAnnotation attributes method should be sufficient. It seems that you simply need to make a few code changes to ensure that your server validation is invoked also when submitting the form.
I paired xVal with DataAnnotations and have written my own Action filter that checks any Entity type parameters for validation purposes. So if some field is missing in the postback, this validator will fill ModelState dictionary hence having model invalid.
Prerequisites:
my entity/model objects all implement IObjectValidator interface which declares Validate() method.
my attribute class is called ValidateBusinessObjectAttribute
xVal validation library
Action filter code:
public void OnActionExecuting(ActionExecutingContext filterContext)
{
IEnumerable<KeyValuePair<string, object>> parameters = filterContext.ActionParameters.Where<KeyValuePair<string, object>>(p => p.Value.GetType().Equals(this.ObjectType ?? p.Value.GetType()) && p.Value is IObjectValidator);
foreach (KeyValuePair<string, object> param in parameters)
{
object value;
if ((value = param.Value) != null)
{
IEnumerable<ErrorInfo> errors = ((IObjectValidator)value).Validate();
if (errors.Any())
{
new RulesException(errors).AddModelStateErrors(filterContext.Controller.ViewData.ModelState, param.Key);
}
}
}
}
My controller action is defined like this then:
[ValidateBusinessObject]
public ActionResult Register(User user, Company company, RegistrationData registrationData)
{
if (!this.ModelState.IsValid)
{
return View();
}
...
}
The DataAnnotation is certainly not enough. I use it extensively also to pre-validate my calls to the domain model to get better error reporting and fail as early as possible.
You can however tweak the DataAnnotation Model yourself to ensure properties with [Required] MUST be posted. (will follow up with code later today).
UPDATE
Get the source for DataAnnotations Model Binder and find this line in DataAnnotationsModelBinder.cs
// Only bind properties that are part of the request
if (bindingContext.ValueProvider.DoesAnyKeyHavePrefix(fullPropertyKey)) {
Change it to
// Only bind properties that are part of the request
bool contextHasKey = bindingContext.ValueProvider.DoesAnyKeyHavePrefix(fullPropertyKey);
bool isRequired = GetValidationAttributes(propertyDescriptor).OfType<RequiredAttribute>().Count() > 0;
if (contextHasKey || (!contextHasKey && isRequired)) {
I wrote my own ValidationService for MVC 1.0 by copying patterns from both xVal's DataAnnotationsRuleProvider and Microsoft's DataAnnotationsModelBinder (and Martijn's comments). The service interface is below:
public interface IValidationService
{
void Validate(object instance);
IEnumerable<ErrorInfo> GetErrors(object instance);
}
public abstract class BaseValidationService : IValidationService
{
public void Validate(object instance)
{
var errors = GetErrors(instance);
if (errors.Any())
throw new RulesException(errors);
}
public abstract IEnumerable<ErrorInfo> GetErrors(object instance);
}
The service is a validation runner that walks the property tree of the object instance it receives and actually executes the validation attributes that it finds on each property, building a list of ErrorInfo objects when attributes are not valid. (I'd post the whole source but it was written for a client and I don't know yet if I'm authorized to do so.)
You can then have your controllers, business logic services explicitly invoke validation when you are ready, rather than relying exclusively on the model binder for validation.
There are a couple of other pitfalls that you should be aware of:
The default DataTypeAttribute in data
annotations doesn't actually do any
data type validation, so you'll need
to write a new attribute that
actually uses xVal regular
expressions (or something else) to
perform server-side data type
validation.
xVal doesn't walk
properties to create client-side
validation, so you may want to make
some changes there to get more robust
client-side validation.
If I am allowed and have time, I will try to make more source available...
See codeProject Server-side Input Validation using Data Annotations
Input validation can be done automatically on the client side in
ASP.NET MVC or explicitly validating the model against the rules. This
tip will describe how it can be done manually on the server-side of an
ASP.NET applications or within the repository code of WPF
applications.
// Use the ValidationContext to validate the Product model against the product data annotations
// before saving it to the database
var validationContext = new ValidationContext(productViewModel, serviceProvider: null, items:null);
var validationResults = new List<ValidationResult>();
var isValid = Validator.TryValidateObject(productViewModel, validationContext,validationResults, true);
Let's suppose I don't want to use Membership and want to restrict user's access with ActionFilter.
I know I can create a filter/attribute and override the OnActionExecuting method and further I can put this attribute in a ActionResult.
And let's assume that I have a table named 'tbUsers', it has also an int field named 'certificate' and depending on this 'certificate' value, an user can access an ActionResult or not.
But, how can I, in a OnActionExecuting mehod, check this user's 'certificate' value and grant his access or redirect to a 'NotAllowed.aspx' page?
Thanks!!!
I would not do it this way. I would implement an IAuthorizationFilter. Authorization filters run before all action filters.
For example, suppose you later put an OutputCache attribute on the action method and it happens to run before your authentication filter. That would be bad! If the content is cached, the authentication filter would never run and people would see cached sensitive data.
The ActionExecutingContext has the HttpContext which would include the current User object. You can use this to get the User. You can also use it to access the Session if you wanted to store the information in the Session. You could also put it in an encrypted cookie and access those through the Request.Cookies on the context. You'd want to think about the security implications of that, though I don't see it as being more problematic than the auth cookie.
Checking it against the database and maintaining testability on your filter is a little more tricky. What I've done is to provide two constructors for each filter class. One provides a database factory that will create my data context. I use this in testing and supply a mock database factory that produces a mock or fake database. The normal, parameterless constructor calls the previous constructor with a null factory. When this happens the other constructor creates a new instance of the default factory.
private IDatabaseFactory Factory { get; set; }
public MyFilter( IDatabaseFactory factory )
{
this.Factory = factory ?? new DefaultDatabaseFactory();
}
public MyFilter() : this(null) { }
Where do I get information about the currently connected user? That is, how does shibboleth pass the information?
Can I set some restrictions on actions using [Authorize] attribute based on data acquired from shibboleth?
Shibboleth publishes user attributes associated with
sessions into HTTP request headers, based on header names defined
in Attribute Acceptance Policy (1.3.x) or Attribute Mapping (2.x)
files. These headers are transformed into CGI variables based
on mapping rules defined by the CGI specification.
You should be aware of this security advisory:
http://shibboleth.net/community/advisories/secadv_20090615.txt
I have never user shibboleth, but you can get information about the user from Controller.User property. It will return a generic principal of current thread. Using this principal you can check whether the user is authenticated and get a login name of the user. This is due to the reason that after logon an authentication cookie is set and this cookie contains limited amount of information. And on each request after logon only this cookie is checked (if it exists and valid - user is authenticated).
So if you need in some specific information you can manually load a user (it's better to use cache here) and check whatever you want.
Also you can create and attach your own principal with necessary information to the thread on start of a request (e.g. on start of a request load the user from db/cache using user name from base principal, create and set your own principal to thread). After this you can check all properties of the user you need.
Where would you attach your own principal? You say on the start of the request but what if you don't want every request authorizing?
You'll want to create a method in Global.asax.cs that has the following signature
protected void Application_PostAuthenticateRequest()
{
//Your code here.
}
This will be called automatically before almost anything else is done (MVC will call this method if it exists, you don't have to "turn it on" anywhere), and this is where you need to set the Principal. For instance, let's assume you have a header called RolesHeader that has a comma separated value of roles and another header called UserId that has (duh) the user ID.
Your code, without any error handling, might look something like:
protected void Application_PostAuthenticateRequest()
{
var rolesheader = Context.Request.Headers["RolesHeader"];
var userId = Context.Request.Headers["UserId"];
var roles = rolesheader.Split(',');
var principal = new GenericPrincipal(new GenericIdentity(userId), roles);
Context.User = principal;
}
It's the Principal/Identity that the [Authorize] attribute uses, so setting it here at the beginning of the request lifecycle means the [Authorize] attribute will work correctly.
The rest of this is optional, but I recommend it:
I like to create my own custom classes that implement IPrincipal and IIdentity instead of using the GenericPrincipal and GenericIdentity, so I can stuff more user information in it. My custom Principal and Identity objects then have much more rich information, such as branch numbers or email addresses or whatever.
Then, I create a Controller called BaseController that has the following
protected new CustomPrincipal User
{
get
{
return (base.User as CustomPrincipal) ?? CustomPrincipal.GetUnauthorizedPrincipal();
}
}
This allows me to access all my rich, custom Principal data instead of just what's defined in IPrincipal. All of my real controllers then inherit from BaseController instead of directly from Controller.
Obviously, when using a custom Principal like this, in the Application_PostAuthenticateRequest() method, you'd set the Context.User to be your CustomPrincipal instead of a GenericPrincipal.
I would love to be able to get some strongly typed way of knowing which action is executing.
To clarify im doing AOP where I only allow access to a given action if the user has rights for that action.
The problem with using a string for determining which rule to check for, is that if some developer renames an action, I wont get a compile error telling me that my rule is broken.
Any ideas??
Develop an attribute that performs your check. Apply the attribute, with any necessary options, to the actions that you want to protect. Write unit tests that check that the actions in question exist and are decorated with your attribute (with the proper options). In your attribute you needn't know what action is executing, just whether the current user passes the tests as configured by your attribute's options.
I have a couple of different attributes that I've derived from AuthorizeAttribute that do exactly this sort of thing.
public class RequiresEmailAttribute : AuthorizeAttribute
{
... implements the logic to test whether the current user
... has an email address and redirects to error view if no
... email address is found
}
[RequiresEmail]
public ActionResult SendEmail( string to )
{
....
}