We have an internal CRM system which is currently a website that can only be accessed inside our intranet. The boss is now wanting to have it exposed to the outside world so that people can use it from home and on the road. My concern is security based in the fact we will be exposing our Customer base to the outside world. I have implemented 3 layers of security as follows:
User Name and Strong password combination to login
SSL on all data being pushed across the line
Once the user is logged in and authenticated the server passes them a token which must be used in all communication with the server from than on.
Basically Im a bit of newb in the respect of web security. Can anyone give me advice on whether I am missing anything? Or something should be changed?
There's a whole world of stuff you should consider, and it'll be really hard to quickly answer this - so I'll point you at a range of resources that should help you out / get you started.
First, I'll plug http://security.stackexchange.com, for any specific questions you have - they could be a great help.
Now, on to more immediate things you should check:
Are your systems behind a firewall? I'd recommend at least your DB is placed on a server that is not directly available to the outside world.
Explore and run a range of (free) security tools against your site to try and find any problems. e.g.:
https://asafaweb.com
http://sectools.org/
Read up on common exploits (e.g. SQL injection) and make sure you are guarding against them:
https://www.owasp.org/index.php/Top_10_2010-Main
https://www.owasp.org/index.php/Category:Vulnerability
How is your token being passed around, and what happens to it if another user gets hold of it (e.g. after it being cached on another machine)?
Make sure you have a decent password protection policy (decent complexity, protects against brute force attacks by locking accounts after 3 attempts).
If this is a massive concern for you (consider the risk to your business in a worst case scenario) consider getting an expert in, or someone to run a security test against your systems?
Or, as mrunion excellently points out in the comments above (+1), have you considered other more secure ways of opening this up, so that you don't need to publish this on the web?
Hope that gets you started.
Related
We have a security problem here and we really need your help and inputs. We have a website with a backend system where admins can login and update the frontend. Our good friends tried to hack into the backend using SQL injection onto our login page and they succeeded and could create a users with admin access. The website is written in ASP.NET in C#.
We are thinking to remove the login page from public IP or add 2 layers protection ( IIS ip restriction and IP access list by program).
How can we do this in IIS and in the program? Please help since I am new to all these security things.
We distribute this website on a web garden consists of 3 servers so they share local/private ips of xx.xxx.x.x
How do I implement this in my code to grand access to just a list of IPs or a group of IPs?
Thanks so much in advance,
Simplecode
Just to go a little further down this rabbit hole.
First, sanitize your inputs and use parameterized queries. Just fix your code. This is the most important thing you should be working on right now.
Second, moving the login page doesn't fix the problem. If there are other pages within your site that are accessible, then I'm sure you have other sql injection issues. See #1 above.
Third, I bet you are exposed to all manner of other things like XSS. Take a little bit and learn what they are. Then spend some time retraining yourself to code in a defensive way. A hint: validate EVERYTHING. If you expect a number, only accept a number. If you expect a short string, don't allow javascript to be embedded in it.
One mantra to keep in mind is to only trust the browser, the users, and even the system admins as far as you absolutely have to. Which is to say build your site in such a way that you don't have to trust them at all.
Most companies have no idea what threats they are faced with. A hint: external threats or only part of it. Internal threats are usually far worse. I say this simply because you are asking a question which attempts to paste over exactly one part of the problem and ignores everything else.
I recently spoke with a company that claimed they had security down pat. Prior to the meeting I went to their website and noticed that they had a document id in all of their URLs. The id was a simple int. In a few minutes of spare time I wrote an app that started at doc id 1 and iterated until the server stopped giving data. There was a fair number of documents I should never have been able to see. Being a good samaritan, I told them about this.
The point of that tale is that sql injection, xss, etc isn't everything. Security through obscurity is another fail entirely.
I build ASP.NET websites (hosted under IIS 6 usually, often with SQL Server backends and forms authentication).
Clients sometimes ask if I can check whether there are people currently browsing (and/or whether there are users currently logged in to) their website at a given moment, usually so the can safely do a deployment (they want a hotfix, for example).
I know the web is basically stateless so I can't be sure whether someone has closed the browser window, but I imagine there'd be some count of not-yet-timed-out sessions or something, and surely logged-in-users...
Is there a standard and/or easy way to check this?
Jakob's answer is correct but does rely on installing and configuring the Membership features.
A crude but simple way of tracking users online would be to store a counter in the Application object. This counter could be incremented/decremented upon their sessions starting and ending. There's an example of this on the MSDN website:
Session-State Events (MSDN Library)
Because the default Session Timeout is 20 minutes the accuracy of this method isn't guaranteed (but then that applies to any web application due to the stateless and disconnected nature of HTTP).
I know this is a pretty old question, but I figured I'd chime in. Why not use Google Analytics and view their real time dashboard? It will require minor code modifications (i.e. a single script import) and will do everything you're looking for...
You may be looking for the Membership.GetNumberOfUsersOnline method, although I'm not sure how reliable it is.
Sessions, suggested by other users, are a basic way of doing things, but are not too reliable. They can also work well in some circumstances, but not in others.
For example, if users are downloading large files or watching videos or listening to the podcasts, they may stay on the same page for hours (unless the requests to the binary data are tracked by ASP.NET too), but are still using your website.
Thus, my suggestion is to use the server logs to detect if the website is currently used by many people. It gives you the ability to:
See what sort of requests are done. It's quite easy to detect humans and crawlers, and with some experience, it's also possible to see if the human is currently doing something critical (such as writing a comment on a website, editing a document, or typing her credit card number and ordering something) or not (such as browsing).
See who is doing those requests. For example, if Google is crawling your website, it is a very bad idea to go offline, unless the search rating doesn't matter for you. On the other hand, if a bot is trying for two hours to crack your website by doing requests to different pages, you can go offline for sure.
Note: if a website has some critical areas (for example, writing this long answer, I would be angry if Stack Overflow goes offline in a few seconds just before I submit my answer), you can also send regular AJAX requests to the server while the user stays on the page. Of course, you must be careful when implementing such feature, and take in account that it will increase the bandwidth used, and will not work if the user has JavaScript disabled).
You can run command netstat and see how many active connection exist to your website ports.
Default port for http is *:80.
Default port for https is *:443.
Like a lot of people I've gone with ASP.Net Forms authentication because it's already written and writing our own security code we're told is generally a bad idea.
With the current problems with ASP.Net I'm thinking it might be a good time to look at alternatives.
Important: ASP.NET Security Vulnerability - ScottGu
Video demonstrating attack
Microsoft advisory including workaround
From what I understand Microsoft tend to store things on the client side because it makes it easier to operate over server farms without needing database access calls.
I don't really care about server farms though and I'd like to simply have an opaque cookie that demonstrates my lack of trust in the callers.
Is there a decent solution that's already been proven solid?
Update: to clarify my question. I'm talking about the authentication token part of the forms authentication that I'd like to replace. The back end is quite easy to replace, you can implement the interfaces to store your users and roles quite easily. You can also use existing libraries like http://www.memberprotect.net/ which has been mentioned here.
I'd like to change the front end part of the process to use a token that doesn't provide the client with any leverage. Sticking with the existing back end infrastructure would be useful but not essential.
I've been working on an HttpModule that basically does what you're looking for. When a FormsAuthenticationCookie and FormsAuthenticatedTicket are generated, before the response is sent to the client (i.e., during the processing of the postback of the Login page/action), all of the details about the cookie & ticket are stored on the server. Also, the UserData from the ticket is moved to the server (if present) and replaced with a salted SHA-512 hash of the other properties in the ticket along with a GUID that serves as a key into the server-side store of the ticket.
The validation of the cookie & tickets compares everything the client provided (optionally including their IP address) with all of the properties that were known about them at the time they were issued. If anything doesn't match, they are removed from the request before the FormsAuthenticationModule even kicks in. If everything does match, the server's UserData is stuck back in the FormsAuthTicket in case you had any modules or code that depend on it. It's all transparent. Plus, it can detect suspicious and blatantly malicious requests and inserts a random delay in the processing. It also has some explicit padding oracle workarounds in there.
The demo app actually lets you create/modify your cookie & ticket values on the server, with the server encrypting your ticket for you with the machine keys. This way you can prove to yourself that you can't create a ticket/cookie that gets around the server validation unless you write the exact set of data to the server (which should be impossible under normal circumstances).
http://sws.codeplex.com/
http://www.sholo.net/post/2010/09/21/Padding-Oracle-vs-Forms-Authentication.aspx
http://www.sholo.net/post/2010/09/22/Sholo-Web-Security-and-the-EnhancedSecurityModule.aspx
-Scott
If you have your keys in the web.config and the attacker gets to it, they are pretty much done.
If that's not the case (they don't get the keys from your .config), then afaik the padding oracle shouldn't allow them to sign a new auth ticket. The paper explains ability to encrypt by taking advantage of the cbc mode, ending with a tiny bit of garbage there. It should be enough to make it an invalid signature.
As for the video where they get the keys with the tool, its against a dotnetnuke install. A default dotnetnuke has those keys in the web.config.
Implement the workaround, keep your keys off your site level web.config, if you don't use webresource.axd and scriptresource.axd disable those handlers, and apply the patch as soon as ms releases it.
I will simply recommend taking a look at InetSolution's MemberProtect product, it's a component designed with security in mind for the banking and financial services industries but is widely applicable to any site designed on ASP.NET or application built on top of the .NET platform. It provides support for encrypting of user information and a host of authentication methods from the simplistic to the very advanced and the various methods and functions are designed to be used as the developer sees fit, so it's not a canned solution so much as a very flexible one, this may or may not be a good thing depending on the particular situation. It's also a very solid foundation on which to build new member-based websites and applications in general.
You can find out more about it at http://www.memberprotect.net
I am the developer for MemberProtect and I work at InetSolution :)
This isn't a value-less question, but I have to say that I think your logic is suspect. It's no bad idea to consider alternative authentication solutions, but the newly-announced ASP.NET vulnerability should not push you to abandon a current (presumably working) solution. I'm also not entirely sure what the relevance of this comment is:
From what I understand Microsoft tend to store things on the client side because it makes it easier to operate over server farms without needing database access calls.
What is it about the vulnerability that makes you think that ASP.NET forms auth is broken any more than another solution?
The detail of the MS advisory would seem to suggest that pretty much any other authentication system could be rendered similarly vulnerable to attack. For example, any solution that uses the web.config file to store settings would still have its settings open to the world, assuming a successful attack.
The real solution here is not to change security, but to apply the published workaround to the problem. You might switch authentication providers only to find that you are still vulnerable, and your effort has gained nothing.
Regarding tokens/sessions: you have to push something to the client for authentication to work (whether you call it a token or not), and it's not this part of the process that causes the current security issue: it's the way the server responds to certain calls that makes this secret vulnerable to attack.
I want to make a secure website using ASP.NET, but when I publish it, the domain administrator can see all the data stored in my database (SQL Server). I want to hide my data and code from the domain administrator too. Are there any procedures to do that? Please give me the address of a good domain I can use, which will give me all administrative power of my website (Domain owner also cannot access my databases and files.) Thanks for your suggestion.
Have you looked at: SQL Server 2008 Transparent Data Encryption?
Also:
SQL Server 2008 Transparent Data Encryption
Understanding Transparent Data Encryption (TDE)
Have you considered using a Virtual Private Server? I believe with a VPS you should be able to have complete control over who has access to what at the operating system level.
You can encrypt data, but there's no way to protect code (especially not web-facing code), but frankly the question doesn't make sense - if you have trust issues with someone you have an implicit trust relationship with then you need to find a different provider.
If you don't trust anyone (personal psychology not withstanding) you need to host it yourself.
Addendum: look at it from the other way round, why would you host something for someone without being able to inspect it for security and even legal concerns?
If you want total security there's quite a few things you need to implement:
As others have said you need physical encryption of your database. Merely blocking them from accessing the database is not enough because they have access to the physical database files and can use tools on them to access the data directly.
You will want to use web.config encryption
Walkthrough: Encrypting Configuration Information Using Protected Configuration
How To: Encrypt Configuration Sections in ASP.NET 2.0 Using DPAPI
This is rather questionable security however since it requires a key container to be installed upon the server it would be arguably achievable for a nefarious administration to copy your key and then use it to manually decrypt your web.config. To protect yourself further than that you would need to create a secured web service (secured both for message transport, SSL, and secured message that the content itself is encrypted inside the SSL transport tunnel, see WCF services security) that your application constantly talks to for protected data like the login users for the sql server database and then apply rotating passwords to make it if they intercepted one password that it might not be valid anymore if it's been rotated.
After this point you will need to use source code protection that includes decompilation protection and code obfuscation. This will add a layer of protection from prohibiting viewing the source of your application directly for information about how else you protect your application (this will only go so far to stop a sophisticated cracker though).
All in all at this point you've achieved nearly the highest level of code/data security you can inside a hosted environment but this goes back to the core problem. If you have concerns that the system operator is nefarious then all of these protections even can still be beaten if the admin is skilled enough and has enough motivation to do it.
If you need protection above and behind this you would really want to look at colocation hosting or at the very least dedicated server hosting that would allow you to apply encryption at the operating system level as this protects you from the most effective brute strength attacks which involve just ripping out hard drives from a machine and spraying ram with air duster upside down to freeze it and then attempt to steal encryption keys from the ram itself disconnected from the server.
Having security that makes you immune (or nearly immune) to this kind of attack basically requires using TrueCrypt for native encryption of your file system where you do not have it cache the keys/key files in memory. At this point the only last part of security left is to host at a reputable data center like ThePlanet or Rackspace that has 24/7 electronic surveillance that it would be nearly impossible for a nefarious employee to be able to compromise your server without video recordings of it occuring.
Remove the BUILTIN\Administrators group from the sysadmin role - obviously this can only be done by a server admin, but in a proper environment, it is possible for domain admins to only be able to maintain servers nad not see data.
In 2008, the default is to not include this.
As for code, you can obfuscate your DLLs, but there is no complete way to hide code from someone who can access the filesystem.
You won't be able to hide the source code, but you do have some options to make it less inviting to admins:
obfuscate - deter people from knowing what is happening syntactically. While they can follow the code and eventually figure it out (if they want), it requires more effort. After all, with enough effort and know-how, anything can be cracked.
encrypt - because the web page needs to be decrypted by the server, the server needs to have a key to decrypt it. This key needs to be stored in a file that the server (and thus admin) has access to. Using some obfuscation, you can try and hide this (again), but any places there is a symmetric encryption, a superuser has the ability to get at it.
Note:
Any time something is encrypted, it will most likely require a decrypt to use/view. The process will be a negative performance impact.
When things are encrypted, especially from an admin perspective, it is essentially an invitation calling for alarm; it creates curiosity. If it's data, that's one thing, but code should not need to be encrypted where there is trust. It's like saying that you have something you want to hide, generally meaning something "bad" that you don't want found out.
I am looking for a best practice for End to End Authentication for internal Web Applications to the Database layer.
The most common scenario I have seen is to use a single SQL account with the permissions set to what is required by the application. This account is used by all application calls. Then when people require access over the database via query tools or such a separate Group is created with the query access and people are given access to that group.
The other scenario I have seen is to use complete Windows Authentication End to End. So the users themselves are added to groups which have all the permissions set so the user is able to update and change outside the parameters of the application. This normally involves securing people down to the appropriate stored procedures so they aren't updating the tables directly.
The first scenario seems relatively easily to maintain but raises concerns if there is a security hole in the application then the whole database is compromised.
The second scenario seems more secure but has the opposite concern of having to much business logic in stored procedures on the database. This seems to limit the use of the some really cool technologies like Nhibernate and LINQ. However in this day and age where people can use data in so many different ways we don't foresee e.g. mash-ups etc is this the best approach.
Dale - That's it exactly. If you want to provide access to the underlying data store to those users then do it via services. And in my experience, it is those experienced computer users coming out of Uni/College that damage things the most. As the saying goes, they know just enough to be dangerous.
If they want to automate part of their job, and they can display they have the requisite knowledge, then go ahead, grant their domain account access to the backend. That way anything they do via their little VBA automation is tied to their account and you know exactly who to go look at when the data gets hosed.
My basic point is that the database is the proverbial holy grail of the application. You want as few fingers in that particular pie as possible.
As a consultant, whenever I hear that someone has allowed normal users into the database, my eyes light up because I know it's going to end up being a big paycheck for me when I get called to fix it.
Personally, I don't want normal end users in the database. For an intranet application (especially one which resides on a Domain) I would provide a single account for application access to the database which only has those rights which are needed for the application to function.
Access to the application would then be controlled via the user's domain account (turn off anonymous access in IIS, etc.).
IF a user needs, and can justify, direct access to the database, then their domain account would be given access to the database, and they can log into the DBMS using the appropriate tools.
I've been responsible for developing several internal web applications over the past year.
Our solution was using Windows Authentication (Active Directory or LDAP).
Our purpose was merely to allow a simple login using an existing company ID/password. We also wanted to make sure that the existing department would still be responsible for verifying and managing access permissions.
While I can't answer the argument concerning Nhibernate or LINQ, unless you have a specific killer feature these things can implement, Active Directory or LDAP are simple enough to implement and maintain that it's worth trying.
I agree with Stephen Wrighton. Domain security is the way to go. If you would like to use mashups and what-not, you can expose parts of the database via a machine-readable RESTful interface. SubSonic has one built in.
Stephen - Keeping normal end users out of the database is nice but I am wondering if in this day and age with so many experienced computer users coming out of University / College if this the right path. If someone wants to automate part of their job which includes a VBA update to a database which I allow them to do via the normal application are we losing gains by restricting their access in this way.
I guess the other path implied here is you could open up the Application via services and then secure those services via groups and still keep the users separated from the database.
Then via delegation you can allow departments to control access to their own accounts via the groups as per Jonathan's post.