Webserver on the fly decrypting? - php

I am dealing with a concept for a project that involes absolutely critical data.
The most important part is that it needs to be stored encrypted.
An encrypted file system that is mounted from which the webserver serves the files is not enough.
The key to decrypt the data should be passed in the request URI on a secured connection along with a hash and a timestamp.
The hash, based on timestamp, key and filename validates the URI and stores it on a list, so it can only be accessed once.
The important part now is that the webserver should take the file from the disk, and serve it decrypted using they key he got from the request URI.
It should also be efficient and fast. This also requires an encryption method that does not require the whole file to be scanned. so that the file can progressively be decrypted. I think AES can do this with specified block sizes that are encrypted atomic.
So one option would be reading the source file into a php script in chunks of some megs where i decrypt using aes and print the decrypted content. The script then forgets the previous data and continues with the next chunk until eof.
If aes doesnt support that i can just encrypt chunks of defined size of the file seperately, concatenate them and do it the same when serving the files. however i would like to stick to one standard that i dont have to re invent, so i can also use standard libraries to encrypt the files.
However this will be very inefficient.
Do you know of any apache/lighttpd/nginx module or some better method?

You should open the file with nmap() and then encrypt the data on-the-fly as needed.
I don't see anything more appropriate for this than G-Wan (200 KB), which offers native C scripts and AES encryption (no external libraries needed even if C scripts can link with any existing library).
If you need to achieve the best possible performances, then this is the way to go.

You may want to look into PHP's Stream Filters ( http://php.net/stream.filters ); with a bit of glue code, you could make it read an encrypted file with the regular PHP file access functions, and it would be mostly transparent to existing code.

If you can't find a PHP module that lets you decrypt the files chunk/block-wise, you can always pre-split the file into appropriate sized blocks and encrypt each seperately.
Of course, remember that even if you're only sending out small pieces of the plaintext at a time, there's still plenty of other places that this vulnerable data can be held - particularly in the web server's output buffers. Consider the extreme case of a large-ish file being downloaded by someone stuck on a 2400 baud modem. You may very well decrypt and queue the entire file before even the first chunk's been downloaded, leaving the entire file in the clear in a buffer somewhere.

There's no off-the-shelf solution to provide what you require. And while you've provided a bit of information about the data will be retrieved, you've not given much clues as to how the data will get on to the webserver in the first place.
You're jumping through lots of hoops to try to ensure that the data is not compromised - but if you're decrypting it on the server, then there is not only a risk of the data being compromised - but also that the key will be compromised. i.e. there's more theatre than substance in the architecture.
You seem to be flexible in the algorithm used for the encryption - which implies that you have some control over the architecture - so there is some scope to resolve these problems.
The hash, based on timestamp, key and filename validates the URI and stores it on a list, so it can only be accessed once.
How does that ensure it is only accessed once? Certainly it could be used to reduce the window of opportunity for CSRF - but it does not eliminate it.
The script then forgets the previous data and continues with the next chunk until eof.
This fundamentally undermines the objective of encryption - patterns within the data will still be apparent - and this provides a machanism for leveraging brute force attacks against the data - even if the block size is relatively large. Have a look at the images here for a simple demonstration.
A far more secure approach would be to use CBC, and do the encryption/decryption on the client.
There are javascript implementations of several encryption algorthms (including AES) this page has a good toolkit. And with HTML5 / localstorage you can build a complete clientside app in HTML/javascript.
As you're starting to discover - just using a clever encryption algorithm does not make your application secure - it sounds like you need to go back and think about how you store and retrieve data before you worry about the method you use for encrypting it.

Related

Simple but fast binary file de/encryption using PHP

