I have 2 sites that are on different servers and domains but I would like to pass from one to the other with out having to re-authenticate.
Both sites use the same DB so my thought was have an Auth Table where I place a GUID, the users ID, and a time stamp. I would pass the GUID in the URL and do a lookup to see if the GUID is in the table and is less then X old, if so authenticated the user.
Any thoughts?
Yes, As long as security is not critical in your solution.
If security is critical (money is involved) some other measures should be added.
like - encrypt the guid or pass it over secure connection -so it can't be stolen
have the guid used only once (to avoid replay attacks, and constantly look for holes in this system, as you implement your own security.
encryption is not easy as you need a key, and if you choose bad keys, or store them not good, the encryption is useless.
knowing more about the architecture, clients might help tightening the security some more.
Remember that passing it as part of the URL leaves a trail all over the web with the guid. Maybe there is a better way to pass it, maybe as data.
The secure way to do this would be to use OpenID with Directed Identity.
This way the first site can assert the identity of the user that is accessing the second site.
Related
I'm really just looking to see how much folly is in the below suggestion from a security perspective.
I have two websites. One is an administration portal and the other is a members portal.
Within the administration portal administrators can retrieve a listing of members and I need to offer the ability for administrators to login to the member portal without having to enter the members login credentials.
Both are separate websites within IIS and for this discussion lets say they are on different servers.
Both websites access the same SQL Server database.
I was thinking that I could on the administrator clicking a "Login as Member" link create a random code string and save this to the database along with the member number.
I could then pass the code and member number to the member portal as query string parameters.
The member portal then read in these values and checks them in the database to verify that the code string exists and if so that it matches the member number also being passed. I could then login the member and set a flag in the database to set the code as being used and therefore invalid for future requests.
I'm thinking to bypass this a hacker would need to successfully guess the random code and pass that to the page alongside the corresponding member number for that code and for that combination to be marked as unused in the database.
This would seem to be unlikely given that only seconds will pass between the code being generated and the code being used.
If necessary I could always check the IP address of the request as users of the administration portal all share the same fixed IP address.
So do you think the above would stand up to scrutiny on a security review or will I need to go down the SSO route?
Your approach is very sound. I can confirm because I have implemented just such a solution for just such a reason. We analyzed the options and exposure. And after implementation, our application passed a PCI Complaince Audit.
Reasons:
SSL is Esential! protects against sniffers. Essential. Without Encryption, sniffers could detect your GUID and may have a window to use it)
As Tony pointed out, the GUID is effectively unguessable.
Guid Tokens expiring should expire within 24 hours.
Suggestions:
Checking against IP is good. But don't be fooled into a feeling of security from it. Anyone can fake IP's in headers. To be Secure against XSS and CSRF by using AntiForgery tokens.
The AntiForgery token is a cookie that populates your HTTPHeaders with __RequestVerificationToken which is almost as hard to guess as your GUID.
Consider using an established Authentication framework like .NET Identity 2 and multitenancy.
An established framework takes the burden of encrypting your passwords. MS Frameworks like Simple Membership and Identity integrate into modern ASP.NET frameworks and give you very strong base of functionality to lean on.
If you're using an old framework like classic ASP or .NET 2.0, the classic Membership Provider is more appropriate.
If you are creating new MVC 5 applications utilizing Entity Framework, I strongly suggest using Identity 2.1.
Consider Mult-Tenancy. While there is nothing wrong with your solution, if Admins and users shared Membership Provider, your solution would be cleaner. An admin could log into the main site and "get" the token from the DB. Then no exposure.
Assuming the use of HTTPS and adequate physical and IT security processes and procedures in place for the administrators, this method should be adequate. It is more secure than most financial website password resets, which typically only require a compromised email account and some personal information to reset the password. If you check the IP address range of the originating client request as well, a hacker would have had to already have access to your systems or network. Also, if you make the code a GUID, it would be (pragmatically speaking) impossible for someone to guess.
You could add a layer of checking for hack attempts by storing a record in the database each time this event occurs (or at least each it fails due to a bad key), and each time it occurs run a check to see if it is happening too often (like 100 times in the past hour, or something--the right number depends on how often you expect it to happen). If it's happening too often, then have it send an alert to IT personnel and revert so that the user has to enter their credentials manually.
Disclaimer: I am not a security expert by any means, so I'll gladly defer to anyone claiming such status. I'm weighing in here due to a lack of answers.
I am about to deploy an ASP .NET application (developed with LINQ-to-SQL).
I have taken following precautions:
Database access via user with limited access, however, since application is to access the sensitive data, I can't deprive this limited access user from it
Database server is not exposed to external network - is hiding behind DMZ and all external ports are blocked
I have done thorough security testing of the web-application; SQL Injections, rights management, illegal data access (via post/get data tempering)
Application is operating on SSL
Questions:
1 - I am using ASP .NET authorization API; any recommendation for avoiding session hijacking (in case someone some-how gets to know the session key). Is there are way to change the authentication cookie less prone to threats? Say like, changing it after every request? (I know I am get very conscious about this particular item)
2 - Data in the database is not encrypted. To make things ultra-secure, I am thinking about implementing transparent data encryption. Can someone share his/her experience or a link about implementing data level encryption with SQL Server 2008 along with pros-and-cons?
3 - Recommendation for storing connection string in web.config. Is using integrated security better then using encrypted database connection string?
It's seems to me that it's enough of standard asp.net api for this task. There is a very good article from MS P&P team about securing your forms authentication, it should help you.
I don't have such experience but here is a link with article.
I don't know :(
Also I recommend to check AntiXSS tool, it can show you some potential xss holes. And one last note, never trust to user input.
Integrated security is your strongest option.
I'm not an ASP.Net expert, but in my PHP projects I encrypt the cookie and affinitize it to a specific client IP. This way sessions cannot migrate to a different client. Ultimately, if you want to be absolutely sure, cannot rely on cookies for authentication, but instead use HTTP Digest, since browsers will transparently re-authenticate every request within the realm. Unfortunately this option does not work with the built-in ASP.Net membership providers as the HTTP Digest option they offer is half-brained to say the least (only authenticate against AD).
What specific threat are you trying to mitigate by encrypting data? TDE is designed to mitigate the threat of accidental media loss (ie. someone find an old disk of your with all the data on it, or you loose a laptop with the database on it). This is also the threat mitigate by most other database encryption schemes, like column encryption or file level encryption (bit locker). Other threats, like accidental compromise of access to the database (ie. someone finds a SQL injection vector to your db) cannot be mitigated by TDE, since the database will offer the decrypted data to any authenticated user. To mitigate such threats it means the data is encrypted with keys presented by the user (ie. only the user session can decryt the data becaus eonyl that session know the key password), but that knocks out the 'Transparent' aspect of all these encryption schemes. Having the user encrypt data with it's own key password protects data from other users (other sessions), so it is stronger, but its very difficult to 'get right', and the user is always at risk at locking himself out of its own data by forgetting/loosing the key password.
Use integrated security and store connection string encrypted. Since encrypting the strings in Web.Config is trivial and well supported in ASP deployment and operation, just do it. Encrypting the string protects agains accidental compromise of the IIS/ASP host from a non-admin account. An admin account, or the account under which the ASP runs will always be able to read the encrypted connection string. Since the most likely attack vector will always be ASP compromise (ie. SQL injection and friends) the attacker will most likely be able to read the connection string even when encrypted, so there isn't that much benefit from it, but every little bit counts.
Asp.net stores the session in a cookie, thus not having to worry about sessions on the server side (traditionally sessions are stored in a database, and lookups are done via a session ID, which is usually a Guid like string).
In my previous question, I was asking about how a spring application stores/creates sessions etc: Spring authentication, does it use encrypted cookies?
Cletus pointed out that storing a username/id in a cookie, although encrypted, is a security issue because the would-be-hacker has both the encrypted text, but also the hacker knows what the actual encrypted text is i.e. the userId or username.
What are you thoughts on this?
I am sure StackOverflow is also using this mechanism, as is **99.9% of asp.net web applications that are using formsauthentication in this manner.
Microsoft's MSDN site itself is filled with examples like:
FormsAuthentication.RedirectFromLoginPage(UsernameTextbox.Text, NotPublicCheckBox.Checked);
In the above code, the username value is stored in the encrypted cookie.
actually, I recall that the asp.net website was hacked because the web.config didn't have the Protection=All in the forms authentication tag.
So is this a real issue?
To repeat what cletus linked to:
In case you're wondering what a "crib" is. see: http://www.faqs.org/faqs/cryptography-faq/part03/
Cryptanalytic methods include what is
known as practical cryptanalysis'':
the enemy doesn't have to just stare
at your ciphertext until he figures
out the plaintext. For instance, he
might assumecribs''---stretches of
probable plaintext. If the crib is
correct then he might be able to
deduce the key and then decipher the
rest of the message. Or he might
exploit ``isologs''---the same
plaintext enciphered in several
cryptosystems or several keys. Thus he
might obtain solutions even when
cryptanalytic theory says he doesn't
have a chance.**
Maybe you should take a look into this document: Improving Web Application Security: Threats and Countermeasures -- Threat Modeling
It's a good start point to understand what security risks are involved and how can you mitigate that threats.
Working inside the context of an ASP.NET application I am creating a page that will be able to execute database scripts against one of many databases in our environment. To do this we need to prompt the user for a username/password combination, this value can be used for all servers without issue.
The question is where is the most secure location to store this information? We need to store it temporarily as when they are on this specific page they could be executing hundreds of scripts, over multiple postbacks. From what I can tell I have 3 options and I'm not sure what is the best. Below is my take on the options, what is the recommendation of everyone here? What is the most secure, while still being friendly for the user?
Store Information In Viewstate
One of the first ideas we discussed was storing the information after being supplied by the user in the ViewState for the page. This is helpful as the information will only exist for the lifetime of the page, however, we are unsure of the security implications.
Store information in Session
The next idea we had was to store it in session, however, the downside to this is that the information can be made available to other pages inside the application, and the information always lingers in memory on the server.
Store Information in Application
The last idea that we had was to store it in the Application cache, with a user specific key and a sliding 5 minute expiration. This would still be available to other pages, however, it would ensure that the information is cached for a shorter period.
Why?
The final question that is important is "Why are you doing this?". Why don't we just use their Lan id's? Well we cannot use lan id's due to the lack of network support for delegation.
S0 what is the recommended solution? Why? How secure is it, and can we be?
Update
Great information has been discussed. TO clarify, we are running in an intranet environment, we CANNOT use Impersonation or Delegation due to limitations in the network.
In my opinion the natural place for this is the Session.
I'm not sure why you seem to be fearing "other pages inside the application" (you control the appliciation, don't you?), but if you really are, you could use some sort of encryption before you store it.
But if you are going to do that, the data could live in the ViewState as well.
I don't like any of these ideas, but totally hate the viewstate idea.
I don't know how many databases you are attaching to, but if there is a limited number, I kind of wonder if handling your authentication and authorization in a standard secure manner, then connect to those databases via integrated security using identity impersonation with an account that has minimal permissions.
The ViewState approach is good but has the problem that you are giving out the username and password to the client. Even if you encrypt it, if some attacker has the encryption key, the situation will not be very good.
Regarding the Session and Application approaches, I don't think Application approach makes sense. Data is user specific, so Session should be the way to go. It'll go away as soon as user's session is closed. By the way, if you chose to store it at the server, use SecureString class.
As John MacIntyre wrote you should use integrated security and impersonation for this.
If for some reason you can not use it and you are going to provide your own login page, use by all means SSL to encrypt the traffic between the browser and your server. Using the ViewState approach is also completely insecure if you do not use SSL, there are tools to view the contents very easily. From the methods that you enumerate the best one would be to use the Session state. You can offload saving the session state from your web server memory and save that data in a database that you can secure the way you want. If you don't like the way these work you could even write your own session state provider and apply the security you need there.
Storing in Viewstate increases your exposure because the password will be flying around the internet again and again. It's up to you if encryption is good enough to address this risk.
Using Application or Session both keeps the password in the server. As mentioned above SecureString will keep people from simply reading passwords out of memory. Session will scale to more users, and probably more importantly to multiple servers much easier than Application. Unless you are sure you will never use more than 1 web server I would not use Application, as it will be up to you to synchronize all the servers.
Never store passwords!
Rather store the hash of a password. See: http://en.wikipedia.org/wiki/Crypt_(Unix)#Library_Function.
I'm aware this does not answer the question, but the more programmers who ignore this advice, the easier it will be for criminals to steal data. Don't let your organization become a news story.
The username/password really shouldn't be stored anywhere.
You store a live database connection, preferably from a pool in your Session object. You only need the username/password as long as it takes to log into the database.
While another page can use the live connection, it doesn't give anyone else permanent access to the database as you would by storing a username/password.
Imagine that you have a simple site with only 2 pages: login.aspx and secret.aspx. Your site is secured using nothing but ASP.net forms authentication and an ASP.net Login server control on login.aspx. The details are as follows:
The site is configured to use the SqlMembershipProvider
The site denies all anonymous users
Cookies are disabled
The are obviously many things to consider regarding security but I am more interested in the zero code out of box experience that comes with the .net framework.
If, for the sake of this question, the only attack points are the username/password textboxes in login.aspx, can a hacker inject code that will allow them to gain access to our secret.aspx page?
How secure is the zero code out-of-box experience that Microsoft provides?
You still have some variables that aren't accounted for:
Security into the data store used by your membership provider (in this case, the Sql Server database).
security of other sites hosted in the same IIS
general network security of the machines involved in hosting the site, or on the same network where the site is hosted
physical security of the machines hosting the site
Are you using appropriate measures to encrypt authentication traffic? (HTTPS/SSL)
Not all of those issues are MS specific, but they're worth mentioning because any of them could easily outweigh the issue you're asking about, if not taken care of. But, for the purpose of your question I'll assume there aren't any problems with them.
In that case, I'm pretty sure the forms authentication does what it's supposed to do. I don't think there's any currently active exploit out there.
As far as I know password will be sent as plain text (but encoded). So the most important thing to do is to use HTTPS protocol on login screens.
The other setting seems to be secure for me.
With HTTP Basic Authentication, which is what the .NET basic forms authentication is using, in order to view the secret.aspx page, the browser must send a Base64 encoded concatenation of the username and password.
Unless you utilize SSL, anyone who has access to scan the network between the server and the browser can read this information. They can decode the username and password. They can replay the username and password in the future to gain access to the secret.aspx page.
That said, unless you use SSL, someone can also scan the whole session of someone else using secret.aspx, so in effect, they would have access to the content of the page as well.
Well, try and look behind the scenes:
Password Protection
Applications that store user names,
passwords, and other authentication
information in a database should never
store passwords in plaintext, lest the
database be stolen or compromised. To
that end, SqlMembershipProvider
supports three storage formats
("encodings") for passwords and
password answers. The provider's
PasswordFormat property, which is
initialized from the passwordFormat
configuration attribute, determines
which format is used:
MembershipPasswordFormat.Clear, which stores passwords and password
answers in plaintext.
MembershipPasswordFormat.Hashed (the default), which stores salted
hashes generated from passwords and
password answers. The salt is a random
128-bit value generated by the .NET
Framework's RNGCryptoServiceProvider
class. Each password/password answer
pair is salted with this unique value,
and the salt is stored in the
aspnet_Membership table's PasswordSalt
field. The result of hashing the
password and the salt is stored in the
Password field. Similarly, the result
of hashing the password answer and the
salt is stored in the PasswordAnswer
field.
MembershipPasswordFormat.Encrypted,
which stores encrypted passwords and
password answers.
SqlMembershipProvider encrypts
passwords and password answers using
the symmetric encryption/decryption
key specified in the
configuration section's decryptionKey
attribute, and the encryption
algorithm specified in the
configuration section's
decryption attribute.
SqlMembershipProvider throws an
exception if it is asked to encrypt
passwords and password answers, and if
decryptionKey is set to Autogenerate.
This prevents a membership database
containing encrypted passwords and
password answers from becoming invalid
if moved to another server or another
application.
So the strength of your security (out of the box) will depend on which password protection format strategy you are using:
If you use clear text, it is obviously easier to hack into your system.
Using Encrypted on the other hand, security will depend on physical access to your machine (or at least, machine.config).
Using Hashed passwords (the default) will guarantee security depending on: a) known reversals of the hashing strategy of RNGCryptoServiceProvider class and b) access to the database to compromise the randomly generated salt.
I do not know if it is possible to use some sort of rainbow table hack into the default Hash-base system.
For more details, check out this link:
http://msdn.microsoft.com/en-us/library/aa478949.aspx
If configured correctly through the membership provider, you will have a adequate level of security. Outside of that, access to that page might be accessible through cannonical attacks, but that has to do with your general security. I gave a presentation on using the Security Enterprise Application Blocks. You might want to read up on those and look into that when implementing security on your site, and just be aware of common security threats. No site will ever be 100% unhackable, given that you are on an open shared network and total security would be an unplugged server locked in a safe guarded 24/7 by the military (around DoD "A" level security, based of Orange book). But the out of the box functionality of the Membership Providers (when configured correctly) will offer a good amount of security.
Edit: Yeah, I agree with the other comment that was made, HTTPS on at least the log in screens is a given, if you want to protect the username/passwords from packet sniffers and network monitors.
Asp.Net supports cookieless sessions, as this blog post shows. Instead of a session cookie, it uses an identifier in the url to track users.
I am not sure how secure this is, but I would think it is a secure as the difficulty to brute force the identity string.
It looks like it works more or less out of the box, however when redirecting a user and wanting to maintain session state you must include the session id. The blog post shows how to do that, as well as many other articles on the web.
Here are two good articles from Microsoft on the subject:
How To: Protect Forms Authentication in ASP.NET 2.0
INFO: Help Secure Forms Authentication by Using Secure Sockets Layer (SSL)
Cookies over URL is not secure enough, there are so many different problems with it (especially referrer leakage if you've got any) and usage of HTTPS.