Encrypting Salary value in ASP .NET 2.0 and SQL Server 2005 - asp.net

I have an ASP .NET 2.0 website connected to a SQL Server 2005 database. The site is pretty simple and stores information about staff, including salary.
What is the best way to encrypt the salary value so no-one (including myself) can ever see what it is, except for the authorised staff using the web-app?
I don't want to encrypt / decrypt on the SQL Server because I could just run SQL Profiler to view the information, so I assume the encrypt/decrypt happens in the BLL on the web server?
Also, do I need SSL to stop someone sniffing HTTP responses between the browser and the web server?
Many thanks!
Anthony

SSL is probably your best bet to keep someone from sniffing, but be aware that it is still possible.
As for the other bit, SQL Server 2005 supports table-level encryption out of the box. Here's an article on it. You could create a SALARY table that is linked to an employee and keep that table encrypted.

Developers of the webapp could still access the salary figures -- it's all a matter of trust. To counter that, you could switch to the model where the encryption/decryption happens on the client-side, but this is more cumbersome and still not 100% secure. Security is always a trade-off with convenience.
You should use TLS/SSL (i.e., HTTPS) so that eavesdropping on the HTTP traffic is harder to perform.
An attack you may consider, is replacing your own encrypted salary figure with that of the person you are interested in, then calling up the accounting department and asking what your current salary figure is. One way to negate the attack is to have the contents of the encrypted salary field reference the person it belongs to.

There are many encryption methods you could use here in your code. Make sure you choose one that takes a key and a "salt" (as opposed to just using the same key each time). If you use the same key (without a salt) each time you encrypt a salary, then two employees with the same salary will display the same encrypted value in the database, compromising the security of the salary info.
You could use each employee's unique ID as the salt.

You definitely need SSL to prevent sniffing of the sensitive web traffic (not to mention logins), but that doesn't solve your server-side encryption problem.
To make it impossible for you as the developer to access the data is a tough nut to crack. In order for it to really work, all the encryption/decryption needs to be done only on machines that you have no access to. Theoretically you would have to make some sort of browser extension that decrypts the salary data on the client machines. Your employer would have to trust you enough to not put a backdoor into the client-side code (or at least hold the possibility of a code audit over your head).
In most cases, it is easier to trust the developer to not disclose the data. It's a good idea to keep it on a need-to-know basis, but ultimately some people need to know. (For instance, accounting people see salary data all the time.)

You definitely want to use SSL for the transportation security. You could also setup IPSec for the transportation between the web server and database server.
As for securing in the database, SQL Server 2005 has several encryption functions:
1) EncryptByAsymKey - http://msdn.microsoft.com/en-us/library/ms186950.aspx
2) EncryptByKey - http://msdn.microsoft.com/en-us/library/ms174361.aspx
3) EncryptByPassPhrase - http://msdn.microsoft.com/en-us/library/ms190357.aspx
4) EncryptByCert - http://msdn.microsoft.com/en-us/library/ms188061.aspx
Obviously, all of these have an associated decrypt function.
You can store the key or whatever you choose on the web server (in the machine.config or web.config or somewhere) and then pass it to your stored procedures (or along with your sql somehow) for the encryption.

Related

Encrypting data in SQL Server Azure database with separate key for each user's data

I'm trying to create a service based on an Azure SQL Database backend.
The service will be multi-tenant, and would contain highly sensitive information from multiple "clients" (potentially hundreds of thousands), that must be strictly isolated from one another and secured heavily against data leaks. "by design"
Using so many individual databases would not be feasible, as there will be a lot of clients with very little information per client.
I have looked into the transparent encryption offered by Azure, but this would essentially encrypt the whole database as one, so it would in other words not protect against leaks between clients or someone else; due to development errors, or hostile attacks, and it's very critical that one "client's" information never comes into anyone else's hands.
So what I would really like to achieve, is to encrypt each client's data in the database with a different key, so that you would have to obtain the key from each client (from their "physical" location) to de-crypt any data you might manage to extract from the database for that particular client, which would be virtually impossible for anyone to do.
Is it clear what I mean?
Do you guys have any suggestions for me on how to manage this problem, or know of any third party solution that allows for this functionality? Any other advise?
You're looking at protecting/isolating the tenants "by design" in a single table, why not check out Row Level Security. You could configure it to serve up only the applicable rows to a specific tenant.
This doesn't directly address your initial question about encrypting the data with a separate key for each tenant; If you have a separate table for each tenant, then you could do this via Always Encrypted, but this would seem to have some complexity in key management, if you're trying to handle 200k keys.
AFAIK, there isn't a native SQL Server functionality to encrypt each set of rows that belongs to a tenant with a distinct key- but there may be some elegant solutions that I haven't seen yet; Of course, you could do this on the app side and store it in SQL and there would be no issues; the trick would be the same as the AE based solution above- managing a large number of keys.