I need to implement a simple (not ultra-secure) but fast file en/decryption using PHP, so files are encrypted on upload and decrypted on download. Files are mainly images (jpg) and videos (mp4), and some videos are up to 30 MB, so my idea is to encrypt only the first X bytes of each file, just to avoid anyone that could have access to the server (ie. support people) to open the files from users.
I am new to this subject and after almost 6 hours researching found only old examples, using deprecated Mcrypt.
Please, can anyone give me tips to start? Is there any native method from PHP that I can use, or maybe an open-source library? Does Mcrypt would be an option, even if deprecated (I am using PHP 5.6). Do you think encrypting only the first X bytes of the file is a good approach in my case?
Thanks!
Here is a PHP encryption library: https://github.com/defuse/php-encryption
I found this just by googling, I can't vouch for it's reliability or security. There are documentation and examples on that page.
However I really would ask you to take a step back and consider what the purpose of this is and what the wider security considerations are. In order to do this successfully then there will need to be some security secret, either a key or a password, that will need to be kept hidden from the people that you don't want to be able to decipher the data. I can imagine that would be difficult if those people are the support staff. If you made the password the users login password you are setting yourself up for widespread data loss when a user forgets their password. Also at some point it will need to be unencrypted and you will need to think about making sure that is not leaked at this point. And then you need to think about who has access to the source code that handles the file access, and the key/password code. What about server logs and caches? Etc etc
Furthermore if you are only encrypting the first X number of bytes and don't need to make it 'ultra-secure' then I wonder why you are attempting to do it this way at all? I'm not sure what problem it is you are trying to solve.
Given that doing encryption properly is not simple (not to mention costly in terms of computing resources), but if you don't do it properly it isn't much good then I can't help suspect you will probably be much better off spending the effort making sure that untrusted persons only access information on a need-to-know basis and all access is logged in order to keep people honest.

Store 'sensitive' data in MySQL DB

