Background Information:
I'm part of a team of developers that runs a web application that stores and retrieves HIPAA (medical) data. Recently, the HIPAA guidelines were updated to include a policy that requires that all identifying client information be encrypted when it is "at rest" (stored in the database and not being accessed).
The Initial Problem
The first problem we had to tackle was determining the best way to two-way encrypt the data in a manner that makes the data secure in the event of a breach.
The initial Solution
The quickest solution we came up with was to use mcrypt to encrypt the data before we inserted it into the database.
The New Problem
The application we're developing is quite old (as web applications go) and uses a lot of procedural programming as well as heavy reliance on the mysql_query function to insert, update, retrieve, and delete data. We do not have the time or luxury of translating our code to a database-abstraction-layer. So, the only way to implement this encryption/decryption system is to manually edit all of the CRUD queries to use data that's been encrypted via mcrypt. This is very inefficient and extremely error-prone.
Our Proposed Solution
We decided that the fastest and most effective way to solve our problem is to overwrite the native mysql_query function with one of our own devising. In our new function, we would encrypt/decrypt the data values before sending the query to the server/ returning the resultset.
Where You Folks Come In
Is this the best solution to solving our initial problem?
How do you go about overwriting an existing, core PHP function?
Although you've previously stated you can't/won't translate your code into a database abstraction layer, I believe that would be the ideal solution. Sure, it's a lot more work right now, but it pays off. What you've proposed is a hack, that can (and probably will) lead to errors and headaches in the future.
The next best thing would be to encrypt the whole database, as proposed in the comments. There are solutions out there for transparent encryption in different levels, ie: this or this
Another thing you might want to look into is MySQL's native encryption and decryption functions, which could be used to implement column-level encryption if you're concerned about performance.
While the best solution would be the abstraction layer that the other answers have suggested, you can override existing PHP functions with your own versions with the PECL Runkit extension
Something like:
runkit_function_rename ( 'mysql_query', 'mysql_query_old' );
function mysql_query ( $query , $link_identifier=null ) {
// modify $query here for UPDATE/DELETE statement and any WHERE clause, etc
$newQuery = modifyQuery($query);
if (is_null($link_identifier)) {
$result = mysql_query_old ( $newQuery);
} else {
$result = mysql_query_old ( $newQuery, $link_identifier);
}
// modify $result here for returned data from any SELECT statement
return modifyResult($result);
}
Note: By default, only userspace
functions may be removed, renamed, or
modified. In order to override
internal functions, you must enable
the runkit.internal_override setting
in php.ini.
It's not a solution I'd really recommend. I had to do something similar some years back in java, where it was far easier to extend jdbc; but while parsing the syntax of SQL queries is hard enough, it gets harder still if your queries are using bind variables. Watch out for escaped strings! Watch out for any use of related function like mysql_db_query, just in case they're used alongside mysql_query within the application!
Apologies for shaky typing. My wife has been bouncing our router a few times while I'be been writing this suggestion
I think one way of handling this automatically would be to look into MySQL proxy
and implement encryption through that. I played around with it 2 or so years ago when it was in a very early stages, and from what I remember it could basically intercept requests and do 'stuff' with them :) No code change required essentially.
Hopefully this helps.
There are commercially available solutions to help with data at rest encryption. You can check out either Gazzang or Packet General. Both offer MySQL encryption to help with HIPPA compliance. Good Luck
You could encrypt at the file system level, and let the OS handle it. If you wish to handle it at the PHP level, extend, don't overwrite.
function mysqle_query() {
// Do some stuff
// like replace fieldnames with AES_ENCRYPT(fieldname) on insert and delete
// and replace fieldnames with AES_DECRYPT(fieldname) on select
mysql_query();
}
I really think you are looking at this from the wrong perspective. This is not a problem to be solved by developers via encrypting/decrypting data as you store and retrieve it from the database - use an infrastructure solution.
Consider hardware or software whole disk encryption, encryption of the database itself via the RDBMS's transparent data encryption function (if the particular RDBMS has one), or via the OS.
See this document from NIST
Related
I am making a login, and will use this for registration, and am allowing symbols and special characters in emails and passwords. I know that this poses a serious threat for hackers with injections. My question is: How might I turn the inputs from fields (ex. 'email', 'password'), into strings and not allow the server to process them as code and commands.
I truly have very little clue as to where to start, but have tried mysqli_escape_string; but, as you most likely know, it is very thin and deprecated. I don't mind researching a little, I would just greatly appreciate a bit of information to get started!
If you really do have no idea where to start, that's not a bad thing! However, I recommend not trying to go create you're own login/registration system unless you do know what to do. Especially if you care about security. This is an extremely easy thing to mess up, even for seasoned programmers. I will be the first to admit, I spent a lot of time rolling my own login/auth modules in PHP, and also spent a lot of time inheriting code where other people implemented their own method, most of the time, improperly.
I recommend learning a web framework. My favorite Web frameworks for PHP are Laravel, and Code Igniter, Laravel being my favorite. You'll find that you'll have a learning curve here as well, but you will find a lot more support for implementing user authentication correctly and securely. For exampe: http://laravel.com/docs/4.2/security
With a framework you could also get lots of helper methods to make DB access fun, easy, and safe. Check out the examples here! You can always use raw sql if you want!, but for your day-to-day CRUD applications, there is no need!
If you still absolutely insist on doing it yourself, though I will warn you against it one final time. I recommend using PDO or MySQLi prepared statements (I prefer PDO).
My guess is that the app isn't too far along since you're still considering how to build login/registration, so you're probably not "stuck" using raw php and doing it all yourself. :)
Use prepared statements when executing mysql queries. (more details here)
Limit input field length when possible (normally a mysql injection queries are long. This prevents execution of altered longer queries even there is a vulnerability made by a mistake)
Give only the permissions needed for mysql users. Wherever you only need the user to read, provide only read permissions.
Encrypt sensitive data like passwords. Use salted password hashing.
I have my own crypt/decrypt function in PHP which is on my server.
I feel it is not a safe thing to store it in my server as if one day we get to be hacked. The hacker can decrypt easily our datas.
Would like to know if is there is solution to this ? How can we protect our own PHP functions ? Is it better to store the decrypt function in another server.
Thank you in advance for your answers !
It looks like you want to disregard Kerckhoffs's principle and that is fine in some cases. If you want to encrypt data at rest, then there is essentially nothing you can do besides obfuscation (PHP code "encryption" techniques are nothing more than clever (?) obfuscation).
For example: Since every obfuscation can be reversed with enough time (but not so much time what would needed to break an encryption), a key that was used to encrypt the data and which is embedded in the code can be extracted and your data decrypted.
If the server only stores encrypted data (which I somehow doubt because that would make it not very useful) and never uses the decryption, only then it would add some security to your arrangement by out sourcing the decryption function. This would raise the bar, because the attacker would need to exploit (possibly other) weaknesses of the second server.
Do Not Implement Your Own Crypto
Never try to develop your own crypto. You should choose use one of tested and trusted by professional. Please watch this video I believe you will understand why you shouldn't implement your own crypto. ( https://www.youtube.com/watch?v=3Re5xlEjC8w#t=49 )
If you really want yo use your own crypto, you may want to encode your php application. Because likely to you are going to store your private key into your source codes.
Example for Plain-text form of PHP source code.
It will be something like when you encode your this php source code.
Further information : http://www.virtual-apps.com/post/security-and-performance-benefits-of-encoding-php-files
I have a weird question,
Is it possible to encrypt mssql sp or triggers or even queries? like in php base64 system.
If it's possible, can someone provide me a link of the method or a small tutorial explaining how to use the encrypted method to be read from sql?!
all I want is a small encryption method that allows me to encrypt my queries and let the sql read it over the encryption itself. just like php
If I understand correctly you want encryption to happen in SQL itself. I would suggest against this as it kind of defeats the whole purpose of encrypting the data. The reason behind it is usually that if a 3rd party gains access to your database (and not application code), they still cannot read the data. If you set encryption to happen in SQL, then they will be able to decrypt the data.
If this is not what you've wanted, then sorry for my wasted reply.
I am using a Postgres 9.3 database as a back-end for a web application. I use PHP 5.5.7 to connect to the database and return JSON for the front-end AJAX calls.
I'm trying to decide on where to put the user authentication logic.
I am not a security expert; however, I am familiar with PHP's new password_*() functions and I have a strong grasp of what is going on under the hood. I am also familiar with the Postgres Extension pgcrypto and the associated crypt() function.
My question is, does it make sense to use PHP or Postgres to hash passwords?
I was curious as to how these functions differ, so I made a password hash in PHP and then gave it to Postgres to see if Postgres uses the same algorithm. Given the same parameters, Postgres returned a different result when compared to PHP (not unexpected, but with noting).
PHP
password_hash('password', PASSWORD_BCRYPT, ["cost" => 15]);
output: $2y$15$o8JufrnVXoob2NKiEGx6.uI4O2D4VcaAmY7WtNq5zPFiJow4KohGu
Postgres
SELECT '$2y$15$o8JufrnVXoob2NKiEGx6.uI4O2D4VcaAmY7WtNq5zPFiJow4KohGu' = crypt('password', '$2y$15$o8JufrnVXoob2NKiEGx6.uI4O2D4VcaAmY7WtNq5zPFiJow4KohGu')
output: false
PHP vs. Postgres
Given that these processes are different, I wonder if one is better then the other? Is one more, or less, secure?
Some other thoughts:
I currently have all logic stored in the database (in views, functions, constraints, etc.) so if I ever need to use a different front-end I don't have to worry about missing logic. Calculating password hashes in PHP would effectively require all requests to pass through PHP to access the database.
On the other hand, putting the logic in the database would allow me the flexibility to use other connection options; however, all of the Postgres queries are logged. I can't disable the logs because of the WAL used in replication. This seems like a big security hole.
Am I on the right track here? What am I missing?
EDIT
I just looked at another message thread and found some more information.
Putting the logic in Postgres would require the database to processes and perform the hash operation. This would be a bad thing for other users and batch jobs that need those resources.
Not only would the hash slow down normal operations, it would make the whole system more vulnerable to DOS attacks.
Our simple web servers with load balancing would address both issues...
Again, am I on the right track here? What else am I missing?
For the difference between versions 2y and 2a, see this thread and the various links within it:
https://security.stackexchange.com/questions/20541/insecure-versions-of-crypt-hashes
My understanding is there was a problem with the 2a implementation in PHP until v.5.3.8, though only for strings that contained non-ascii chars. PgCrypto, as you noted, doesn't "speak" 2y for some reason, and I'd assume it suffers so such problem. (Perhaps report this as a bug?)
Apart from the points raised in the latter, you nailed the main security difference between the two in your question: systematically hashing the password within the database is convenient but implies that you send it to your database in clear text, where it can (and will) be logged — or snooped at outright, if your DB connection is not encrypted.
In an ideal world, you'd hash the password in the client app using javascript before it's even sent to PHP. The next best thing is to send it using SSL to PHP, then hash it using PHP before sending it to the DB.
Aside: I'm pretty certain that PHP's crypt can generate a (secure) 2a version hash if you need interoperability for some reason.
I am making a CMS which can be extended by third-party developers. In the past I have had problems with newbie developers ignoring security all together. When they put their modules on my website, they are potentially compromising users websites.
I want to create a globals object. This will overwrite all globals with a sanitized copy. This could cause issues, so this object will also provide an option to get unsanitized data.
This way, by default, developers could theoretically do something like this and it's effect wouldn't be as bad as it usually would be. (Obviously this would still potentially cause problems however tables won't be dropped and data won't be exposed.)
mysql_query("INSERT INTO users (`name`) VALUES ('{$_POST['name']}')");
This doesn't protect against developers who intentionally try to break things. However, it will help eliminate basic mistakes.
The end object would be accessed as follows.
$_POST['key']; // Provides Sanitized version of the post key.
$obj->post('key'); // Provides Sanitized version of the post key.
$obj->post_raw('key'); // Provide unsanitized version of the post key.
What do people think about this approach? Is there a proven 'escape all' function floating around that would achieve this?
You're basically talking about reimplementing magic_quotes_gpc. It didn't go that well when Zend did it.
The largest problems are 1) different forms of data protection are necessary for different contexts, and 2) if somebody is too much of a noob to do elementary data security, they're definitely too much of a noob to understand what data your auto-protection mechanism has been applied to and which it hasn't. (They will source data from places your mechanism does not and cannot touch; take this as a given.)
No, it's really difficult to have a generic sanitizing function. It's always use-specific. And let me thus recommend something else:
http://sourceforge.net/p/php7framework/wiki/input/
It basically overwrites the superglobals $_GET, $_POST with objects. This prevents raw access, and you get either notices or log errors if no appropriate filter is used. You still have to think about which filter to use, but at least this method can be used to coerce co-developers on spending a few seconds to give it a thought. Also it's really easy to apply:
$_GET->text["comment"]
mysql_query("SELECT '{$_REQUEST->sql[field]}'");
$_POST->nocontrol->utf7->xss->text["text"];
It's also possible to predefine filter lists for specific input variable names. Or set a filter for all old array accesses with $_POST->xss->nocontrol->always(); It needs some getting used to, but it's really the simplest API possible and meant just for cases like you describe.
You may want to check out http://code.google.com/p/inspekt/ , which pretty much already does what you describe.
Security is a very complicate and delicate subject IMHO.
I'm not sure if you should even allow unsafe access to data. I'd make access only to sanitized contents, and also enforce use of prepared statements.