Security practices for internal web application - security

I am a developer working on an internal web-based application, and I have been given responsibility to make sure the system is secure. I have no experience in this area, but I still want to do the best job I can: I'm in the middle of reading OWASP's guide (http://surfnet.dl.sourceforge.net/project/owasp/Guide/2.0.1/OWASPGuide2.0.1.pdf), but there is a lot of information to process, and unfortunately deadlines are deadlines.
Can the knowledgeable users here at Stack Overflow please poke holes in my design and show me where my understanding is lacking? If the entire idea is fundamentally flawed, knowing that would be appreciated, too. Thanks for any input.
This application is hosted internally, and should not be visible at all externally, even though it is accessed over our wireless networks. I trust our network engineers to handle this, though.
The users of this application are only a subset of all the employees in this corporate environment. In addition, even authorized users should be limited to only the information pertaining to them (which is largely an application-level concern, but I want to make sure exploits are not possible).
Security Framework for Internal Web Application (by a newbie)
All communication with the web server is done over HTTPS connections.
Logging in
User enters name and password, which are POSTed over an HTTPS connection
If the name and password are correct, generate a token, and store it in a cookie. Also store the cookie in the database for future lookup. The token should have an expiration date and is associated with only the user that generated it.
Requests
Check that the token supplied is still valid (not expired)
Check that the token is valid for the user making the request
If everything checks out, refresh the token's validity for another 30 minutes (or so)
Otherwise, deny access

That sounds good.
The token can either be a signed expiration date (signed with a private key stored on the server) or a sequence of cryptographically secure random bytes which is stored in a database.
Unless the token is specific to an IP address, everything must be done over SSL.
Independently of authentication, you'll also need to look out for SQL injection, CSRF, XSS, and other security holes.

Important consideration: The entire session has to be over SSL. Firesheep has demonstrated quite clearly that being able to sniff cookies (by being on the same network as the victim) leaves your users open to session hijacking.
Security is more than just logging in. You'll want to read up on SQL Injection and Cross-Site Scripting Attacks, on the very least (the two most common attacks against web-applications).

Look into CSRF attacks. They bypass cookie checks and company firewalls.

Related

My web application is not publicly hosted, do I need to worry about CSRF?

My web app is not publicly available and will be used by certain verified users within a firewall.
Do I need to worry about CSRF?
Reading about the CSRF attacks and the below:
From Spring documentation:-
18.3 When to use CSRF protection
When should you use CSRF protection? Our recommendation is to use CSRF protection for any request that could be processed by a browser by normal users. If you are only creating a service that is used by non-browser clients, you will likely want to disable CSRF protection.
I believe apps hosted publicly are more susceptible.
Thank you in advance!
Naturally I do not know the exact circumstances or environment you are dealing with; so I can't say beyond a reasonable doubt here.
Your risk factor is definitely low, being that the web app it is not publicly accessible, behind firewalls, verified users. But it depends on what your app is doing.
I've found that XSRF or CSRF protection is only needed for domains that use cookies. Every request to your site carries your cookies even if the request comes from a web page not controlled by you. It is most important when you are modifying state on the server but there are cases where it can be useful even in cases where state is not changed.
This guide here contains a short tutorial on XSRF and how to avoid it, and allows you to actually try it out.
CSRF is one of the attacks that is actually used to bypass firewalls. So it sounds like you do need protection if authentication in your app relies on something sent automatically by the browser (eg. session cookies). If authentication tokens are not sent automatically (you have explicit Javascript to attach them to requests, like request headers), then you are inherently protected from CSRF.
In case of CSRF, the unsuspecting victim user, while being logged in to your (internal) application visits a malicious external site. That site then creates a request (eg. POSTs) the user to your apps internal url, with appropriate parameters to do something your user didn't want. As cookies are sent automatically to the destination domain, the request will be valid and processed by your app (even in case of javascript, mostly).
Notice that the user doing the internal request is your victim user with access to the internal resource. So the firewall is bypassed, the victim's browser was tricked into making the request.
Also note that this required knowledge of your app (most probably a targeted attack specifically against your app). That reduces the risk somewhat, but it is still very much a risk from a security perspective. You don't want to rely on security by obscurity, ie. you should assume that attackers know everything about your application except cryptographic secrets, but including endpoints, parameters necessary and so on. That will not always be the case, but you should design for this to make it secure.

How to store third-party credentials (no api, no OAuth) for automatic reuse?

I've read several Stack Overflow threads, I still can't decide what is the best option for my case. And the most secure one.
Here is the story. My webapp is to help users automatically get an overview of some of their data available in some third-party website. I need to store for each user some third-party credentials. Each night or so, my server will connect to the third-party services on the users' behalf and retrieve the required data.
Most of those third-party sites do not implement any API or OAuth mechanism, so I was thinking to do some web scraping.
I've read in many places that storing the credentials in the DB is not a good idea - especially because my app needs access to the password (so it has to be encrypted in such a way I can easily reuse it).
So, I have two options left:
Whenever I access (via webscraping) the third-party service, I store on the server the cookies issued by that service, for future reuse. I encrypt them and keep them encrypted in a DB, and decrypt them only when I need them. The problem is that the cookie can be denied or expired after a while, and so the automatic process wouldn't work any more.
I store the credentials in the environment variables. I will be on Node.js and Heroku. That's an idea I found in another SO thread. But I'm wondering about the security of this idea. Is it really safe? No one can access them but me? And what about if I reach many users. Like 1000 users, with 10 services. That's 10000 credentials to store in the env variables. That doesn't seem like a good idea.
I found two interesting questions on Stack Overflow but they don't fit 100% with my use case.
Security model: log in to third-party site with user's credentials (that gave me the idea in point 1)
Rails storing third party credentials.. Anyone know best practice? (gave me the idea in point 2).
I add another answer because maybe this one will do the trick for you.
You said the main goal of your website is to have an overview of third party applications. But what if instead of updating this overview every night, you update it when the user logs in ? It changes everything, because you could use the user's password (of your website) as master password to encrypt (using AES) all the others.
If you do that, the communications between your server and the clients have to be encrypted with SSL pinning, because an attacker could perform a MITM, get the master password and all the others stored in the DB... (Even if in practice it's very hard because you need to hack the client AND the server)
Storing a lot of data that changes and grows in environment variables will never be practical, no matter if it's secure or not so this is pretty much out of the question, unless if you have a small fixed number of users.
Not storing credentials in the database is a very good advice, but the cookies are credentials and even if you store them encrypted, your app needs to be able to encrypt it to use it. (This is unlike the situation with verifying passwords of your users when you don't need to ever encrypt them, you only need to see if the provided passwords hash to the same values that you have stored).
This is a hard problem because to make it work you need to have some form of credentials (whether those are passwords or cookies) stored and ready to be used unencrypted (even if they are stored encrypted, you need to store the keys to encrypt it as well).
Also, what you are trying to do can be illegal. Mayke sure that you follow the TOC of every service that you're using or otherwise you may face legal trouble.
Plan for the attacker gaining admin access to the server. Your site will be very attractive to attackers, kind of a one-stop-shop for user credentials so you will need very good security of the login credentials.
There are more than two options for storing the credentials:
Use an HSM for the storage or individual credential encryption keys.
Keep the credentials on another dedicated server with no Internet access, 2-factor authentication and limit admin personal. Rate limit the access to this server and add rate alarms. Access this server on a per user credential basis over a non-Internet connection. The credentials will only be available to the Internet connected server in memory as used, not at-rest in a file.
Storing users credentials in a reversible way looks like a terrible idea anyway. But if you really want to store them, I suggest you to use the environment variables solution. But you can improve it. To limit the amount of data you store and don't have 1000000 variables as you said, you can just store an AES encryption key, store all credentials in a DB encrypted with this key, and you just have to get this key (which is in memory) and decrypt the DB. But there is another problem with this solution. As I said, this is stored in RAM memory, so it's not persistent, imagine your server has to reboot for X or Y reason... You will lose the AES key and also the credentials of your users... Moreover, if the attacker performs a memory dump, he will have access to the AES key...
I think the better idea is to store the cookies (in an encrypted way) and when this one expires, you alert the user (by mail, phone, notifications, ...) and ask him to fill his credentials again. But it's not a perfect solution ! Indeed the cookies are a type of credentials and shouldn't be stored either...

Data encryption safe even with developer access

Suppose you have a server-client application.
Server keeps sensitive information that belongs to a Client.
Server will search some parameters in side the clients's sensitive information.
Thus server should decode the sensitive information with client control temporarily.
But server should not reveal the keys, by hacking it self.
I mean a developer should not try to change server sidde code and should not extract the client keys.
Is there really a way to do that?
Somewhat client permits server to decode sensitive information, but the keys instantly disappear and developer have no tricks to reveal this password?
The answer if exist, is valid also for an ideal secure cloud application. Developer or cloud hosting company should not access to decrypted information.
I am not optimistic, but worth to try asking.
So in a word no. This does not grant any security whatsoever, as you cannot trust the client. You even call out that the server will be controlled by the client temporarily, this is generally not a wise approach. Also, do not underestimate a bored developer, it is completely feasible to write some code and rip the keys. The key here is remembering that if someone has access to the box it is no longer your box.
In general, any client access to sensitive info on the server must require authentication of the client, so that you can verify that the client is exactly who he claims he his. The authentication typically involves sending a password, or some kind of authentication token (e.g., an encrypted shared secret) that was given to the client by the server through a secure channel.
As has been said many times, many ways, allowing client access to server data without proper and sufficient authentication means that you give up control of the server.

Reliable ways to register a user's computer with a server

As part of strengthening session authentication security for a site that I am building, I am trying to compile a list of the best ways to register a user's computer as a second tier of validation - that is in addition to the standard username/password login, of course. Typical ways of registering a user's computer are by setting a cookie and or IP address validation. As prevalent as mobile computing is, IP mapping is less and less a reliable identifier. Security settings and internet security & system optimization software can make it difficult to keep a cookie in place for very long.
Are there any other methods that can be used for establishing a more reliable computer registration that doesn't require the user to add exceptions to the various cookie deleting software?
If you're looking to do device authentication, you may want to consider mutually authenticated SSL. Here, you'd deploy a client identity certificate to each endpoint you'd want to authenticate. Then, you set the server up to require client authentication, so that a client would need to present a valid identity certificate in order to form the SSL tunnel.
This, of course, is not a perfect solution. In reality, this presents much of the same weaknesses as other solutions (to various degrees) Once your client identity certificates go to your clients, they are out of your control; should a client give their certificate to anyone else, you lost the device authentication that you have based on it. SSL identity certificates are generally stored in a keystore on the client which is encrypted with a password or other credential needed to unlock them. While a client certificate could still be compromised, it's somewhat stronger that just a cookie or something like that (assuming you don't have a client that is trying to give away its credential). In addition, you'd want to come up with some validation routine that a client would need to go though in order to get a credential in the first place (how do I know that this is a client device that I want to remember/register?).
Remember, these types of approaches only do device authentication, not users. There are more in-depth schemes already developed for device authentication than what I've mentioned; for example, 802.1x is a network protocol where an endpoint needs to present a client-side certificate to the network switch to get on a LAN. This is out-of-scope for a web application scenario, like what you've described, but the idea is the same (put a cryptographic credential on the client and validate it to establish the connection).
This, like all other security matters really, is a risk decision. What are you trying to accomplish with such a countermeasure? What are the threats you're trying to prevent and what are the consequences if someone does log in on an unregistered device? Only your situation can answer those questions and let you see the real risk, if you need/should mitigate it, and, if so, how strong of a solution do you need to get the risk level down to an acceptable level?
the best ways to register a user's computer as a second tier of
validation
From my point of view this approach does not offer much in the aspect of authentication.
You are not authenticating a user and have no idea who is using the PC that you would accept as being registered.
The way you describe it, this step should be a configuration rule in the firewall to accept connections from specific IPs only.
IMO the filtering of the PCs is the responsibility of a firewall and it would be much better handled by the firewall than any application level filtering.
Just think that you would have the overhead in your application to examine each request and decide whether to accept it or not.
Better leave this preprocessing overhead to the firewall. That's why it is there.

How safe is openID?

Is this something that can be used for highly secure information or should it be bypassed for a single site authentication system? This may be a stupid question (as it does not sound secure) but I would like some advice.
OpenID itself is no less secure than the traditional username+password login.
Obviously, you're entrusting a large part of the security to the provider - e.g. brute force prevention, password size policy, etc.
Wouldn't use it for online banking for example, not while the OpenID protocol itself is insecure, but due to the use case.
highly secure information
Financial info? DoD Top Secret? Really secure information isn't available via the internet, only on the local network or through a VPN, which is moving a chunk of the security to the network level. Really really secure information is on a computer with no network connection...
There is the theory that the user, having just one password to use for their OpenID account, has the possibility to choose a decent strength password, less likely when they have to remember x passwords.
OpenID is technically sound, but can be baffling for some users. I recommend browsing through the responses to this question. For very private information I would be cautious about using OpenID because:
Since the login is being used so widely and so frequently there are more opportunities for the password to be accidentally disclosed. A particular worry would be if another OpenID-enabled site which the user is registered on one day asks them for their actual password...some users might enter it without thinking, not realizing that they are circumventing the OpenId security model.
If you have doubts about the security of OpenID, users might also have these doubts. From a business point of view, is it worth the risk of being perceived as insecure? (Of course, this is at least better than the other way around -- bad security being perceived as safe!)
There is a trend towards offering OpenID login on social networking sites and such, but I doubt we will see it being adopted very much for protecting extremely sensitive data.
OpenID itself is secure, however due to its decentralised nature it often assumes that three servers are "trusted". If these servers are not trustworthy then your security is gone.
For instance, if you use your own website as an identifier but delegate authentication to a 3rd party provider, then if your website, or the identity provider, or the consumer server is penetrated, then the information is not secure.
If you want to use OpenID internally, and use only your own secure server as an OpenID provider, then you should be pretty secure. But if you want people to "bring their own OpenID account" then OpenID is not the right choice.
In general, it's not really any more o less secure than normal user/password authentication, but with one major difference (IMO). OpenID allows a user to login via multiple different methods (Google, AOL, Yahoo, etc..). If someone were to crack it, they'd have to go after each individual service. You have the option to not allow certain services to participate, in the event you found one of them to be less secure.

Resources