Re: [PHP] How to store encrypted data and how to store the key?

2010-06-23 Thread Peter Lind
On 23 June 2010 09:11, Michael Shadle mike...@gmail.com wrote:
 This is somewhat related to the whole PCI/credit card discussion a
 couple weeks back. The consensus was basically leave it to other
 people - however, what if YOU are the other person?

 I wonder if anyone has some BKMs to share about encrypting data in a
 web application. A lot of people take the most obvious approach, but
 it's fundamentally flawed, that is:

 I take data from the user, I encrypt it (using PHP crypto, or MySQL
 crypto, etc.) and a key stored in my config file, and put it into the
 database. Then when I want to get it back, I just use decrypt + the
 key in my config file. The issue there? If you server is compromised
 and the database is accessable, they'll have the key to decrypt the
 data right off the server. They can pull down copies of everything or
 even write their own script ON the server itself to extract the data.

 This has been one thing that I have not really been able to figure out
 yet. You could separate the servers, and figure out some very hard way
 for them to communicate, but when it comes down to it, the webserver
 needs to access the data. For example, the webserver could be behind a
 fully firewalled setup that only allows MySQL traffic. However, the
 webserver has to access the data still.

 I assume the only solution is somehow storing the key in a third
 place, so the accessor has to get the key somehow before accessing the
 encrypted data. But again - how to automatically allow access for only
 the webapp? I thought of per-user keys, but that isn't an appropriate
 solution for something that needs to be encrypted using the same key.

 Has anyone had to implement anything like this? Is there a good
 whitepaper on something like this? Especially relating to HIPAA
 requirements. PCI would be nice too, but I'm sure once this major
 unknown in my mind is addressed, the general concepts are common,
 probably just differences in levels of firewalling, cryptography
 strength, physical access to the machines, etc.

 Please keep this on topic - this is about the people who DO have to
 address this issue, not something about just offload it to other
 guys - that's an obvious choice already, and not one that is allowed
 depending on the job.


I haven't had to implement a scheme like this but for an app I'm
working on we've been considering the same issues in order to keep
member data safe. I would say your best bet is to keep the decryption
key in memory while the app is running. Initialize it by hand whenever
the server is started - don't store it on the disk. Yes, your server
won't be able to start up the app on it's own but that's the security
in the design, not a flaw. If you want automatic access for the
web-app you've compromised security (anyone compromising the server
has automatic access as well).
 You're essentially looking at the old problem: if it runs it can be
broken. You can only try to make it as hard as possible but there's
nothing foolproof.

Regards
Peter

-- 
hype
WWW: http://plphp.dk / http://plind.dk
LinkedIn: http://www.linkedin.com/in/plind
BeWelcome/Couchsurfing: Fake51
Twitter: http://twitter.com/kafe15
/hype

-- 
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP] How to store encrypted data and how to store the key?

2010-06-23 Thread Michael Shadle
On Wed, Jun 23, 2010 at 12:21 AM, Peter Lind peter.e.l...@gmail.com wrote:

 I haven't had to implement a scheme like this but for an app I'm
 working on we've been considering the same issues in order to keep
 member data safe. I would say your best bet is to keep the decryption
 key in memory while the app is running. Initialize it by hand whenever
 the server is started - don't store it on the disk. Yes, your server
 won't be able to start up the app on it's own but that's the security
 in the design, not a flaw. If you want automatic access for the
 web-app you've compromised security (anyone compromising the server
 has automatic access as well).

That's something I've thought about before.

Storing MySQL on an encrypted partition using cryptoloop or something.
However, every time the server boots - someone has to manually unlock
the partition (unless some sort of physical key is present, then
another dimension is introduced)

