Why would I need access control policies if I use encryption? - encryption

If encrypted data is stored on a server, and decryption key is disseminated to the legitimate users (through email), is there a need to implement access control policies?
What could be a possible scenario where I need both of them (if decryption key is only available to the legitimate users)?

Access control and authentication are two separate modes of security. Depending on your needs, you may need one or both.
Encrypting data on the server, and then disseminating the key, is arguably a form of authentication, since (at least in theory) knowing the key proves that you are a legitimate user.
Access control would be more along the lines of giving different levels of access to different users -- for instance, access to general documents for most users with a key and access to privileged data for a select few users.
Ultimately, you have to evaluate your needs and decide on which modes you require.

It depends on your security needs. Do you have any need to have levels of security?
If you just need to ensure that only legitimate users can access your site then you can just encrypt their username with the key, then have them use a password, so that they have to know something and they have something (two-factor authentication) and they can get into the site.

A term that applies here is the Princple of Least Privilege
An enterprise system will have a number of different roles that users or applications perform. In these cases, it's appropriate to stop actors in one role accidentally (or deliberately) intruding into the realm of another actor's role.
A simple analogy: I am an employee of a company. I am legitimate member of the company with a pass card who can get past the security desk to reach my workstation. However, I cannot access the company's bank account.
The vast majority of employees, even if they were given the bank account details, would do nothing inappropriate with the information. As the manager of this company, you could either trust the honesty of each and every employee, or you can go the far simpler route of recognising they have no need to access the account and keep them locked out. Then, if money starts disappearing, you have far fewer people to be suspicious of.

Audit and revocation.
Audit because you want to know if someone accessed data, not if they could do it because they had a key ( this is usually a requirement for say HIPPA/HITECH)
Revocation because re-distributing keys for the data may be impractical and depending on the underlying crypto scheme, revocation may be impossible.

Access control policies, surprisingly, flow directly from your needs to control access.
When one of legitimate user accounts becomes illegitimate for any number of reasons (user changed employment, violated terms of service, reported identity theft), then you have to control access to that account's data somehow.

Related

Is it safe to expose the UserId to a client?

I'm developing a web app and I'm wondering if exposing UserIds to the clients is potentially posing a security vulnerability. (By UserId I refer to the Id of an Identity user object created by the Identity Framework and used as a PK of the users table.)
To give some context or an example: in my app, I need to distinguish between content that is posted by the signed in user and the content that was posted by others. In a naive approach, I would just compare the UserId of the content to the UserId of the currently authenticated user. But that would mean that the client sees the Ids of all involved users.
My gut feeling tells me that this is not a good idea but I couldn't pinpoint to why. So, I wonder if there's a guideline around this question. Maybe it's just the general rule to reduce the surface of knowledge that is exposed to a minimum.
If this is the case, how should I proceed? Would hashing of the UserId help to solve the problem or are there better approaches around?
EDIT
The example I made is not the best because this problem can easily be solved on the back-end by comparing user IDs there and then sending the contents to the client already tagged as "mine" or "by others". But still, the general question remains.
If user IDs are themselves sensitive data,for example, your primary keys for some reason happen to be social security numbers, that'll definitely be a security and privacy liability. If your user IDs are just auto-increment numbers though, it should be fine.
It is always best to expose a unique identifier other than the primary key outside your system. It gives you more flexibility in resolving data mix-ups, dealing with data migration issues, and in otherwise future-proofing your system.
If UIDs are just identifiers for users. Knowing a user's UID does not grant you any permissions that are associated with that user. Sharing the UID in URLs is about as safe as sharing your username on Github, or your unique ID on Stack Overflow.
Stack Overflow displays user IDs in their URLs in order to make user profile lookups work: https://stackoverflow.com/users/10158551/xing-zou
Anyway, it is up to your design and you need to consider more than we could.
Refer to Should I expose a user ID to public?
I would put this in the low risk category. Exposing user ids does increase the risk surface as you have correctly identified.
For you application, it sounds like you require an identifier for the post and an indication of whether that post has been made by the user or by someone else.
You could structure that in the following way to avoid the low risk exposure:
GET /posts
{
"postId": "AJDIWC",
"isAuthor": true,
"content": "This is a post by the user."
},
{
"postId": "LISHWE",
"isAuthor": false,
"content": "This is a post by another user."
}
EDIT
To answer your question following the edit, yes, it is best practice to avoid exposing identifiers from other users unless the authorisation boundary allows it.
For example, there is no issue having an admin user of an RBAC protected application see the unique identifiers of users within their security boundary.
It's usually not a good idea to expose the user id at the client-side. If you need any information, username or a unique number is better than the exact user id in the database. This is generally not an issue if your application has protections against SQL injection attacks. But in case there is any vulnerability in loopholes, if anyone knows the user id for a user, they can inject SQL scripts for that user.
A better idea is to issue an access token to your clients with claims inside that. The access token will perform authentication for you on the server-side.

