Thread: Re: [HACKERS] SSL over Unix-domain sockets
Bruce Momjian wrote: > Tom Lane wrote: > > Conclusions: > > > > * SSL, even without real authentication, is *way* too expensive to > > enable by default. > > > > * The extra cost of going across a local TCP connection is measurable, > > but it's insignificant compared to the cost of turning on SSL. (This > > is on a Fedora 8 kernel BTW ... that result might vary on other > > platforms.) > > > > So you could make a pretty good case that the answer for DBAs who > > want to prevent spoofing is to disable socket connections in pg_hba.conf > > and force even local connections to come through "hostssl" connections. > > Yea, I figured using protected directories for the socket was the > zero-cost solution, and if you have to do SSL, might as well just use > TCP too. (If you moved the socket file to a protected directory I think > you could use external_pid_file='/tmp/.s.PGSQL.5432' to prevent a spoof > socket file in /tmp. Should we document that idea?) I did some research on this. external_pid_file will not prevent the server from starting. If the lock file exists it just generates an entry in the log file: postmaster: could not write external PID file "/tmp/x": Permission denied Looking at the threat matrix, we have: Server Client Server Up? Spoofable? /tmp /tmp Y N /tmp /tmp N Y $HOME $HOME Y N $HOME $HOME N N $HOME /tmp Y N $HOME /tmp N Y Basically, if you use a user-specific directory for the server socket file ($HOME) and an external_pid_file, the only way for the client to be spoofed is for the client to be using /tmp _and_ for the server to be down. I assume most new applications will be tested while the server is up and therefore will fail and the client will be fixed. I have written the following documentation addition suggesting the use of external_pid_file. -- Bruce Momjian <bruce@momjian.us> http://momjian.us EnterpriseDB http://postgres.enterprisedb.com + If your life is a hard drive, Christ can be your backup. + Index: doc/src/sgml/runtime.sgml =================================================================== RCS file: /cvsroot/pgsql/doc/src/sgml/runtime.sgml,v retrieving revision 1.402 diff -c -c -r1.402 runtime.sgml *** doc/src/sgml/runtime.sgml 8 Jan 2008 18:07:38 -0000 1.402 --- doc/src/sgml/runtime.sgml 17 Jan 2008 00:20:36 -0000 *************** *** 1397,1405 **** connections is to use a Unix domain socket directory (<xref linkend="guc-unix-socket-directory">) that has write permission only for a trusted local user. This prevents a malicious user from creating ! their own socket file in that directory. For TCP connections the server ! must accept only <literal>hostssl</> connections (<xref ! linkend="auth-pg-hba-conf">) and have SSL <filename>server.key</filename> (key) and <filename>server.crt</filename> (certificate) files (<xref linkend="ssl-tcp">). The TCP client must connect using --- 1397,1413 ---- connections is to use a Unix domain socket directory (<xref linkend="guc-unix-socket-directory">) that has write permission only for a trusted local user. This prevents a malicious user from creating ! their own socket file in that directory. ! Additionally, you might want to set <xref ! linkend="guc-external-pid-file"> to <literal>/tmp/.s.PGSQL.5432</> to ! prevent spoofing for clients looking for the socket in its default ! location. This protection is only effective while the server is ! running. ! </para> ! ! <para> ! For TCP connections the server must accept only <literal>hostssl</> ! connections (<xref linkend="auth-pg-hba-conf">) and have SSL <filename>server.key</filename> (key) and <filename>server.crt</filename> (certificate) files (<xref linkend="ssl-tcp">). The TCP client must connect using
Bruce Momjian wrote: > I have written the following documentation addition suggesting the use > of external_pid_file. How does that prevent spoofing? -- Peter Eisentraut http://developer.postgresql.org/~petere/
Peter Eisentraut wrote: > Bruce Momjian wrote: > > I have written the following documentation addition suggesting the use > > of external_pid_file. > > How does that prevent spoofing? It creates a lock file that is the same name as the socket file that a default-configured client would use, so it prevents a spoofed socket from being created. -- Bruce Momjian <bruce@momjian.us> http://momjian.us EnterpriseDB http://postgres.enterprisedb.com + If your life is a hard drive, Christ can be your backup. +
Bruce Momjian <bruce@momjian.us> writes: > Peter Eisentraut wrote: >> How does that prevent spoofing? > It creates a lock file that is the same name as the socket file that a > default-configured client would use, so it prevents a spoofed socket > from being created. Only if the attacker didn't get there first. I think this idea is nothing but a crude kluge anyway... regards, tom lane
Tom Lane wrote: > Bruce Momjian <bruce@momjian.us> writes: > >> Peter Eisentraut wrote: >> >>> How does that prevent spoofing? >>> > > >> It creates a lock file that is the same name as the socket file that a >> default-configured client would use, so it prevents a spoofed socket >> from being created. >> > > Only if the attacker didn't get there first. I think this idea is > nothing but a crude kluge anyway... > > I agree. I remain of the opinion that this is not a problem than can be solved purely within the bounds of postgres. cheers andrew
Andrew Dunstan wrote: > I agree. I remain of the opinion that this is not a problem than can be > solved purely within the bounds of postgres. I agree. Please comment on my proposed solution. -- Alvaro Herrera http://www.CommandPrompt.com/ PostgreSQL Replication, Consulting, Custom Development, 24x7 support
Alvaro Herrera wrote: > Andrew Dunstan wrote: > > >> I agree. I remain of the opinion that this is not a problem than can be >> solved purely within the bounds of postgres. >> > > I agree. Please comment on my proposed solution. > > I'm not sure tmp cleaners will work that well against a determined spoofer. cheers andrew
Andrew Dunstan wrote: > > > Alvaro Herrera wrote: >> Andrew Dunstan wrote: >> >> >>> I agree. I remain of the opinion that this is not a problem than can be >>> solved purely within the bounds of postgres. >> >> I agree. Please comment on my proposed solution. > > I'm not sure tmp cleaners will work that well against a determined spoofer. I don't understand. The tmp cleaner is something we have to _avoid_. Let me repeat my proposal. I propose to create a dangling symlink on system startup in /tmp/.s.PGSQL.<port> to the real socket, which is not on a world-writable directory. This avoids the spoofer, because he cannot create the socket -- the symlink is occupying its place. The only problem with this proposal is that the tmp cleaner would remove the symlink. The solution to this is to configure the tmp cleaner so that it doesn't do that. It absolutely requires cooperation from the sysadmin, both to setup the symlink initially, and to configure the tmp cleaner. -- Alvaro Herrera http://www.CommandPrompt.com/ The PostgreSQL Company - Command Prompt, Inc.
Alvaro Herrera <alvherre@commandprompt.com> writes: > I propose to create a dangling symlink on system startup in > /tmp/.s.PGSQL.<port> to the real socket, which is not on a > world-writable directory. This avoids the spoofer, because he cannot > create the socket -- the symlink is occupying its place. > The only problem with this proposal is that the tmp cleaner would remove > the symlink. The solution to this is to configure the tmp cleaner so > that it doesn't do that. > It absolutely requires cooperation from the sysadmin, both to setup the > symlink initially, and to configure the tmp cleaner. This is definitely a slick solution if you can overcome the tmp-cleaner risk; not least because it doesn't require any work on our part ;-). However, we should document the approach someplace. Further down the road we could think about Postgres changes to support such a strategy --- for instance, having the postmaster check to see if such a link exists. This will require more thought than we have time for for 8.3; also I think we'd need to negotiate with packagers, such as the Debian crew, to make sure any such behavior is acceptable to them. BTW, is a symlink's atime changed by accessing it? We could imagine adapting the existing postmaster code that keeps the socket atime fresh so that it will work on a symlink, thus providing partial protection against tmp-cleaners. Portability of this is uncertain... regards, tom lane
Alvaro Herrera wrote: > > I'm not sure tmp cleaners will work that well against a determined spoofer. > > I don't understand. The tmp cleaner is something we have to _avoid_. > Let me repeat my proposal. > > I propose to create a dangling symlink on system startup in > /tmp/.s.PGSQL.<port> to the real socket, which is not on a I am confused because you say "dangling" then you say "to the real socket". You are saying it isn't dangling when the server is running? > world-writable directory. This avoids the spoofer, because he cannot > create the socket -- the symlink is occupying its place. > > The only problem with this proposal is that the tmp cleaner would remove > the symlink. The solution to this is to configure the tmp cleaner so > that it doesn't do that. > > It absolutely requires cooperation from the sysadmin, both to setup the > symlink initially, and to configure the tmp cleaner. If you are going to require the admin to modify the tmp cleanup script, the admin might as well create the symlink at the same time and have it recreate on boot. We could actually just document this idea and be done with it. -- Bruce Momjian <bruce@momjian.us> http://momjian.us EnterpriseDB http://postgres.enterprisedb.com + If your life is a hard drive, Christ can be your backup. +
Bruce Momjian wrote: > Alvaro Herrera wrote: > > > I'm not sure tmp cleaners will work that well against a determined spoofer. > > > > I don't understand. The tmp cleaner is something we have to _avoid_. > > Let me repeat my proposal. > > > > I propose to create a dangling symlink on system startup in > > /tmp/.s.PGSQL.<port> to the real socket, which is not on a > > I am confused because you say "dangling" then you say "to the real > socket". You are saying it isn't dangling when the server is running? > > > world-writable directory. This avoids the spoofer, because he cannot > > create the socket -- the symlink is occupying its place. > > > > The only problem with this proposal is that the tmp cleaner would remove > > the symlink. The solution to this is to configure the tmp cleaner so > > that it doesn't do that. > > > > It absolutely requires cooperation from the sysadmin, both to setup the > > symlink initially, and to configure the tmp cleaner. > > If you are going to require the admin to modify the tmp cleanup script, > the admin might as well create the symlink at the same time and have it > recreate on boot. We could actually just document this idea and be done > with it. Oh, sorry, I see now you are having the admin create the symlink and modify the tmp cleaner --- yea, I think we just document this and call it done. Do we do anything in the backend for this proposal? -- Bruce Momjian <bruce@momjian.us> http://momjian.us EnterpriseDB http://postgres.enterprisedb.com + If your life is a hard drive, Christ can be your backup. +
Bruce Momjian <bruce@momjian.us> writes: > I am confused because you say "dangling" then you say "to the real > socket". You are saying it isn't dangling when the server is running? Exactly. When the server is running it provides a perfectly good path to the postmaster. The point (and the main difference from your PIDfile proposal) is that it's supposed to be there all the time, even when the postmaster isn't running. This is what provides protection against the spoofer getting there first. > If you are going to require the admin to modify the tmp cleanup script, > the admin might as well create the symlink at the same time and have it > recreate on boot. No, that's not the same, because it doesn't provide protection against the symlink getting deleted later on. regards, tom lane
Tom Lane wrote: > Bruce Momjian <bruce@momjian.us> writes: > > I am confused because you say "dangling" then you say "to the real > > socket". You are saying it isn't dangling when the server is running? > > Exactly. When the server is running it provides a perfectly good path > to the postmaster. The point (and the main difference from your PIDfile > proposal) is that it's supposed to be there all the time, even when the > postmaster isn't running. This is what provides protection against the > spoofer getting there first. OK, got it. > > If you are going to require the admin to modify the tmp cleanup script, > > the admin might as well create the symlink at the same time and have it > > recreate on boot. > > No, that's not the same, because it doesn't provide protection against > the symlink getting deleted later on. Right, so you have to modify the tmp cleaner and create the symlink, right? -- Bruce Momjian <bruce@momjian.us> http://momjian.us EnterpriseDB http://postgres.enterprisedb.com + If your life is a hard drive, Christ can be your backup. +
Alvaro Herrera wrote: > Andrew Dunstan wrote: > >> Alvaro Herrera wrote: >> >>> Andrew Dunstan wrote: >>> >>> >>> >>>> I agree. I remain of the opinion that this is not a problem than can be >>>> solved purely within the bounds of postgres. >>>> >>> I agree. Please comment on my proposed solution. >>> >> I'm not sure tmp cleaners will work that well against a determined spoofer. >> > > I don't understand. The tmp cleaner is something we have to _avoid_. > Let me repeat my proposal. > > I propose to create a dangling symlink on system startup in > /tmp/.s.PGSQL.<port> to the real socket, which is not on a > world-writable directory. This avoids the spoofer, because he cannot > create the socket -- the symlink is occupying its place. > > The only problem with this proposal is that the tmp cleaner would remove > the symlink. The solution to this is to configure the tmp cleaner so > that it doesn't do that. > > It absolutely requires cooperation from the sysadmin, both to setup the > symlink initially, and to configure the tmp cleaner. > Oh. I'm sorry. Yes, I think this would work. cheers andrew
On Thu, 17 Jan 2008, Tom Lane wrote: > BTW, is a symlink's atime changed by accessing it? It seems so in the cases I've tried or researched, but it's complicated. After burning through a bunch of time looking into this I wanted to drop some notes so nobody else has to wander down the specific dead-ends I just followed. I figured I'd just run some experiments to figure this out for my Linux system, but that didn't go so well. The process of running anything that shows the atime: ls -l --time=atime <file> ls -lu <file> stat <file> actually updates the atime to right now along the way. I hacked up something with perl that directly calls lstat() and it did the same thing. Mystified, I found this thread suggesting the same thing is true on Mac OS X: http://lists.apple.com/archives/darwin-kernel/2006/Dec/msg00054.html The point made in there is that how symlinks are encoded varies not just from OS to OS but from filesystem to filesystem, and that encoding changes how things like atime work. On Linux with ext2, I found this note: "Symbolic links are also filesystem objects with inodes. They deserve special mention because the data for them is stored within the inode itself if the symlink is less than 60 bytes long. It uses the fields which would normally be used to store the pointers to data blocks." So what I think is happening is: the process of doing anything at all with a Linux symlink references the inode that has the link. That updates the atime on that inode. But since there's no actual data underneath that lookup in cases where the link is less than 60 bytes, the inode atime is the link atime, so that just updated the link's atime to right now as well. I have no idea how any tmp cleaner could ever find a short symlink it can delete if I'm understanding this correctly. I left behind the link I was just playing with and I'll see if I can get tmpwatch to eat it tomorrow, that seems like the most appropriate test here. -- * Greg Smith gsmith@gregsmith.com http://www.gregsmith.com Baltimore, MD
Am Donnerstag, 17. Januar 2008 schrieb Bruce Momjian: > It creates a lock file that is the same name as the socket file that a > default-configured client would use, so it prevents a spoofed socket > from being created. A counter-spoofing solution must be implemented in the client. No moving around of files by the server will ever solve the problem. -- Peter Eisentraut http://developer.postgresql.org/~petere/
Am Donnerstag, 17. Januar 2008 schrieb Andrew Dunstan: > I agree. I remain of the opinion that this is not a problem than can be > solved purely within the bounds of postgres. Well, the SSL patch I showed certainly solves the problem. (I am not saying it is the best possible solution.) Of course there also need to be prudent users, but that is the case for any security system. -- Peter Eisentraut http://developer.postgresql.org/~petere/
Am Freitag, 18. Januar 2008 schrieb Alvaro Herrera: > I propose to create a dangling symlink on system startup in > /tmp/.s.PGSQL.<port> to the real socket, which is not on a > world-writable directory. This avoids the spoofer, because he cannot > create the socket -- the symlink is occupying its place. This approaches the issue from the wrong end. Spoofing attacks the client, so the defense must be in the client. If the defense of the client is to rely on a carefully configured server, then that might exclude some possible attack vectors, but it is not a defense the client can rely on. To look at this in another way, if we relied on every browser user to type in web addresses correctly and all server administrators to make sure their "socket address" cannot be hijacked, we wouldn't need SSL on the web. The proper approach, however, is to configure the client to only talk to servers that can prove their identity. -- Peter Eisentraut http://developer.postgresql.org/~petere/
On Fri, Jan 18, 2008 at 11:24:09AM +0100, Peter Eisentraut wrote: > Am Donnerstag, 17. Januar 2008 schrieb Andrew Dunstan: > > I agree. I remain of the opinion that this is not a problem than can be > > solved purely within the bounds of postgres. > > Well, the SSL patch I showed certainly solves the problem. (I am not saying > it is the best possible solution.) Of course there also need to be prudent > users, but that is the case for any security system. Not that much more than moving the socket file to a secure directory. Both rely on configuring the client properly. It's arguably a lot easier to configure the client to connect to the correct socket, than to make sure the client has a root certificate installed. //Magnus
Am Freitag, 18. Januar 2008 schrieb Magnus Hagander: > Not that much more than moving the socket file to a secure directory. Both > rely on configuring the client properly. It's arguably a lot easier to > configure the client to connect to the correct socket, than to make sure > the client has a root certificate installed. How would a client check whether the socket file is in a secure location? -- Peter Eisentraut http://developer.postgresql.org/~petere/
On Fri, Jan 18, 2008 at 12:35:40PM +0100, Peter Eisentraut wrote: > Am Freitag, 18. Januar 2008 schrieb Magnus Hagander: > > Not that much more than moving the socket file to a secure directory. Both > > rely on configuring the client properly. It's arguably a lot easier to > > configure the client to connect to the correct socket, than to make sure > > the client has a root certificate installed. > > How would a client check whether the socket file is in a secure location? The same way it would get the root certificate to trust - it would be told so by the administrator who had secured the location. //Magnus
Tom Lane wrote: > Bruce Momjian <bruce@momjian.us> writes: > > I am confused because you say "dangling" then you say "to the real > > socket". You are saying it isn't dangling when the server is running? > > Exactly. When the server is running it provides a perfectly good path > to the postmaster. The point (and the main difference from your PIDfile > proposal) is that it's supposed to be there all the time, even when the > postmaster isn't running. This is what provides protection against the > spoofer getting there first. OK, I have added documention suggesting the creation a symbolic link in /tmp to prevent server spoofing when the socket file has been moved. I think we can consider this issue concluded. I think SSL over unix domain sockets has so much overhead as to be worse in most cases than just creating the symlink. Of course if someone comes up with a better idea we can reopen this. -- Bruce Momjian <bruce@momjian.us> http://momjian.us EnterpriseDB http://postgres.enterprisedb.com + If your life is a hard drive, Christ can be your backup. + Index: doc/src/sgml/runtime.sgml =================================================================== RCS file: /cvsroot/pgsql/doc/src/sgml/runtime.sgml,v retrieving revision 1.403 diff -c -c -r1.403 runtime.sgml *** doc/src/sgml/runtime.sgml 24 Jan 2008 06:23:32 -0000 1.403 --- doc/src/sgml/runtime.sgml 31 Jan 2008 17:21:57 -0000 *************** *** 1397,1403 **** connections is to use a Unix domain socket directory (<xref linkend="guc-unix-socket-directory">) that has write permission only for a trusted local user. This prevents a malicious user from creating ! their own socket file in that directory. For TCP connections the server must accept only <literal>hostssl</> connections (<xref linkend="auth-pg-hba-conf">) and have SSL <filename>server.key</filename> (key) and --- 1397,1412 ---- connections is to use a Unix domain socket directory (<xref linkend="guc-unix-socket-directory">) that has write permission only for a trusted local user. This prevents a malicious user from creating ! their own socket file in that directory. If you are concerned that ! some applications might still look in <filename>/tmp</> for the ! socket file and hence be vulnerable to spoofing, create a symbolic link ! during operating system startup in <filename>/tmp</> that points to ! the relocated socket file. You also might need to modify your ! <filename>/tmp</> cleanup script to preserve the symbolic link. ! </para> ! ! <para> ! For TCP connections the server must accept only <literal>hostssl</> connections (<xref linkend="auth-pg-hba-conf">) and have SSL <filename>server.key</filename> (key) and