How should 'sensitive' data be stored in MySQL Database?
1) Should I focus more on the security of the MySQL database and store the data as plain text?
I found a step by step tutorial on how to make a MySQL database more secure:
http://www.symantec.com/connect/articles/securing-mysql-step-step
2) Should I encrypt the data?
If yes, then how should the encryption be done?
Using MySQL aes_encrypt/aes_decrypt?
Using PHP AES functions/algorithm for encrypting/decrypting data?
How should the data be stored in MySQL?
BLOB
BINARY
VARBINARY
In my case the 'sensitive' data are payments done by individuals.
Thanks
It's a mixture of both. Two existing answers (at the time I wrote this https://stackoverflow.com/a/10718397/1015483 and https://stackoverflow.com/a/10718459/1015483) are valid - you need to look at about 5 methods of possible attack that I can think of
They get access to your DB server; so yes, secure that baby as much as is reasonable (Matt's answer)
Stand alone data hijacking (someone gets to your database data somehow else, could be a backup, could be they guess a password, could be MITM if you transfer data from one place to another). For this, you do encypt your data. You also may do a CSV dump for some reason and e-mail to someone. Whoops. But it happens. So encrypt (vlzvt's answer)
But three elements not mentioned:
They could gain access to your web server (if different from your DB server). If they have access to the webserver, all bets are off as they have your password, encyption keys the lot. So you need to make that even more secure than the DB server. (Matt might have meant that above - but just make it clear)
Similar to above, but not to be forgotten, is if someone gets access to phpMyAdmin or your management consule. Don't use plain text auth or config stored passwords for access.
Finally there's your application itself (and the hardest to lock down). You need to prevent against SQL injections that may reveal data. Encrypting the data would stop minimise problems if someone did gain access through an untrapped query - so for this, encryption is the solution.
For part 2 of your question:
Using MySQL encrypt/decrypt functions will stop someone who has access to the raw data, but not MITM or SQL injection or even CSV dumps taken for transport.
So, IMO (and it's only my opinion and the way I've done it) is to encrypt with PHP and sned the encrypted data over the wire, as that stops all methods of trapping the data, and a CSV dump will be "scrambled".
If you do that, you may as well use the varbinary / blob types as it stops you accidentally trying to read/edit in phpMyAdmin. Plus potentially saves a few bytes nominally (although this depends on indexes and other stuff - so that alone is not a winning argument).
And now the down side: searching and sorting. Anything you index or search on, if encrypted, will only match the entire, exact, case sensitive string padded to the correct length (normally a search will be case insensitive, and you can do part searches with LIKE). And if you want to ORDER BY then you need the original strings. So bear than in mind when designing the structure.
Hope that helps.
What's the worst possible scenario if an attacker gets access to the plain text data? Given that you have to decrypt data in order to make it useful and you therefore need the encryption key to be somewhere accessible too, any attacker who can get to the DB will likely be able to get to the key as well, unless this is for archiving rather than e.g. a live website. I'd focus on the DB server security, unless you're carting HDDs around full of data which might get lost, but it really depends on why you need to encrypt it.
if you need to secure the data in your possibly hacked database, you can encrypt it
with mcrypt
$key = "mykey";
$crypttext = mcrypt_encrypt(MCRYPT_RIJNDAEL_256,$key,$data,MCRYPT_MODE_ECB,$key);
after that you can select BLOB,TEXT,MEDIUMTEXT or anything, based on the ~expected data size.
* for VARBINARY/BINARY you might need to pack it first.
The encryption operation has additional cost.
You need evaluate if in your scenario, this additional cost will be a problem, per example, if your data grow to considerable size.
The first frontier to avoid data leaks is a strong data access policy with profiles of access an so on. This has the disadvantage that you will need to manage the mysql and configurate it.
If you want care about the managment of profiles, you can encrypt the data assuming the extra cost in CPU and (depend of encyption algorithm) a extra storage space.
The security of the a system is equals to the security of more weak component, don't focus your effort only in encryptation task, this only give you the sensation of security, if the data can be decrypted, the only thing that the intruder needs is time and bruteforce to break the encryption

IonCube extra layer of security ?

I am now working on a php project(Internet Shop) that will possibly deal with storing locally customer credit card information.
So I was thinking among other things about encrypting php files with IonCube, especially those containing settings(encryption/decryption key, IV) for
symmetric encryption algorythm. So I'm not sure if it will add an extra layer of security or not, since it appears IonCube-encrypted
files and similar solutions can be decryped.
Thank you!
IonCube is not a suitable solution here. If you encode a file which contains something along the lines of:
<?php $SecretValue = "xyzzy"; ?>
It's still trivial to recover the secret value:
<?php require("encoded.secrets.php"); print $SecretValue; ?>
So the IonCube encoding is basically worthless here.
ionCube and Zend are fine for code protection, and even if some decompilation service produced usable code from an encoded file, this would typically do little if anything to diminish the benefits from encoding and license enforcement, and may even result in increased revenue in the longer term for the software provider.
Data hiding, however, is entirely different. Keep in mind that PHP and all of the associated library wrappers, plus the libraries themselves, are opensource and therefore easily modified. Data sent into and returned from any PHP function can be easily exposed by simple changes to the PHP internals. Want to see the database password to MySQL? Just modify the mysql_connect() wrapper or the underlying MySQL library and log the details. Some encoding systems, for example ionCube, can encrypt non-PHP files and then decrypt at runtime via closed source routines in their runtime component, which may in some cases provide some benefits over the opensource PHP routines such as mcrypt.
duskwuff is not entirely incorrect with the example cited as in some systems, ionCube for example, it is possible to protect files from being included by non-encoded files, or files encoded by a different copy of the Encoder through a mechanism called "include attack protection". None the less, storing sensitive data in variables, particularly globals is a poor approach, and it would be better to have such data returned by a function with a misleading name and that perhaps performs differently unless called in a particular way. e.g. a function called mytime() that does return the time unless called with a "magic" value.
If you're going to encode/encrypt your files, Zend Guard is supposed to be one of the best, but as others have said, if they can get to your files that's the least of your worries.

2-way encryption in PHP - need some guidance

I'm working on my first secure shopping site. We're not storing credit card data, so that's not a problem. However, we do have a transaction key and API login key for our payment gateway (authorize.net) that I'd prefer to keep in a database, rather than hard-coding into my php. I don't know that we need tremendous security, but I would rather not store it in plain text. I know about sha, but that's one-way. I need a way to store the value in the database in a semi-secure format, but then be able to "decrypt" it programmatically for use in my function.
An additional caveat to this is that my site is hosted, which means there's a very tight limit to what kind of stuff I can install, so ideally any solution would rely on something that's included with a standard php install.
Can anyone point me in the right direction? I'm very new to securing data.
EDITED TO ADD: I checked with my host and mcrypt is installed. Is this the right direction to look in?
MCrypt can be your friend here. What you do need to take into account, though, is that every publicly available (and useful) encryption method requires a key. If AES encryption or 3DES encryption didn't require a key during the encryption process then breaking the encryption would just be a matter of trying every standard decryption method until you got a meaningful result. Thus, storing the key for your payment gateway incurs the exact same risks as storing the key for your encryption. No matter how many layers of encryption you want to add, at some level there will have to be a key stored in plain text, usually hard-coded into the PHP and often in an included config.php file to make it easy to change in the future.
The only option for securely storing information without the need for a key would be to invent your own encryption method. The security of this method lies solely in the fact that no one knows the means by which you are encrypting the string, so they don't have a step-by-step pattern to just walk backwards through. If you ever told someone how your encryption worked, though, then the security would be forfeit. Also, there are many algorithmic ways to break simple encryptions (letter replacement, for example). This is why mathematicians get a lot of money for developing things like AES.
Your best best is to look into MCrypt Encrypt and MCrypt Decrypt. This way if just your PHP is compromised then they know the key you used to encrypt, but they don't have the data. If just the database is compromised then they have the data but not the key you used to encrypt it. If both are compromised, you're screwed. But if both are compromised you're screwed no matter what you do, so that's a fairly safe route.
Hmm, you can try AES encryption. The problem is that you have to save the salt hash(98sdfx9c6v5c) somewhere in your PHP.
Insert config:
INSERT INTO config (secret_key) VALUES (AES_ENCRYPT('secret api key','98sdfx9c6v5c'));
select config:
SELECT AES_DECRYPT(secret_key,'98sdfx9c6v5c') AS secret_url FROM config
From a security perspective, there's no difference by storing it in the php files or in the database, if someone has access to your php files he has access to the database as well.
working with mcrypt doesn't mean you will have MORE security, (if they can read your php files they can read the key as well) so...
If I were you i'd store the API key in plain text on a file outside the web server directory.
just write good code you should be fine.

get firefox to decrypt using private portion of client certificate

I am interested in having something that I encrypt using a public key on a LAMPhp server, decrypted using the appropriate private key on the web client (firefox at least, best if it is standard javascript)
Note that what I want to do is -not- merely to have an encrypted connection using SSL/https. Or even to use browser-based client certificates as a login/access control method. I know how to do both of those things. What I want to do is more like emailing with gpg keys. I want to be able to create a short message that I will encrypt with a users public key that -only they- can decrypt using their private key. What I am looking for is not the privacy achieved automatically by ssl, but the ability to allow only particular users to decrypt messages. I know I can easily do this with gpg or perhaps SMIME, and perhaps that is the best way, but I would prefer a web-based alternative.
Firefox etc have a certificate stores, and I know that the private keys held there are unlikely to be exportable into javascript for obvious security reasons, but I would assume there is some way to -use- the certificates from javascript calls to decrypt something..
The reason I would like to do this, is that I need a secure method to give a randomly generated password to a particluar administrator. I am trying to implement full database translucency and public key cryptography seems like an important part of that effort. But this is one use-case that I am having trouble addressing without this kind of ability.
So on the php side I would use the openssl encryption calls like so...
<?php
$browsers_public_key = get_it_from_the_browser_via_apache_maybe();
openssl_public_encrypt($data,$encrypted_ends_up_here,$browsers_public_key);
echo "<html><head>
<script type='javascript'>
function decrypt_textarea(){
??
}
</script>
</head>
<body><textarea id='decrypt_me'> $encrypted_ends_up_here </textarea>
<div id='where_the_plaintext_goes'> </div>
</body> </html>";
?>
Note that I have found via stackedoverflow many fine javascript encrypton libraries... but I actually want to use keys imported into Firefox as per MyOpenId.com or CaCert.org
Does anyone know if this is possible?
Thanks,
-FT
It's been a while since you asked this question, but if you or anyone else is looking for a potential solution to this problem or a similar one, they should check out the JavaScript Forge project:
http://github.com/digitalbazaar/forge/blob/master/README
This project has an SSL implementation in JavaScript that will allow you to include a client-side certificate when communicating with Apache. You can also manually do RSA decryption using the associated private key (which you have access to in JavaScript).
For instance, the JavaScript could get/post to the server and include its client-side certificate. Apache could read this certificate, use the public key to encrypt whatever data is appropriate, and then return that data to the client. The client could then use its private key (in JavaScript) and decrypt the information and do something with it. This extra encryption is probably not even be necessary, however, if your server can authenticate the client-side certificate as the appropriate recipient of the secret you're trying to pass.
The Forge project also has the APIs to build a system for importing/exporting keys and certificates to/from Firefox or other browsers (if this is still a requirement for some reason). A little help from openssl might be necessary to get the keys/certs in the correct format for import/export (pem => pkcs12), but an example of how some of this works can be found in a JavaScript-based demonstration of WebID. WebID is a client-side certificate-based authentication system:
WebID management demo: https://webid.digitalbazaar.com/manage/
WebID authentication demo: https://payswarm.com/webid-demo/
Note that the SSL certificates for the above sites are self-signed and will require temporary exceptions to be added to your browser to view them. The sites do not require you to enter any personal information, they are for demonstration purposes only. However, if you go to the first link, you can generate keys in-browser (it uses Forge JavaScript to do this) and then you can see the private key and certificate that were generated, in PEM format, in the list at the top of the page. The key and certificate are persisted via Flash local storage.
Nearly 100% (if not that) of the source for the WebID management site is viewable since it is mostly JavaScript. Also, the Forge project itself (see the github link) is opensource.
Now that I understand what you're saying, I can give you a firm answer :)
The best I can tell you is that you can't get decent encryption in the way you're looking to do it. Private key encryption (namely RSA) uses very, very, very large numbers to do encryption. Using small numbers is very simple to crack computationally (there are only so many prime numbers) and the numbers get big extraordinarily quickly. Basically, with RSA, you need to take large numbers and raise them to large exponents. JavaScript is able to support quite large numbers, but you'll hit a wall with performance. With a 512-bit key, encryption of a few kilobytes can take up to a few seconds, while decryption can take seconds to minutes to do. The reason JS is so slow is simply because it's not a compiled language. Sure, you could decrease the key size, but anything larger than a couple kilobytes and you've got a problem.
Also, RSA is inherently insecure in a web page because the private key is transmitted alongside the data to be decrypted (unless it was transferred earlier), which enables anyone that receives the page to decrypt the data.
I'm going to assume that you're looking to do this because you want to obfuscate some code from your user or a client, so I'm going to recommend that you check out XOR encryption. Granted, it's nowhere near as secure as RSA, but it uses principles that can be very secure if used properly. For instance, if you use a random key that's used only once and has the same length as your data/code (an one-time pad), your encryption is "uncrackable". Even better, XOR encryption is FAST. Here are some resources:
http://guymal.com/mycode/xor_js_encryption/
http://javascript.internet.com/passwords/xor-encryption4.html
Hope you have luck with what you're trying to do!
I am searching exactly the same thing you do and wanted to use php's openssl-functions, too.
I was happy to see that on the phpside everything was working great with private/public key (encrypt/decrypt) and now wanted to find a way to use privatekey on clientside as you do.
!!!
IF you will find anything please let me know by email:
pki (at) life.de
!!!
And for the performance aspect:
You would encrypt the big parts with symetric encryption and only the decryption key with the public key of the client to excahnge it. So you dont't need to enrypt many kb.
But it seems to be an dead end with firefox, but with IE and ActiveX it seems possible with
CAPICOM (I had not much read about it now).
hxxp://geekswithblogs.net/shahed/archive/2007/05/03/112232.aspx
But for JavaScript/PHP have a look at (and read all comments at FAQ and other pages,too!In future maybe bidirectional communication was mentioned):
hxxp://www.jcryption.org/
hxxp://www.zend.com//code/codex.php?ozid=1323&single=1
Pure Javascript Public/Privatekey encryption
hxxp://shop-js.sourceforge.net/crypto2.htm
A helful FireFox-Addon for PKI:
hxxps://addons.mozilla.org/en-US/firefox/addon/4471
hxxp://www.mozilla.org/projects/security/pki/nss/tools/index.html
PHP with OpenSSL on Serverside / .NET on CLientside
hxxp://www.csharpbydesign.com/2008/04/asymmetric-key-encryption-with.html
Javascript OpenPGP
hxxp://www.hanewin.net/encrypt/
PS: stupid mechanism prevents me posting links ...
You don't handle SSL in your PHP. SSL is handled by the web server automatically. If you're using Apache, here's a simple tutorial:
http://www.debian-administration.org/article/Setting_up_an_SSL_server_with_Apache2
The idea is that you write your code like normal, and when the user accesses your site using https, the server automatically encrypts the connection. On the client side, the browser is capable of using the private keys that it already has to automagically decrypt the connection and present the code to the user agent.
Hope this helps!

Categories