Using MVC when registering a new user a record gets created in webpages_Membership and UserProfile
The UserId by default gets created as sequential number 1, 2, 3...
my model
public class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
}
When I go to edit the record in the URL it shows /profile/1
I want to change the id's value to something random e.g. profile/f8934hre987f8987f9f8 for security reasons.
Same thing I want to generate random number when details gets viewed by members so instead
/details/1 want it to be /details/783787483743874873
The ViewModel for displaying the details contains Id field as a primary key which is also gets generated sequentially.
I read using [GUID] is not great for performance.
Advice how to change it without affecting the performance? Suggestions. Thank you.
EDIT
Have similar like groupon site, when user attempts to edit his/her profile instead of showing /edit/1 have something like:
So user doesnt know how many records in the database or what record number the user is.
I am not 100% sure what you mean by something random. I am assuming that you mean encryption. Please take a look at this MSDN link for the details on encryption.
After that ,you can have your action method like /detail/{encrypteduserId}
Then you can have action method like below
public class Detail(string id)
{
var decryptedUserId = GetDecryptedId(id);
// GetDecryptedId gives the decrypted information.
// You can implement it based on the MSDN link
// You can use decryptedUserId to run queries on the database.
}
This way you can achieve your goals without making schema changes. This seems like a minimum possible friction approach.
There is no security benefit to having a random user id, so long as your site implements proper controlled access. That is, nobody should be able to access /profile/1 except the user with a user id of 1 (or another user who is authorized to do so, such as an administrator). All other users should get an error.
An even better approach is to not use an id at all. Simply get the current users ID and show the profile of the currently logged in user. Then user with userid 1 just goes to /profile and they see their profile, and user with an id of 2 goes to /profile and they see their profile and there is no way for one user to see the others.
That's not always possible however, for instance in maintenance screens where an admin is viewing other users profiles, but in that case only the authorized admin should be able to do that.
Obscuring the userid is a false sense of security, since the id will be visible anyways. You are simply fooling yourself if you think this adds any security value, unless you haven't implement proper security in the first place, in which case it's just hiding your real problem.
It also adds needless complexity, and confusion. It's equivalent to saying "I want to change the address of my house to a random number for security reasons". Think of all the problems that would cause, for dubious results.
Having the User ID displayed in the URL is a genuine security concern, be it a simple integer user id or some GUID (if that GUID can be used to identify a user). This is especially true in cases of Transport layer security (HTTPS) where the URL is not encrypted like the content is.
Here are a couple of ways I can think of going around this:-
1.) As suggested by Erik above, use User.Identity.Name to identify the currently logged in user. This wouldn't however work for the administrator accessing another member's profile. It would also not work for unauthenticated scenarios.
2.) Instead of creating a direct hyperlink, create a form which posts the user id as part of a custom type (model). Then use model binding to access the User ID as a property of the custom model object in the Action method. In this case, the user ID is submitted as part of the form and hence is transported over the wire encrypted (if HTTPS) and not visible in the URL. This would work in both cases where a member is trying to access his/her own profile, or when an administrator chooses a profile to access on screen.
An example of scenario 2::
public ActionResult EditProfile(UserProfile userProfile)
{
bool success = false;
if (User.Identity.IsAuthenticated)
{
if (ModelState.IsValid)
{
if (WebSecurity.UserExists(userProfile.UserName))
{
// your code to update profile here.
}
}
}
if (success)
{
ViewBag.Message = "Profile updated successfully.";
}
else
{
ViewBag.Message = "Profile not updated:";
}
return View();
}
Related
<authentication mode="Forms"/>
<forms loginUrl="~/Login/Login" defaultUrl="~/Login/Something" protection="All"></forms>
</authentication>
One way is to add Authorization tag to every Controller to secure application from unauthorized user.Other way is to use session variables to store user information .So,my question is from hacking perspective,how we can secure our application form hackers?Is there any other way to secure application?
Note: This answer should not be viewed as complete in any way, security is always hard and if it's important to you - always consult with a third party security and penetration testing company. This is just a few things you should consider to make your MVC application safer (not necessarily safe).
Protect controllers
First step is to apply [Authorize] to your controllers, to make sure there is some sort of valid authentication before accessing a method. Preferably add Authorize to all controllers and make exceptions with [AllowAnonymous] to make it secure-by-default.
Authorize the user
Even though you've added [Authorize] to the controller, that only means that the user is logged in, not that the user should have access to whatever method is being accessed. The first step is to extend the attribute by specifying a set of roles for the method: [Authorize(Roles = "Administrator"]
Depending on the application, you might also have to check that the current user belongs to the company/group or whatever that is being edited, to prevent someone from modifying data that doesn't belong to them.
Don't leak data into models
If you're using your actual data models as view models, you are at risk of allowing the user to enter more data than they're supposed to. Consider this example:
class Employee {
public int Id { get; set; }
public string Name { get; set; }
public int Salary { get; set; }
}
Assume that we for some reason allow our employees to change their name, and we use the Employee model for that. But of course we only make an edit field for the Name, and not the Salary as that would be stupid :D. However, due to how the model-binding works, a smart Employee could just add <input type="text" name="Salary" value="2147483647"> to the form when changing their name, and our gullible db.Entry(employee).State = EntityState.Added; followed by db.SaveChanges() would update their salary as well.
Solution? Either make a view model with only the Id and Name property, to make it impossible to change the salary, or use the Bind attribute to only include the properties we allow: public IActionResult Update([Bind(Include="Id,Name")]Employee model).
XSS
A very important part is to protect your users from bad dynamic content. If I can enter HTML and Javascript that's displayed to some other user, I can abuse that to steal their authentication token for example. Making to never render user-entered data as HTML is a first step to prevent this. You should also make sure to always use the anti-forgery token in your forms as well. Adding CSP headers is a good practice to prevent someone from injecting scripts that shouldn't be there.
I have a Grails application using Spring Security.
This application is basically a content management system, so it is a CRUD.
My URL's access are basically formatted as follows:
/$controller/$action/$id
This is where encounters problems. That occurs in a controller, for example, to change a user I have the following URL:
/user/update/1
And into the controller I have the following code:
def update(Long id) {
def user = User.get(id);
[user: user]
}
That's the problem. If the user change the (id) directly without checking if the user id in request is correct, anyone can surf the users of my system. Now i have a big problem.
The solution that I thought would be to create a unique hash for each registration system, which would hinder the user to understand that, for example, the ID 1 has the hash 123aabbCCDD, for example.
But i have a lot of registers and many domains in the system, and i don't know if this is the best solution.
I need help to know, for example, using the spring security, I can do this kind of thing.
I tried to find solutions to the issue but I'm not sure by what words to search, so if there is already a question like mine, put the link in comments please.
Thanks.
As Joshua points out, if this is a general problem where you need to limit which users (or which roles) can perform particular actions, the spring-security-acl plugin will help. But that can be tedious to work with because you typically need to model things in a fine-grained way, and you end up with a lot of ACL data in the db.
But if you only want to restrict users to being able to edit themselves, just don't pass the user id. You already know who the user is if the action requires authentication. If that's the case, change the action to something like
def springSecurityService
def update() {
[user: springSecurityService.currentUser]
}
A related workflow that can often avoid using ACLs is allowing a user to edit something that they own, e.g. a CreditCard. Assuming you have static hasMany = [creditCards: CreditCard] in the User class and static belongsTo = [user: User] (or just User user), then you can allow the form to send the credit card id, but you just need to use a modified query, e.g.
def springSecurityService
def update(Long id) {
def user = springSecurityService.currentUser
def card = CreditCard.findByIdAndUser(id, user)
[creditCard: card]
}
The final SQL query will look something like select ... from credit_card where id=? and user_id=?, which has a big security advantage over the SQL for a get() call which would be select ... from credit_card where id=?. A malicious user can still try to send any id they want, but since the where clause checks both the id and the user foreign key, if they're not logged in as the card owner, the finder will return null and you can treat that as a mistake or a hack and not allow access.
Note that the hash approach you described isn't very secure - it's just "security by obscurity". If each user's hash is constant, it's not difficult to find out what a user's hash is and forge a request (e.g. a coworker can just look at another's monitor and see the url in their browser).
In asp.net mvc when creating, updating, deleting data how does one know that the data beeing manipulated does really belong to the user making the call?
[Authorize]
[HttpPost]
public ActionResult Edit(Model model)
{
// edit data in database
}
If a user is only to manipulate his own data but can see and easily find out information of other users witch is public to manipulate.
How can i be sure that the user is really who he says when for example Edit is called?
The Authorize only makes sure that a user has logged in.
I'm thinking about using controller.User.Identity.Name in the update to make sure the user how created the data is the one that changes it.
But then comes the question could it be possible for a user to go around this by manipulating controller.User.Identity.Name ?
How can one know that a user is who he says he is with regard to this?
There are two kinds of authorization.
One, which is very "vertical", has helpers provided by the framework (such as the Authorize attribute). This "vertical authorization" determines if a user is allowed to make a request or perform an action. It knows nothing of the data of the request or the action being performed, just the request/action itself.
The second, which is more "horizontal", doesn't have built-in helpers in the framework because it's subjective based on the business logic of your application. This one is up to you. This "horizontal authorization" determines if a user is permitted to manipulate specific data elements (specific records in the data) under specific conditions.
To put it simply... If a user submits a request to your application (invoking an edit action on a record for example) then while the framework can tell you if that user is permitted to invoke that action you need to manually determine if that user is permitted to edit that specific data.
For example, let's say two users create records in a table. In that table there should be a column indicating the user which created that record. (Username, some identifier, however you want to link it to a user.) This value isn't provided by the user when inserting the data, it's provided by your code when you build the record. You'd probably pull this value from the logged-in identity of the user (however you track username/id in the application).
Later, when a user attempts to edit a record in that table, you would need to validate that the user performing the action (again, based on their logged-in identity) is the user who originally wrote that record (based on the data that's in the table). Or an admin, or in some other way authorized to manage that data based on your business logic. None of this is based on values being sent from the client, it's all entirely server-side.
So while the client-side code may store an identifier for the record being edited, that value can be changed by any savvy user. That value isn't to be trusted. If a user requests a page, edits values, and submits that page then your server-side code would use the page-provided identifier to know which record the user is attempting to edit, but would use the logged-in user identity to determine if the user is allowed to edit that record. In the event that the user has manipulated the form values to edit somebody else's record, the server-side code should just respond with an error or friendly message denying that action.
This is a loaded question. You could do this with roles (if only Admins can edit). You can do this via user IDs (if you only want them to edit their own personal data).
It seems your question on more based on personal user data so lets go that route.
[Authorize]
[HttpPost]
public ActionResult Edit(Model model)
{
var userId = WebSecurity.CurrentUserId;
var previousRecdord = //Logic or service call to get previous record
if (previousRecord.AUthorId != userId)
{
//Do Something
}
else
{
//Edit something
}
}
You could even throw all of this into a service method and have a validate method that is called before the actions on the service are run. something like
[Authorize]
[HttpPost]
public ActionResult Edit(Model model)
{
var userId = WebSecurity.CurrentUserId;
var profileEntity = //some mapper that maps profile to entity
_UserService.EditUserProfile(userId, profileEntity)
}
and then in some service method:
public void EditUserProfile(int userId, profileEntity profile)
{
validateProfile(userId, profile);
saveProfile(profile);
}
private void validateProfile(int userId, profileEntity profile)
{
var previousRecdord = //Logic or service call to get previous record
if (previousRecord.AUthorId != userId)
{
//throw exp of some sort
}
}
I am looking to create a new Web App that will allow the user to first enter the users id then navigate around the site based on that user's id. So, first the user would search for an ID, select that user and have options available based on that ID.
Currently I am using the Query string to store the ID, so... /AddProduct/2222.
This works fine but I'm not too sure about the security aspects. I've thought about sessions and cookies but I don't think they are suitable for this scenario. Or do I encrypt the ID for the query string?
Does anyone have any thoughts?
Thanks
Edit
I forgot to mention, the users will be authenticated and have specific permissions on each page on the site. The data is also stored in a database. So, the site will be querying and editing/adding to current data.
So basically here you seem to be afraid that some user might modify an item belonging to another user. Alright, this sentence tells us already that you have users and items in your application and that there are some roles associated to those items. And you have a mechanism to identify those users. So you are probably using some sort of authentication such as the built-in FormsAuthentication for example. So now the question becomes: how to ensure that the currently authenticated user is not modifying the product that belongs to another user.
OK, so you have items that belong to users. I suppose that this information is stored somewhere on the server, presumably a database or something. One approach I would recommend you is to write a custom authorization attribute which would check if the requested resource id actually belongs to the currently authenticated user.
For example:
public class MyAuthorizeAttribute : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
var isAuthorized = base.AuthorizeCore(httpContext);
if (!isAuthorized)
{
// The user is not authenticated or authorized => no need to continue further
return false;
}
// At this stage we know that the user is authorized => we can fetch
// the username
string username = httpContext.User.Identity.Name;
// Now let's fetch the id of the resource he is trying to manipulate from the request
string id = httpContext.Request["id"];
// All that's left is to verify if the current user is the owner
// of the account
return IsOwnerOfItem(username, id);
}
private bool IsOwnerOfItem(string username, string id)
{
// TODO: query the backend to perform the necessary verifications
// about whether the user has permissions to work with the resource
// pointed by the id parameter
throw new NotImplementedException();
}
}
and now all that's left is to decorate your AddProduct controller action with this custom attribute:
[MyAuthorize]
public ActionResult AddProduct(int id)
{
// if we get that far we know that the currently authenticated user
// is the owner of the resource pointed by the id parameter and we
// could proceed respectively
...
}
With this approach you don't need to be using any sessions or encrypting anything. The encryption is already built into the ASP.NET framework under the form of a Forms Authentication cookie which holds the currently authenticated username in a secure manner. This cookie cannot be manipulated -> the user cannot impersonate as another user. So once you've got the guarantee about who the current user is, all that's left to you is to perform the necessary authorization whether he can access the requested resource.
SITUATION:
I have a Model and based on a users Role I want to allow the user to only update certain parts of the model. Lets say the Model has three fields. (My Model is obviously more complex than this)
MyObject
Field1
Field2
Field3
My View looks something like this:
Html.TextBoxFor(#Model.Field1)
Html.TextBoxFor(#Model.Field2)
#if(UserIsAdmin())
Html.TextBoxFor(#Model.Field3)
else
#Model.Field3
Bearing with me on the syntax (and the poor design of the example), you can see what I'm trying to do. Upon the user posting the form my controller would just take the MyObject and save it back to the database, we are using EF.
QUESTION:
My question is, is there a way to stop a user from forging a POST to be able to save data he/she should not be able to. My current idea would be to do a check in the controller to see if the user modified values he should not have. Or I could save fields individually, but neither is a convient solution.
Is there a better one?
Thanks!
Additional Info:
Not sure if this artical is relevant at all: http://blog.stevensanderson.com/2008/09/01/prevent-cross-site-request-forgery-csrf-using-aspnet-mvcs-antiforgerytoken-helper/
All three fields are from the same database table and I'm using EF to get and save the entity.
You want to make sure the user is only able to update permitted fields.
You decided that the way to achieve this is to prevent the user "forging" a response using e.g. firebug, or F12 developer tools, or GreaseMonkey, and have asked how to do this.
But the correct/best method is to check which fields the user is attempting to update, and only update those which he is permitted to update. Then it doesn't matter if they forge the request or not, they still won't be able to access anything they shouldn't. In other words, check access rights at the point of access.
Anti-forgery tokens are there to solve a separate problem, namely XSRF.
Use a viewmodel that accepts only the fields that should be updated and then populate the model with those values. You could use something like AutoMapper for mapping between the two.
My current idea would be to do a check in the controller to see if the user modified values he should not have. Or I could save fields individually, but neither is a convient solution.
You're on the right track with that idea. A typical Add() operation would look like this:
public class FooController : Controller
{
public ActionResult Add(FooViewModel viewModel)
{
if (ModelState.IsValid)
{
FooDataModel dataModel = FooMapper.MapToDataModel(viewModel, User);
FooRepository.Add(dataModel);
}
}
}
Like #VimalStan said, your FooViewModel is then a model that contains only the fields you want to let the user update. Also this still doesn't solve your problem, which should be done in your mapper (in this case FooMapper) and still check every field as #Ben suggested:
public static class FooMapper
{
public static FooDataModel Map(FooViewModel viewModel, IPrincipal user)
{
var dataModel = new FooDataModel();
dataModel.Field1 = viewModel.Field1;
dataModel.Field2 = viewModel.Field2;
if (IsAllowedToUpdateField3(user))
{
dataModel.Field3 = viewModel.Field3;
}
return dataModel;
}
public static bool IsAllowedToUpdateField3(IPrincipal user)
{
return false; // your logic
}
}