Encrypting fields in openerp using db postgres

We are going to store some sensitive information about our customers in the db model res_partners.
However we don't want to store this information in a simple text field. We would prefer
some basic encrypting if possible for those fields. We do not want someone who
has access to the db to have access to these fields.
Is there a way we can get this done in openerp or postgres ?
Thank you,
Vishal Khialani
There is no such thing as "basic" encryption. Rot13 is not getting to get you anywhere here. If your data is sensitive enough to deserve protection, then you need to use state of the art cyphers such as Blowfish. I advise you give a good long look at Bruce Schneier's book Applied Cryptography
The easy (and insecure) way to achieve this is to overload the write and read methods of your model to encrypt before writing and decrypt after reading.
The tricky part is storing the encryption key. You could store it in a file on the computer running the OpenERP server (assuming the database is running on another server). This is still pretty weak, as the key will be available in clear on the server, but could still be useful if you don't trust your database server admin, but do trust you openerp server admin. It's still way easier to get the database server in a secure and trusted place, and if required to crypt offline copies of the database (such as backups).
If you want more security, you'll have to send the data encrypted to the client application, and let the decryption happen there, using a user-supplied key. I'm not enough knowledgeable of this part of openerp to say if it is easily feasible or not.

Best Practice: Protecting Personally Identifiable Data in a ASP.NET / SQL Server 2008 Environment