However, that would solve the data being encrypted at rest, more or
less. The issue of how to use the data in the web application is still
not addressed this way :(

-- 
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php



RE: [PHP] How to store encrypted data and how to store the key?

2010-06-23 Thread Tommy Pham
 -Original Message-
 From: Peter Lind [mailto:peter.e.l...@gmail.com]
 Sent: Wednesday, June 23, 2010 12:22 AM
 To: Michael Shadle
 Cc: PHP-General
 Subject: Re: [PHP] How to store encrypted data and how to store the key?
 
 On 23 June 2010 09:11, Michael Shadle mike...@gmail.com wrote:
  This is somewhat related to the whole PCI/credit card discussion a
  couple weeks back. The consensus was basically leave it to other
  people - however, what if YOU are the other person?
 
  I wonder if anyone has some BKMs to share about encrypting data in a
  web application. A lot of people take the most obvious approach, but
  it's fundamentally flawed, that is:
 
  I take data from the user, I encrypt it (using PHP crypto, or MySQL
  crypto, etc.) and a key stored in my config file, and put it into the
  database. Then when I want to get it back, I just use decrypt + the
  key in my config file. The issue there? If you server is compromised
  and the database is accessable, they'll have the key to decrypt the
  data right off the server. They can pull down copies of everything or
  even write their own script ON the server itself to extract the data.
 
  This has been one thing that I have not really been able to figure out
  yet. You could separate the servers, and figure out some very hard way
  for them to communicate, but when it comes down to it, the webserver
  needs to access the data. For example, the webserver could be behind a
  fully firewalled setup that only allows MySQL traffic. However, the
  webserver has to access the data still.
 
  I assume the only solution is somehow storing the key in a third
  place, so the accessor has to get the key somehow before accessing the
  encrypted data. But again - how to automatically allow access for only
  the webapp? I thought of per-user keys, but that isn't an appropriate
  solution for something that needs to be encrypted using the same key.
 
  Has anyone had to implement anything like this? Is there a good
  whitepaper on something like this? Especially relating to HIPAA
  requirements. PCI would be nice too, but I'm sure once this major
  unknown in my mind is addressed, the general concepts are common,
  probably just differences in levels of firewalling, cryptography
  strength, physical access to the machines, etc.
 
  Please keep this on topic - this is about the people who DO have to
  address this issue, not something about just offload it to other
  guys - that's an obvious choice already, and not one that is allowed
  depending on the job.
 
 
 I haven't had to implement a scheme like this but for an app I'm working on
 we've been considering the same issues in order to keep member data safe.
 I would say your best bet is to keep the decryption key in memory while the

This is something I'm very interested in hearing more about since our other 
discussion about PHP  threads and how some list members prefer the 'share 
nothing' approach.  That said, how would you access the memory for every 
individual sessions that need that decrypting code/key when nothing is shared?  
(I'm assuming that this would be purely in PHP :)

Regards,
Tommy

 app is running. Initialize it by hand whenever the server is started - don't
 store it on the disk. Yes, your server won't be able to start up the app on 
 it's
 own but that's the security in the design, not a flaw. If you want automatic
 access for the web-app you've compromised security (anyone compromising
 the server has automatic access as well).
  You're essentially looking at the old problem: if it runs it can be broken. 
 You
 can only try to make it as hard as possible but there's nothing foolproof.
 
 Regards
 Peter
 
 --
 hype
 WWW: http://plphp.dk / http://plind.dk
 LinkedIn: http://www.linkedin.com/in/plind
 BeWelcome/Couchsurfing: Fake51
 Twitter: http://twitter.com/kafe15
 /hype
 


--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP] How to store encrypted data and how to store the key?

2010-06-23 Thread Michael Shadle
On Wed, Jun 23, 2010 at 12:55 AM, Tommy Pham tommy...@gmail.com wrote:

 I haven't had to implement a scheme like this but for an app I'm working on
 we've been considering the same issues in order to keep member data safe.
 I would say your best bet is to keep the decryption key in memory while the

 This is something I'm very interested in hearing more about since our other 
 discussion about PHP  threads and how some list members prefer the 'share 
 nothing' approach.  That said, how would you access the memory for every 
 individual sessions that need that decrypting code/key when nothing is 
 shared?  (I'm assuming that this would be purely in PHP :)

+1. each server stores it locally in APC, or you have to mess with
memcached, and since it is plaintext, encrypt that too? :p

I -always- design for 'shared nothing' so this is a necessary
discussion too, if in memory is the idea.

--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP] How to store encrypted data and how to store the key?

