A false sense of security
After reading my post about enterprise security infrastructure, Comlin asks:
Ayende, What would you say if I give you a real world scenario:
1. Server running Microsoft Windows hosts a web site which includes your security features.
2. Separate server hosts database.
Well, common thing isn't it?
We are pretty sure that the first server(it's on the Internet) would be hacked sooner or later and the hacker will acquire admin privileges. And all we have is your "entity security" inside the BL, who needs it anyway, you will take the connection string and perform all the malicious actions inside the database!
I see two ways to handle this situation: developing an app server to process queries or building security infrastructure inside DB using stored procedures or row-level security. What do you think?
Let us go through several of those iterations in turn, shall we?
First, I disagree with the implicit assumption that it will essentially be broken, and broken with admin privileges. But even then... Well, getting admin access to the box doesn't mean that you get my connection string, by no means. That connection string is DPAPI-ed encrypted and keyed to the user running the application. Even as admin, you have no way to get that out.
Nevertheless, let us assume that a nefarious person did get their hands on a connection string to my database, one that had read and write access. Well, what can it do?
Well, doing something like "UPDATE Sales SET TotalSales = TotalSales * 100 WHERE UserId = @myUserId", and get a hefty commission all of a sudden. But is there really a way to stop it at this point?
It seems to me like at that point, anything more it basically pointless, it is closing the doors with the fox in the coop. Let us take into account the idea of using stored procedures, shall we. What extra security measure do we get from that? The user is already in possession of a connection string with privileges to do things in the database. They can now do things like "while @count < 100 exec AddSaleTo @myUserId".
Oh, you solve that by using windows authentication all the way to the database, and validate permissions on the logged on user? Well, to do that, the web server must also be marked as trusted for delegation. Which means that if the "hacked" server tells the DB to think that it is Super Mario, it will believe it.
Row level security is bad for the same reasoning as before, but it has an additional twist. Doing security in the database level utterly exclude the option to cache data. That is bad, really bad.
Then you have the idea of an application server in the middle. Now we have a bit more structure, we may even be able to do some business logic testing on the incoming requests, but, and this is the critical part. The application server has no way to know that the web server was hacked. As far as it is concerned, those requests now being made to it are valid ones, and it will try to honor the thousands AddSaleToUserMessage coming its way.
Now, you could structure you application in such a way that nothing trusted anything else, but that is not a good way to structure an application. To be rather exact, the cost of untrusting the inner circle is very high. Both in terms of the effort involved and as a result of the design, which would be awkward to work with long term.
Now, the diagram here is fairly typical, I would assume, in fact, this is how OS security is built, by having a trusted kernel. The kernel cannot protect itself from itself. That is why rootkits are possible.
And, like rootkits demonstrate, it contains a very problematic flaw, you cannot ensure that all the nodes will remain trustworthy. And when one of them turns red, it is endgame.
A better approach would be to go with the firewall approach, with the external application explicitly not trusted by the internal one, and all communication be inspected for suspicious activities.
You can imagine it a little the diagram to the right. This is another typical architecture design. This time we are going with the application server route, with a firewall (or an application firewall) in the middle.
That point of yellow is an inspection port, in addition to the usual checks a firewall will make, this inspection port will try to analyze the request with a more domain knowledge. It can then trigger alarms or deny access if it suspect that the external application is behaving strangely. Such things that might trigger it are malformed business requests, too much focus on a single item (such as trying to add sales to a salesperson), etc.
Then again, something else that would trigger it might be a data entry clerk that is typing really fast, or a simply sale on the site that means that a lot of people are suddenly buying this one item, etc, etc.
Something that I would definitely be interested to have is an audit trail, so I can revert changes if needed, or at least follow their logic.
In the end, there really isn't a one good way to secure an application, this requires cooperation from developers, IT, networking, etc. If there was, everyone was using it. And while I do believe in defense in depth, I also believe that once the king is taken, the game is over. Starting with the premise that the attacker has gained an admin control over one of your machine is not a start that you want to be in.