Thanks to a SQL injection vulnerability found last week, some of my recommendations are being investigated at work. We recently re-did an application which stores personally identifiable information whose disclosure could lead to identity theft. While we read some of the data on a regular basis, the restricted data we only need a couple of times a year and then only two employees need it.
I've read up on SQL Server 2008's encryption function, but I'm not convinced that's the route I want to go. My problem ultimately boils down to the fact that we're either using symmetric keys or assymetric keys encrypted by a symmetric key. Thus it seems like a SQL injection attack could lead to a data leak. I realize permissions should prevent that, permissions should also prevent the leaking in the first place.
It seems to me the better method would be to asymmetrically encrypt the data in the web application. Then store the private key offline and have a fat client that they can run the few times a year they need to access the restricted data so the data could be decrypted on the client. This way, if the server get compromised, we don't leak old data although depending on what they do we may leak future data. I think the big disadvantage is this would require re-writing the web application and creating a new fat application (to pull the restricted data). Due to the recent problem, I can probably get the time allocated, so now would be the proper time to make the recommendation.
Do you have a better suggestion? Which method would you recommend? More importantly why?
Encryption in SQL is really only good for securing the data as it rests on the server, although that doesn't mean that it is unimportant. When you mention that a prime concern is injection attacks or the likes, my concern would be whether or not the database uses a single account (SQL or otherwise) to connect to the database, which would be common for a public internet site. If you use integrated authentication, or connect to SQL using the same credentials supplied to the application, then SQL's encryption might work fine.
However, if you're using a single login, SQL's encryption is going to manage encrypting and decrypting the data for you, based on your login. So, if your application is compromised, SQL may not be able to protect that data for you, as it implicitly decrypts it and doesn't know anything is wrong.
You may want to, as you suggested, encrypt/decrypt the data in the application, and store as bytes in the database. That way you control who can decrypt the data and when (for example, you could assign the key to decrypting this data to those few employees you mentioned that are in a specific role). You could look into Microsoft's Security Application Block, or Bouncy Castle, etc. for good encryption utilities. Just be careful about how you manage the key.
Update:
Although you could potentially use two connection strings: one normal, with no rights to the encrypted data, and one that has the key and the rights to the data. Then have your application use the appropriate connection when the user has the rights. Of course, that's pretty kludgy.
Some practices that we follow:
Never use dynamic sql. It's completely unnecessary.
Regardless of #1, always parameterize your queries. This alone will get rid of sql injection, but there are lots of other entry points.
Use the least priviledged account you can for accessing the database server. This typically means the account should NOT have the ability to run ad hoc queries (see #1). It also means that it shouldn't have access to run any DDL statements (create, drop, ..).
Don't trust the web application, much less any input received from a browser. Sanitize everything. Web App servers are cracked on a regular basis.
We also deal with a lot of PII and are extremely strict (to the point of paranoia) on how the data is accessed and by whom. Everything that comes through the server is logged. To make sure this happens we only allow access to the database through stored procedures. The procs always test to see if the user account is even authorized to execute the query. Further they log when, who, and what. We do not have any mass delete queries at all.
Our IDs are completely non-guessable. This is for every table in the system.
We do not use ORM tools. They typically require way too much access to the database server to work right and we just aren't comfortable with that.
We do background checks on the DBA's and our other production support people every 6 months. Access to production is tightly controlled and actively monitored. We don't allow contractors access to production for any reason and everything is code reviewed prior to being allowed into the code base.
For the encrypted data, allow specific users access to the decryption keys. Change those keys often, as in once a month if possible.
ALL data transfer between machines is encrypted. Kerberos between servers and desktops; SSL between IIS and browsers.
Recognize and architect for the fact that a LOT of data theft is from internal employees. Either by actively hacking the system, actively granting unauthorized users access, or passively by installing crap (like IE 6) on their machines. Guess how Google got hacked.
The main question in your situation is identifying all of the parts that need access to the PII.
Things like how does the information get into your system? The main thing here is where does the initial encryption key get stored?
Your issue is key management. No matter how many way's you turn the problem around, you'll end up with one simple elementary fact: the service process needs access to the keys to encrypt the data (is important that is a background service because that implies it cannot obtain the root of the encryption hierarchy key from a human entered password whenever is needed). Therefore compromise of the process leads to compromise of the key(s). There are ways to obfuscate this issue, but no ways to truly hide it. To put this into perspective though, only a compromise of the SQL Server process itself could expose this problem, something which is significantly higher bar than a SQL Injection vulnerability.
You are trying to circumvent this problem by relying on the public key/private key asymmetry and use the public key to encrypt the data so that it can only be decrypted by the owner of the private key. So that the service does not need access to the private key, therefore if compromised it cannot be used to decrypt the data. Unfortunately this works only in theory. In the real world RSA encryption is so slow that is cannot be used for bulk data. This is why common RSA based encryption scheme uses a symmetric key to encrypt the data and encrypts the symmetric key with the RSA key.
My recommendation would be to stick with tried and tested approaches. Use a symmetric key to encrypt the data. Use an RSA key to encrypt the symmetric key(s). Have SQL Server own and control the RSA private key. Use the permission hierarchy to protect the RSA private key (really, there isn't anything better you could do). Use module signing to grant access to the encryption procedures. This way the ASP service itself does not even have the privileges to encrypt the data, it can only do so by the means of the signed encryption procedure. It would take significant 'creative' administration/coding mistakes from your colleagues to compromise such a scheme, significantly more than a mere 'operator error'. A system administrator would have an easier path, but any solution that is designed to circumvent a sysadmin is doomed.

How to hide my data stored in database from domain administrator of web server?

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.

Encrypt data from users in web applications

Some web applications, like Google Docs, store data generated by the users. Data that can only be read by its owner. Or maybe not?
As far as I know, this data is stored as is in a remote database. So, if anybody with enough privileges in the remote system (a sysadmin, for instance) can lurk my data, my privacy could get compromised.
What could be the best solution to store this data encrypted in a remote database and that only the data's owner could decrypt it? How to make this process transparent to the user? (You can't use the user's password as the key to encrypt his data, because you shouldn't know his password).
If encryption/decryption is performed on the server, there is no way you can make sure that the cleartext is not dumped somewhere in some log file or the like.
You need to do the encryption/decryption inside the browser using JavaScript/Java/ActiveX or whatever. As a user, you need to trust the client-side of the web service not to send back the info unencrypted to the server.
Carl
I think Carl, nailed it on the head, but I wanted to say that with any website, if you are providing it any confidential/personal/privileged information then you have to have a certain level of trust, and it is the responsibility of the service provider to establish this trust. This is one of those questions that has been asked many times, across the internet since it's inception, and it will only continue to grow until we all have our own SSL certs encoded on our fingerprint, and even then we will have to ask the question 'How do I know that the finger is still attached to the user?'.
Well, I'd consider a process similar to Amazons AWS. You authenticate with a private password that is not saved remotely. Just a hash is used to validate the user. Then you generate a certificate with one of the main and long-tested algorithms and provide this from a secure page. Then a public/private key algorithm can be used to encrypt things for the users.
But the main problem remains the same: If someone with enough privileges can access the data (say: hacked your server), you're lost. Given enough time and power, everything could be breaked. It's just a matter of time.
But I think algorithms and applications like GPG/PGP and similar are very well known and can be implemented in a way that secure web applications - and keep the usability at a score that the average user can handle.
edit I want to catch up with #Carl and Unkwntech and add their statement: If you don't trust the site itself, don't give private data away. That's even before someone hacks their servers... ;-)
Auron asked: How do you generate a key for the client to encrypt/decrypt the data? Where do you store this key?
Well, the key is usually derived from some password the user has chosen. You don't store it, you trust the user to remember it. What you can store is maybe some salt value associated to that user, to increase security against rainbow-table attacks for instance.
Crypto is hard to get right ;-) I would recommend to look at the source code for AxCrypt and for Xecrets' off-line client.
Carl
No, you can't use passwords, but you could use password hashes. However, Google Docs are all about sharing, so such a method would require storing a copy of the document for each user.

Resources