2010-06-23 Thread Peter Lind
On 23 June 2010 10:09, Michael Shadle mike...@gmail.com wrote:
 On Wed, Jun 23, 2010 at 12:55 AM, Tommy Pham tommy...@gmail.com wrote:

 I haven't had to implement a scheme like this but for an app I'm working on
 we've been considering the same issues in order to keep member data safe.
 I would say your best bet is to keep the decryption key in memory while the

 This is something I'm very interested in hearing more about since our other 
 discussion about PHP  threads and how some list members prefer the 'share 
 nothing' approach.  That said, how would you access the memory for every 
 individual sessions that need that decrypting code/key when nothing is 
 shared?  (I'm assuming that this would be purely in PHP :)

 +1. each server stores it locally in APC, or you have to mess with
 memcached, and since it is plaintext, encrypt that too? :p

 I -always- design for 'shared nothing' so this is a necessary
 discussion too, if in memory is the idea.


In memory means that any of the php processes spawned by the server
would have access to it. Encrypting it in memory really doesn't help
you, as the php process would then decrypt it, bringing you back to
square one: you just mimic the decrypting behaviour of a working php
process to get the plaintext key.
 Shared nothing also doesn't help you - that just multiplies the
amount of places the key is placed because you're still facing the
same issue: the scripts need access to the key. You could possibly
devise an authentication scheme by which a script could authenticate
itself to a server that would then hand out the key ... but that's
susceptible to other attacks as well. So I'd probably stick the key in
memory, possibly memcached. I'd encrypt it but nothing special, just
making sure that you cannot get the plaintext from memcached without
digging through working php files to figure out how you decrypt it.
Then I'd monitor the solution to see if anything *weird* was going on,
wiping memcache if something strange comes up.
 As should be obvious, this doesn't solve the problems. Your number
one priority is blocking access to the server. Number two is making
sure that noone can use the data *if* they get access but without
working scripts. If someone roots the server with everything up and
running, there's really very little you can do.

This is getting offtopic, though, if memory serves. I believe PCI has
some strict requirements on how security should be implemented. You'll
have to follow those and not other schemes that may be more or less
secure.

Regards
Peter

-- 
hype
WWW: http://plphp.dk / http://plind.dk
LinkedIn: http://www.linkedin.com/in/plind
BeWelcome/Couchsurfing: Fake51
Twitter: http://twitter.com/kafe15
/hype

--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP] How to store encrypted data and how to store the key?