Security risk of passing a GUID via URL

I am after some advice regarding use of GUIDs from the security perspective. I have developed an ASP.Net application. It provides the user with access to some material, such as documents and photos, that aren't on the web server. These are stored on a file server. I have a 'GetResource.aspx' page which takes the ID of the resource, opens it using System.IO.FileInfo writes it to the response stream and returns it.
So, GetResource.aspx?id=123 would return, say, a picture that the user has access to. Of course, the user could manually enter the URL as GetResource.aspx?id=456 in which case the picture / document etc with that ID would be returned and it may not be one they have permission to access.
So clearly using an integer ID is not adequate. Would using a GUID as the ID provide enough 'randomness' that I could reliably assume the user could never manually enter "GetResource.aspx?guid={A guessed guid}" and ever expect to access a valid resource, including if using a script that made many random guesses per second?
Or, is there no substitute to determining the ID of the user from a Session variable, determining he does actually have access to the requested resource and only then returning it (Which as I write this I'm more and more convinced is the case!).
Thanks
There is certainly no substitute to authenticating the user and seeing if they are authorized to access the resource. What you are proposing here is a method of making it harder for a user to hit on a valid id for a document they are not authorized to view (either by mistake or on purpose).
A GUID is certainly large enough that you would never get "accidental" valid ids in practice. That makes a GUID without authorization checks a system that works great as long as noone is actively trying to break it. On the other hand, authorization checking is a system that would work great even in the presence of active attackers (of course this depends on what the attackers can manage to do).
You should choose between the two approaches depending on the nature of your application (is it public? are the users known and accountable for their actions? how bad would a "security breach" be?).
You should be determining if the user is authorised before blindly serving it if it is protected content.
The GUID does help to some extent, it makes guessing URLs harder, so I'd still recommend using them. But URLs can still be shared (even accidentally). If you are just going to serve up the content anyway regardless of who makes the request then it is of little real protection.
If you think that content is restricted one and having some personal data then you should go with username and password thing.

How to detect the misuse of a valid password

I'm starting to size up a project where I feel security needs strike a little closer to home. What tools and techniques could I look at to attempt to raise an alarm when a valid login is used, but the owner of the login has given it away or had it stolen. I would prefer ASP.NET, then MVC 3, oriented stuff.
This is not a silver bullet, but perhaps you should consider employing some kind of two-factor authentication. For example: when a user creates an account with you, you require that she provide you with a phone number where she can receive text messages as part of the registration process. Then, when she attempts to log in, you text her a temporary authentication code to be used in combination with her username and password.
This ads an extra layer of security to the system, because an attacker would have to both know her username and password and have physical access to her cell phone in order to compromise her account.
I hope that's helpful.
Seems like you would get a lot of false positives... but you might try checking what IP address the login is coming from. Most people will log in from the same IP address most of the time, so when that changes, it's at least a warning sign. If you want to be very strict about security, you could maintain a whitelist (for each account) and require that they get their IP address added to the whitelist before logging in.
My bank (Chase) does this by checking a secure cookie during my username/password login. If the cookie is missing or corrupted, they require a second form of authentication, which is either a code sent via text to my phone number on file or via email to my email address on file. Once the second form of authentication is complete, they set the secure cookie and then I can login from that browser with only username and password.
Implement your own Membership provider and add field locked to model,
check for user being locked on login and do some actions
It might be useful to think of the factors of the Authentication process, so that you can be sure that you are sufficiently covering things. You can easily get ridiculous with the layers of assurances, but I happen to find that most banks now have a variation on a simple model. All of this is, of course, over SSL
User submits account name. Additionally, you can require a secondary piece of information, last 4 of account number or year part of date of birth.
Optional, but a good idea: present the user with a counter sign, that is something that verifies the identity of the server. The user selects this at registration and should be looking for this every time they attempt to log in. This aids in preventing phishing.
System checks to see if the current system using IP lookup or cookie is associated with the account. If not, presents challenge question along with password input. Otherwise, presents just the password input.
Complicated, but can actually be done in 2 pages and more secure than is usually required.
I've presented this workflow to a few bank clients and they usually remove one or two of the checks for a balance of user friendliness.
With phones with text capabilities being so common, the idea of SMS verification code as mentioned by others is also a good idea, though I haven't implemented this in a system yet, personally.

ASP.NET User Profile vs using Cookies

I think, in almost all cases user preference data may be stored in a cookie with (almost) equally good results as when the User Profile API is used. Disadvantages of using cookies (for authenticated users) seem to be that a cookie can be deleted or time-out, in which case the user preference data will be lost. For anonymous users, if the preferences data needs to be persisted across sessions then a cookie will have to be used even when User Profiles are used.
So what are some of the biggest advantages/disadvanges of using either User Profiles or cookies for storing user preferences?
One of the benefits of registering on a site is that it remembers my preferences - if you're storing that information in a cookie on my machine instead of on your server then when I log into your site from another computer, I've got to set all my preferences up again - from a usability point of view, this is fairly bad.
For an anonymous user, storing the prefs in a cookie may seem fairly sensible - you don't know who they are, or whether they will comeback, and as you state, you can't work out from one session to the next who they are - however you'd probably be better off storing some sort of token in the cookie and mapping that to a preferences store on the server.
Also, I've noticed different browsers have different implementations for cookies - for example IE can now receive 50 cookies from one domain (up from the original 20), but it is still limited to a total of 4096 bytes for the entire cookie collection (and previous) - other browsers will support 4KB per cookie, rather than per domain.
Another disadvantage to holding all the preference data in cookies is that all of that data will have to be sent in every request from the client and in any response from the server whenever a change to the data is made. Whilst this may seem like a minor point in the age of broadband it is still an additional overhead. Using the Profiles API meands that the data is held at the server and only a session identification cookie needs to be sent by the browser.
Also, as you stated, for anonymous users if cookies are deleted then the user preferences held in the Profiles DB will no longer be accessible. However this will not be the case with registered users of your website. If they remove their cookies the server will still be able to retrieve their user preferences the next time they log in.
Cookies are limited in maximum length and they are using an implementation beyond of your control (after all, they are a feature of your visitors browser). Personally, I dislike relying on unknown third-party implementations I don't have any control over and if I have to, I'm trying to use it in the simplest way possible.
So from where I'm coming from, I would always store the user data on the server and just pass around a cookie pointing to that information.
Aside of not trusting the browser with a potentially big chunk of data (which may be lost, incorrectly stored or not stored at all depending on not only the browser but also, say, some antivirus application or whatever), this has various other advantages:
You are hiding your implementation from the user: If you store the data in the cookie, it's visible for anybody and can be analyzed or modified at will. This can even lead to users changing cookies to there liking and thus force you into keeping stuff around you probably want to get rid of just because some users are depending on your particular implementation at any time.
As cookies are stored in plain text, on shared machines, everybody can no longer easily see all the settings the previous user made, nor change them at will.
But the most important point remains the disconnect from not-quite-working browser implementations (just storing small tokens is the common, tested use-case)
Don't forget that one of the biggest disadvantages of using cookies is that they can be copied, so its dangerous to store authentication info on them.
I'm not familiar with User Profile API but I'm guessing it stores the information on the server(?). If thats the case then you could have a problem if you have to many users.
Overall maybe the best solution is to use User Profile if it guarantees the persistence of the information.
Keep in mind that its possible to write a ProfileProvider that persists user data in a cookie, so you can have the best of both worlds if you determine the state you want to persist is appropriate for cookies (size, security, etc).
Actually, you do not need to persist preference data in cookies for anonymous users when using the ASP.NET Profile Provider. Simply store the current UserID (which is some horrible looking session-related string) in a cookie. This becomes the previous UserID on subsequent visits, and then you can just grab the old Profile information and migrate it to the current Profile, or even authenticate them as that old anonymous Profile.

Is it better to convert existing user accounts for them or have the users re-register?

I'm rewriting a website and going from a home-grown authentication model where users logged in with their account id (numbers) and password, to .NET FormsAuthentication where users will login with a username that they choose (or is available) and a stronger password. There are over 38K existing accounts and I'm trying to decide if the existing users should re-register or if I should write some code to do this on their behalf. I've already ruled out creating the usernames for the users because they won't be able to change their username. Luckily we don't have any users named Brenda Utthead.
If the user re-registers, some may gripe about having to do this step again and it may raise some support calls, but I stay with the standard process that everyone has to do. Or I can allow the user to login with their existing userid and password and then optionally give them a grace period to convert their account. I'm hesitant about the latter because it's special code and a possible threat vector because it bypasses the standard authentication mechanism and allows users to log in using less secure credentials.
This application currently accounts for about 40% of our website traffic and I'm not worried about users not coming back to the website because of the possibility of them having to re-register.
What does everyone think?
If you want your users to come back your best bet is to convert their accounts and send an email explaining the transition.
Do not make them re-register whatever you do.
You'll lose half of your users if you do that.
Give them a service so that they can enter their previous user id and have them provide their email address. Email them at the address provided and have them login with their email address as their new user name.
I am about to do the same thing. I am writing a migration page where the user logs in with his/her existing credentials and behind the scenes, I write out to the asp.net membership tables. Do a check first to make sure they haven't already migrated for all subsequent visits.
Don't make them re-register. A little work on your side is all it takes and you need to keep your customers happy.
After listening to everyone's suggestion, I've decided to modify the login. I look at the username they provide and try to guess that they're an existing user. Then I look them up in the old table and if I find a match take them to a conversion screen. There they can quickly convert their account or skip the whole process and login temporarily. The conversion form has fewer fields to fill out b/c I was able to authenticate them against the old user table so I don't need them to provide as much info.
I'm not thrilled with skipping the conversion but that option is only offered for the first 45 days from go-live.
Either convert them or find a way for both membership models to exist together, and somehow convert each user across at login or something.
Think about how long it took to get the 38k members and ask yourself if those were all wiped out, would those same people go through the hassle of signing up again. If you've got a really strong community you should be ok, the hit would just be a matter of time till you're built up.
The other thing you could do to mitigate the risk would be to send out a email, although spam blockers may filter them you could get to a high percentage of your users and tell them about the new membership stuff. Might get some older people back to the site as well in the process.
The biggest challenge is converting all the data that is associated with the user's accounts. People are going to be really upset if they've built up some sort of reputation that you're going to destroy with a new membership system.
This website is a check your balance type of website. It's not a banking site per se, but it exists as a convenience tool to users. I don't believe it would be realistic for users to cancel their accounts because they are forced to re-register.
I do like some of the ideas I'm reading in the responses though.
I would migrate their information and then on their first login ask them to confirm that their membership info is correct (just to be anal).

Resources