2010-06-23 Thread Bastien Koert
On Wed, Jun 23, 2010 at 6:09 AM, Peter Lind peter.e.l...@gmail.com wrote:
 On 23 June 2010 10:09, Michael Shadle mike...@gmail.com wrote:
 On Wed, Jun 23, 2010 at 12:55 AM, Tommy Pham tommy...@gmail.com wrote:

 I haven't had to implement a scheme like this but for an app I'm working on
 we've been considering the same issues in order to keep member data safe.
 I would say your best bet is to keep the decryption key in memory while the

 This is something I'm very interested in hearing more about since our other 
 discussion about PHP  threads and how some list members prefer the 'share 
 nothing' approach.  That said, how would you access the memory for every 
 individual sessions that need that decrypting code/key when nothing is 
 shared?  (I'm assuming that this would be purely in PHP :)

 +1. each server stores it locally in APC, or you have to mess with
 memcached, and since it is plaintext, encrypt that too? :p

 I -always- design for 'shared nothing' so this is a necessary
 discussion too, if in memory is the idea.


 In memory means that any of the php processes spawned by the server
 would have access to it. Encrypting it in memory really doesn't help
 you, as the php process would then decrypt it, bringing you back to
 square one: you just mimic the decrypting behaviour of a working php
 process to get the plaintext key.
  Shared nothing also doesn't help you - that just multiplies the
 amount of places the key is placed because you're still facing the
 same issue: the scripts need access to the key. You could possibly
 devise an authentication scheme by which a script could authenticate
 itself to a server that would then hand out the key ... but that's
 susceptible to other attacks as well. So I'd probably stick the key in
 memory, possibly memcached. I'd encrypt it but nothing special, just
 making sure that you cannot get the plaintext from memcached without
 digging through working php files to figure out how you decrypt it.
 Then I'd monitor the solution to see if anything *weird* was going on,
 wiping memcache if something strange comes up.
  As should be obvious, this doesn't solve the problems. Your number
 one priority is blocking access to the server. Number two is making
 sure that noone can use the data *if* they get access but without
 working scripts. If someone roots the server with everything up and
 running, there's really very little you can do.

 This is getting offtopic, though, if memory serves. I believe PCI has
 some strict requirements on how security should be implemented. You'll
 have to follow those and not other schemes that may be more or less
 secure.

 Regards
 Peter

 --
 hype
 WWW: http://plphp.dk / http://plind.dk
 LinkedIn: http://www.linkedin.com/in/plind
 BeWelcome/Couchsurfing: Fake51
 Twitter: http://twitter.com/kafe15
 /hype

 --
 PHP General Mailing List (http://www.php.net/)
 To unsubscribe, visit: http://www.php.net/unsub.php



Here are a couple of things which may help

http://www.owasp.org/index.php/Cryptographic_Storage_Cheat_Sheet#Rule_-_Under_PCI_DSS_requirement_3.2C_you_must_protect_cardholder_data

http://www.issociate.de/board/post/247319/Encryption_Key_Storage.html

The biggest issue with it on web servers is simply time. If the key is
too hard to get to, or unavailable due to a machine failure, then you
are going to have pissed off customers/clients who won't be able to do
much.

The best solution is to store the CC data on a DB that is not web
facing. That removes the need for the web app to hold the encryption
key. You can store a hashed value, with the last 4 digits of the card
and expiry on the web facing DB for any transaction processing
verification. But those transactions should then move into a queue
inside the secured network that is not web facing. This secured
network can then take the data from the queue, find the appropriate
record in the secured DB, unencrypt it and process it as normal
transaction. Get back the verification of successful transaction and
then queue that back into the web facing system for messaging the
user.



-- 

Bastien

Cat, the other other white meat

--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP] How to store encrypted data and how to store the key?

2010-06-23 Thread Michael Shadle
I talked with a friend who actually had this implemented before and
banks had signed off on it after reviewing it.

load balancer (irrelevant to the security piece)

web server(s) - only accepts traffic to port 80/443. can only forward
requests on to the app server, one direction.

app server(s) - processes the PHP/etc. has access to the
encryption/decryption keys. can only send established packets back to
the webserver, and traffic to the db. cannot connect outbound to the
net.

db server(s) - stores the data. choose how you want to encrypt. they
did not encrypt data at rest in their setup, the bank would have
'preferred' it but was not willing to buy the license for the
encryption plugin. however, the app tier could handle the
encryption/decryption.

all machines were only accessable via VPN, not the WAN.

due to that, assuming physical access is not an issue:

if the webserver got exploited, it could only talk to the app server
using http. it has no access to the encryption key, nor the database.
only one direction of communication. if the app server somehow got
exploited (someone somehow got a trojan installed) it can't
communicate outbound, so unless they figured some creative way to make
the app server expose information through the open port only for the
webserver, it's useless. and to install the trojan, typically people
fetch remote files - well, the app tier can't communicate outbound.

it's pretty damn secure for a web app. you could theoretically pair
the app server and db server on the same box - you could probably make
that work too. depends on how large you need to scale and the
architecture required.

anyway... anyone have any comments or holes to poke in this theory?




On Wed, Jun 23, 2010 at 12:55 AM, Tommy Pham tommy...@gmail.com wrote:
 -Original Message-
 From: Peter Lind [mailto:peter.e.l...@gmail.com]
 Sent: Wednesday, June 23, 2010 12:22 AM
 To: Michael Shadle
 Cc: PHP-General
 Subject: Re: [PHP] How to store encrypted data and how to store the key?

 On 23 June 2010 09:11, Michael Shadle mike...@gmail.com wrote:
  This is somewhat related to the whole PCI/credit card discussion a
  couple weeks back. The consensus was basically leave it to other
  people - however, what if YOU are the other person?
 
  I wonder if anyone has some BKMs to share about encrypting data in a
  web application. A lot of people take the most obvious approach, but
  it's fundamentally flawed, that is:
 
  I take data from the user, I encrypt it (using PHP crypto, or MySQL
  crypto, etc.) and a key stored in my config file, and put it into the
  database. Then when I want to get it back, I just use decrypt + the
  key in my config file. The issue there? If you server is compromised
  and the database is accessable, they'll have the key to decrypt the
  data right off the server. They can pull down copies of everything or
  even write their own script ON the server itself to extract the data.
 
  This has been one thing that I have not really been able to figure out
  yet. You could separate the servers, and figure out some very hard way
  for them to communicate, but when it comes down to it, the webserver
  needs to access the data. For example, the webserver could be behind a
  fully firewalled setup that only allows MySQL traffic. However, the
  webserver has to access the data still.
 
  I assume the only solution is somehow storing the key in a third
  place, so the accessor has to get the key somehow before accessing the
  encrypted data. But again - how to automatically allow access for only
  the webapp? I thought of per-user keys, but that isn't an appropriate
  solution for something that needs to be encrypted using the same key.
 
  Has anyone had to implement anything like this? Is there a good
  whitepaper on something like this? Especially relating to HIPAA
  requirements. PCI would be nice too, but I'm sure once this major
  unknown in my mind is addressed, the general concepts are common,
  probably just differences in levels of firewalling, cryptography
  strength, physical access to the machines, etc.
 
  Please keep this on topic - this is about the people who DO have to
  address this issue, not something about just offload it to other
  guys - that's an obvious choice already, and not one that is allowed
  depending on the job.
 

 I haven't had to implement a scheme like this but for an app I'm working on
 we've been considering the same issues in order to keep member data safe.
 I would say your best bet is to keep the decryption key in memory while the

 This is something I'm very interested in hearing more about since our other 
 discussion about PHP  threads and how some list members prefer the 'share 
 nothing' approach.  That said, how would you access the memory for every 
 individual sessions that need that decrypting code/key when nothing is 
 shared?  (I'm assuming that this would be purely in PHP :)

 Regards,
 Tommy

 app is running. Initialize it by hand 

Re: [PHP] How to store encrypted data and how to store the key?

2010-06-23 Thread Peter Lind
On 23 June 2010 20:55, Michael Shadle mike...@gmail.com wrote:
 I talked with a friend who actually had this implemented before and
 banks had signed off on it after reviewing it.

 load balancer (irrelevant to the security piece)

 web server(s) - only accepts traffic to port 80/443. can only forward
 requests on to the app server, one direction.

 app server(s) - processes the PHP/etc. has access to the
 encryption/decryption keys. can only send established packets back to
 the webserver, and traffic to the db. cannot connect outbound to the
 net.

 db server(s) - stores the data. choose how you want to encrypt. they
 did not encrypt data at rest in their setup, the bank would have
 'preferred' it but was not willing to buy the license for the
 encryption plugin. however, the app tier could handle the
 encryption/decryption.

 all machines were only accessable via VPN, not the WAN.

 due to that, assuming physical access is not an issue:

 if the webserver got exploited, it could only talk to the app server
 using http. it has no access to the encryption key, nor the database.
 only one direction of communication. if the app server somehow got
 exploited (someone somehow got a trojan installed) it can't
 communicate outbound, so unless they figured some creative way to make
 the app server expose information through the open port only for the
 webserver, it's useless. and to install the trojan, typically people
 fetch remote files - well, the app tier can't communicate outbound.

 it's pretty damn secure for a web app. you could theoretically pair
 the app server and db server on the same box - you could probably make
 that work too. depends on how large you need to scale and the
 architecture required.

 anyway... anyone have any comments or holes to poke in this theory?


I'm just wondering if this is a correct understanding:
1. plaintext data arrives on the web frontend.
2. It's sent to the app server
3. It's encrypted and sent to the DB server

Where does the data go after step 3? Does encrypted data go back out
to the app server? In which case, what's to stop me from exploiting
the web-server and then sending *bad data/commands* to the app server?

But maybe I'm taking this too far: are you only looking at security in
terms of storage? I.e. is this merely a question of avoiding dumps of
the data?

Regards
Peter

-- 
hype
WWW: http://plphp.dk / http://plind.dk
LinkedIn: http://www.linkedin.com/in/plind
BeWelcome/Couchsurfing: Fake51
Twitter: http://twitter.com/kafe15
/hype

-- 
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP] How to store encrypted data and how to store the key?

2010-06-23 Thread Michael Shadle
On Wed, Jun 23, 2010 at 12:43 PM, Peter Lind peter.e.l...@gmail.com wrote:

 I'm just wondering if this is a correct understanding:
 1. plaintext data arrives on the web frontend.

or over SSL

 2. It's sent to the app server

SSL or non-SSL - your choice

 3. It's encrypted and sent to the DB server

encrypted or not encrypted - your choice

 Where does the data go after step 3? Does encrypted data go back out
 to the app server? In which case, what's to stop me from exploiting
 the web-server and then sending *bad data/commands* to the app server?

 But maybe I'm taking this too far: are you only looking at security in
 terms of storage? I.e. is this merely a question of avoiding dumps of
 the data?

It is mainly about how to stop an exploited machine (even shell
access) from accessing the data by simply looking at a PHP config
file.

This solves that by reducing the risk with the only WAN-accessable
touchpoint (web servers, or well, technically the load balancer even)
which is only accessable via HTTP or HTTPS. Feeding bad commands is
always a risk, no matter what - but you could figure out how to setup
an IDS system or something to only accept POST/GET without exploitable
characters or anything. Suhosin type things come to mind.

But again - the only way to get data would be if you craft something
and use SQL injection or something to get the data out. You couldn't
exploit code to download a trojan or something because the application
server cannot talk to the Internet. I think it is a compartmentalized
setup that would solve my original question...

-- 
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php