Datesfat Chicks <datesfat.chi...@gmail.com> wrote: > I'm using pipes to pass sensitive information to a child process (spawned > from a PHP script) and also to get back the output. > I didn't use command-line arguments because these are insecure. > Is an anonymous pipe secure from other UIDs?
They're as secure as any other descriptor, such as to a socket or file.
In article <2a39s6-9l9....@wilbur.25thandClement.com>, William Ahern <will...@wilbur.25thandClement.com> wrote:
> Datesfat Chicks <datesfat.chi...@gmail.com> wrote: > > I'm using pipes to pass sensitive information to a child process (spawned > > from a PHP script) and also to get back the output.
> > I didn't use command-line arguments because these are insecure.
> > Is an anonymous pipe secure from other UIDs?
> They're as secure as any other descriptor, such as to a socket or file.
More so. An anonymous pipe doesn't exist in the filesystem, so you can't inadvertently chmod it incorrectly.
There's no API to access the data in an anonymous pipe, except by the process that created it and its descendants. You'd need to read kernel memory to do it from another process, and this requires root privileges.
-- Barry Margolin, bar...@alum.mit.edu Arlington, MA *** PLEASE post questions in newsgroups, not directly to me *** *** PLEASE don't copy me on replies, I'll read them in the group ***
Barry Margolin <bar...@alum.mit.edu> wrote: > In article <2a39s6-9l9....@wilbur.25thandClement.com>, > William Ahern <will...@wilbur.25thandClement.com> wrote:
> > Datesfat Chicks <datesfat.chi...@gmail.com> wrote: > > > I'm using pipes to pass sensitive information to a child process (spawned > > > from a PHP script) and also to get back the output.
> > > I didn't use command-line arguments because these are insecure.
> > > Is an anonymous pipe secure from other UIDs?
> > They're as secure as any other descriptor, such as to a socket or file.
> More so. An anonymous pipe doesn't exist in the filesystem, so you > can't inadvertently chmod it incorrectly.
> There's no API to access the data in an anonymous pipe, except by the > process that created it and its descendants. You'd need to read kernel > memory to do it from another process, and this requires root privileges.
I was hesitant to make that assertion, and too lazy to confirm it, but you've forced my hand ;)
Compile the following and simply execute `cat $(./foo)`. Confirmed to work on Ubuntu Linux, kernel 2.6.28-15-generic, with /proc mounted. That puts anonymous pipes squarely in the realm of file system addressable _and_ accessible objects. I'm unable to change the mode on that file, but strictly speaking that's beside the point. Perhaps a socket pair might be more trouble, but I think prudence dictates that in analyzing the security of anonymous pipes one should simply include them in the class of general file descriptors and move on to more important concerns.
#include <stdio.h>
#include <unistd.h>
int main(void) { int fd[2], pid, i, n; char buf[32];
pipe(fd);
if ((pid = fork())) { printf("/proc/%d/fd/%d\n", pid, fd[0]);
return 0; }
close(0); close(1); close(2);
for (i = 0; i < 1U<<14; i++) { n = sprintf(buf, "%d\n", i);
> Barry Margolin <bar...@alum.mit.edu> wrote: >> In article <2a39s6-9l9....@wilbur.25thandClement.com>, >> William Ahern <will...@wilbur.25thandClement.com> wrote:
>> > Datesfat Chicks <datesfat.chi...@gmail.com> wrote: >> > > I'm using pipes to pass sensitive information to a child process >> > > (spawned >> > > from a PHP script) and also to get back the output.
>> > > I didn't use command-line arguments because these are insecure.
>> > > Is an anonymous pipe secure from other UIDs?
>> > They're as secure as any other descriptor, such as to a socket or file.
>> More so. An anonymous pipe doesn't exist in the filesystem, so you >> can't inadvertently chmod it incorrectly.
>> There's no API to access the data in an anonymous pipe, except by the >> process that created it and its descendants. You'd need to read kernel >> memory to do it from another process, and this requires root privileges.
> I was hesitant to make that assertion, and too lazy to confirm it, but > you've forced my hand ;)
> Compile the following and simply execute `cat $(./foo)`. Confirmed to work > on Ubuntu Linux, kernel 2.6.28-15-generic, with /proc mounted. That puts > anonymous pipes squarely in the realm of file system addressable _and_ > accessible objects. I'm unable to change the mode on that file, but > strictly > speaking that's beside the point. Perhaps a socket pair might be more > trouble, but I think prudence dictates that in analyzing the security of > anonymous pipes one should simply include them in the class of general > file > descriptors and move on to more important concerns.
> #include <stdio.h>
> #include <unistd.h>
> int main(void) { > int fd[2], pid, i, n; > char buf[32];
> pipe(fd);
> if ((pid = fork())) { > printf("/proc/%d/fd/%d\n", pid, fd[0]);
> return 0; > }
> close(0); > close(1); > close(2);
> for (i = 0; i < 1U<<14; i++) { > n = sprintf(buf, "%d\n", i);
> write(fd[1], buf, n); > }
> return 0; > } /* main() */
You've confused me a bit. Your program does not demonstrate that a process that is neither parent nor child can access the pipe. So Barry's comments seem correct.
Datesfat Chicks <datesfat.chi...@gmail.com> wrote: > You've confused me a bit. Your program does not demonstrate that a process > that is neither parent nor child can access the pipe. So Barry's comments > seem correct. > Did I miss something?
Yes. In this case it's neither parent nor even ancestor doing the read. With `cat $(./foo)` the shell first forks and executes foo, which prints a file path string, [forks again,] and blocks on the write. The string is then passed to cat with another fork from the shell, so there's no lineal descent between the cat process and the process which created the pipe, and certainly no descriptor inheritance.
Anyhow, you can just skip the whole `cat $(./foo)` business; I just provided it for completeness. Execute the program, then login in on another terminal and cat--or otherwise attempt to open + read--the printed file path. This worked for me as well.
> You've confused me a bit. Your program does not demonstrate that a process > that is neither parent nor child can access the pipe. So Barry's comments > seem correct.
[...]
$ echo this | sleep 999 & [1] 4396 4397 $ cat /proc/4397/fd/0 this
$ sleep 999 | tr a b & [1] 4401 4402 $ echo aaa > /proc/4401/fd/1 bbb
Stephane CHAZELAS <stephane_chaze...@yahoo.fr> writes: > 2009-11-5, 00:55(-05), Datesfat Chicks: > [...] >> You've confused me a bit. Your program does not demonstrate that a process >> that is neither parent nor child can access the pipe. So Barry's comments >> seem correct. > [...]
> $ echo this | sleep 999 & > [1] 4396 4397 > $ cat /proc/4397/fd/0 > this
<sarcasm> Congratulations. You have just demonstrated that users are allowed to read their own files. </sarcasm>
Until David Woodhouse comes along and changes the default mode for /proc-files to 0666 because security is nowadays done differently, that's sufficiently save from eavesdroppers.
Rainer Weikusat <rweiku...@mssgmbh.com> writes: >Stephane CHAZELAS <stephane_chaze...@yahoo.fr> writes: >> 2009-11-5, 00:55(-05), Datesfat Chicks: >> [...] >>> You've confused me a bit. Your program does not demonstrate that a process >>> that is neither parent nor child can access the pipe. So Barry's comments >>> seem correct. >> [...]
>> $ echo this | sleep 999 & >> [1] 4396 4397 >> $ cat /proc/4397/fd/0 >> this
>> $ sleep 999 | tr a b & >> [1] 4401 4402 >> $ echo aaa > /proc/4401/fd/1 >> bbb ><sarcasm> >Congratulations. You have just demonstrated that users are allowed to >read their own files. ></sarcasm> >Until David Woodhouse comes along and changes the default mode for >/proc-files to 0666 because security is nowadays done differently, >that's sufficiently save from eavesdroppers.
For what it's worth, Solaris' proc filesystem doesn't allow you to open such files using /proc. Ordinary files, I believe yes, but then it works like "dup()".
Casper -- Expressed in this posting are my opinions. They are in no way related to opinions held by my employer, Sun Microsystems. Statements on Sun products included here are not gospel and may be fiction rather than truth.
> Stephane CHAZELAS <stephane_chaze...@yahoo.fr> writes: >> 2009-11-5, 00:55(-05), Datesfat Chicks: >> [...] >>> You've confused me a bit. Your program does not demonstrate that a >>> process >>> that is neither parent nor child can access the pipe. So Barry's >>> comments >>> seem correct. >> [...]
>> $ echo this | sleep 999 & >> [1] 4396 4397 >> $ cat /proc/4397/fd/0 >> this
> <sarcasm> > Congratulations. You have just demonstrated that users are allowed to > read their own files. > </sarcasm>
> Until David Woodhouse comes along and changes the default mode for > /proc-files to 0666 because security is nowadays done differently, > that's sufficiently save from eavesdroppers.
Thanks. I believe this level of security is sufficient for my application.
My application is that I have a web script (PHP) invoking a compiled C executable, and passing sensitive information via a pipe and getting a non-sensitive result back via a pipe. The sensitive information is a cryptographic device key.
The web server and the C executable will both run under the UID/GID of the web server. No possible attacker in the system will be able to run a process under that UID/GID. So I'm satisfied with this result.
However, other processes with the same UID/GID being able to intercept what goes on between parent and child could, in other contexts, be a security problem. So I'll remember what was demonstrated in this thread.
> > $ sleep 999 | tr a b & > > [1] 4401 4402 > > $ echo aaa > /proc/4401/fd/1 > > bbb > <sarcasm> > Congratulations. You have just demonstrated that users are allowed to > read their own files. > </sarcasm>
The sarcasm seems a little unwarranted. The point was exactly to show that anonymous pipes could be accessible just like _files_.
> Until David Woodhouse comes along and changes the default mode for > /proc-files to 0666 because security is nowadays done differently, > that's sufficiently save from eavesdroppers.
You're clearly missing the point. We've gone from a system where anonymous pipes are unique because you can't even derive a reference to them, period, to where you're depending on mode permissions. The profile is totally different. Whether one or the other is more or less safe is completely beside the point of this sub-thread.
But actually, now that I think about it, you're flat wrong, anyhow.
The OP is presumably validating passwords entered into a web form and submitted to a CGI script. Assume, arguendo, that the OP is using PHP. Assume, arguendo, that the OP is executing a setuid utility, so that the web server doesn't actually have direct access to the password database. Now, let's also assume (and I know this is a big leap, because PHP has such a stellar track record) that an attacker finds an exploit in some script that allows him to, say, do something as simple as "passthru(fopen(/proc/N/fd/N))". Said attacker can now collect passwords.
So, the difference is significant. This is why I use OpenBSD, which not only has no /proc, but which chroot's Apache and randomizes PID's. Of course, the OP could configure his Linux system to chroot his web server, and to make sure that /proc is not mounted inside the chroot. Or, the OP could do nothing, judging the scenario to be inconsequential. Both valid options, but options to be considered because there really is a distinction here.
>> <sarcasm> >> Congratulations. You have just demonstrated that users are allowed to >> read their own files. >> </sarcasm>
> The sarcasm seems a little unwarranted. The point was exactly to show that > anonymous pipes could be accessible just like _files_.
The subject of the thread is 'Can Unix Anonymous Pipes Be Eavesdropped On (By a Non-Root User)?' and the answer is 'they cannot'.
>> Until David Woodhouse comes along and changes the default mode for >> /proc-files to 0666 because security is nowadays done differently, >> that's sufficiently save from eavesdroppers.
> You're clearly missing the point.
Nope. You were missing the reference to a recent 'Linux exploit' which was only possible because the /dev/net/tun default permissions, as nowadays set by udev for anyone who actually wants to run this program, had been changed to 0666 'because the code is nowadays doing capability checks'.
> We've gone from a system where anonymous > pipes are unique because you can't even derive a reference to them, period, > to where you're depending on mode permissions.
... which are set to a fixed value when the corresponding /proc pseudofile is created.
[...]
> But actually, now that I think about it, you're flat wrong, anyhow.
> The OP is presumably validating passwords entered into a web form and > submitted to a CGI script. Assume, arguendo, that the OP is using PHP. > Assume, arguendo, that the OP is executing a setuid utility, so that the web > server doesn't actually have direct access to the password database. Now, > let's also assume (and I know this is a big leap, because PHP has such a > stellar track record) that an attacker finds an exploit in some script that > allows him to, say, do something as simple as > "passthru(fopen(/proc/N/fd/N))". Said attacker can now collect > passwords.
If 'an attacker' can execute code written by him as the user the web server runs as, security has quite obviously been compromised and bad things are bound to happen. But this digression is in no way related to the question if unprivileged users can 'eavesdrop' on pipes created by other users. They cannot.
>>> <sarcasm> >>> Congratulations. You have just demonstrated that users are allowed to >>> read their own files. >>> </sarcasm>
>> The sarcasm seems a little unwarranted. The point was exactly to show that >> anonymous pipes could be accessible just like _files_.
>The subject of the thread is 'Can Unix Anonymous Pipes Be Eavesdropped >On (By a Non-Root User)?' and the answer is 'they cannot'.
Sure they can, so long as the "non-root user"[*] has the same UID. Since the OP was in the context of PHP, one can assume that it is running using the apache (or apache2) UID. I think one should be concerned about this; PHP isn't known as the most secure form of CGI.
> > <sarcasm> > > Congratulations. You have just demonstrated that users are allowed to > > read their own files. > > </sarcasm>
> The sarcasm seems a little unwarranted. The point was exactly to show that > anonymous pipes could be accessible just like _files_.
> > Until David Woodhouse comes along and changes the default mode for > > /proc-files to 0666 because security is nowadays done differently, > > that's sufficiently save from eavesdroppers.
> You're clearly missing the point. We've gone from a system where anonymous > pipes are unique because you can't even derive a reference to them, period, > to where you're depending on mode permissions. The profile is totally > different. Whether one or the other is more or less safe is completely > beside the point of this sub-thread.
Since a process can read the memory of other processes belonging to the same UID, this doesn't really give them access to anything they didn't already have access to.
Another thing: I think reading the pipe this way is not passive. Anything read by the interceptor will not be seen by the original reader of the pipe, and vice versa. So you can't really eavesdrop on the conversation, because you'll interrupt it.
-- Barry Margolin, bar...@alum.mit.edu Arlington, MA *** PLEASE post questions in newsgroups, not directly to me *** *** PLEASE don't copy me on replies, I'll read them in the group ***
> Another thing: I think reading the pipe this way is not passive. > Anything read by the interceptor will not be seen by the original reader > of the pipe, and vice versa. So you can't really eavesdrop on the > conversation, because you'll interrupt it.
If the process which has access to the read-end of the pipe also has access to the write-end, it can also write new data by going through the /proc-file. In theory, that's a classic man-in-the-middle-attack except that sufficient privileges to cause mischief to both of the communicating processes must already be available.
Stephane CHAZELAS <stephane_chaze...@yahoo.fr> writes: > 2009-11-06, 11:36(+01), Rainer Weikusat: > [...] >>>>The subject of the thread is 'Can Unix Anonymous Pipes Be Eavesdropped >>>>On (By a Non-Root User)?' and the answer is 'they cannot'.
>>> Sure they can, so long as the "non-root user"[*] has the same UID.
>> Quoting myself:
>> But this digression is in no way related to the question if >> unprivileged users can 'eavesdrop' on pipes >> created by other users. They cannot.
>> [...]
>>> [*] OP _didn't_ say 'different non-root user'.
>> Meanwhile, he did.
> They can be eavesdropped by a different user with the same uid, > or any non-root user with uid 0 ;-).
For the purpose of UNIX(*), a 'user' is an entity identified by a particular user id. For obvious reasons, no 1:1 mapping of UNIX(*) user IDs and 'intelligent beings on this planet' exists.
> > Another thing: I think reading the pipe this way is not passive. > > Anything read by the interceptor will not be seen by the original reader > > of the pipe, and vice versa. So you can't really eavesdrop on the > > conversation, because you'll interrupt it.
> If the process which has access to the read-end of the pipe also has > access to the write-end, it can also write new data by going through > the /proc-file. In theory, that's a classic man-in-the-middle-attack > except that sufficient privileges to cause mischief to both of the > communicating processes must already be available.
It seems to me that it would be very difficult to make this work. If two processes are both reading from the pipe, it's unpredictable which one will get any particular block of data. And if the MITM tries to write back, his write may end up out of order.
Actually, it might not be so hard, now that I think some more. Since this MITM has to be either root or the same UID as the pipe owner, it can also send the reader and writer processes SIGSTOP and SIGSTART. So it can stop the regular processes, read what it wants, write it back, then start them up again. Kind of like Hiro in Heroes....
-- Barry Margolin, bar...@alum.mit.edu Arlington, MA *** PLEASE post questions in newsgroups, not directly to me *** *** PLEASE don't copy me on replies, I'll read them in the group ***
Barry Margolin wrote: > Actually, it might not be so hard, now that I think some more. Since > this MITM has to be either root or the same UID as the pipe owner, it > can also send the reader and writer processes SIGSTOP and SIGSTART. So > it can stop the regular processes, read what it wants, write it back, > then start them up again. Kind of like Hiro in Heroes....
Why go to this length, just become the debugger of the program and intercept the system calls.
Barry Margolin <bar...@alum.mit.edu> wrote: > In article <sgbbs6-ndl....@wilbur.25thandClement.com>, > William Ahern <will...@wilbur.25thandClement.com> wrote: <snip> > > You're clearly missing the point. We've gone from a system where anonymous > > pipes are unique because you can't even derive a reference to them, period, > > to where you're depending on mode permissions. The profile is totally > > different. Whether one or the other is more or less safe is completely > > beside the point of this sub-thread. > Since a process can read the memory of other processes belonging to the > same UID, this doesn't really give them access to anything they didn't > already have access to.
That argument just isn't valid. In as much as there can be bugs at any level, including at the kernel and hardware level, you can't argue that any possible security system can be logically reduced to no security just because there are a series of steps you can take to break every link in the chain.
Languages such as PHP and Java are designed to _prevent_ access to system-level calls, including signaling. You can't say that just because you could use signals and/or process tracing that the /proc issue is meaningless. On the contrary, the /proc issue is important because it's far easier to use in an exploit than some other means requiring breaking out of the interpreter and doing ad-hoc system calls. If one could simply discount any measure in order to argue against a distinction, one could discount all measures and nullify all distinctions.
As a practical matter, you're certainly right. Privilege separation, including using separate UIDs to prevent interprocess signaling, is important, and I can appreciate reducing security analyses in some contexts to canonical scenarios that rest upon distinctions the kernel enforces. Yet in that case, the vast majority of all web applications' security models (which ultimately rest upon one web process UID with unfettered access to all data) completely fail your security analysis. In fact, I completely agree that the state of things is ridiculous. But that's a completely unproductive way to approach the issue, in general, and in this case in particular.
System authentication in BSD/OS and OpenBSD uses a design very similar to the OP's--communicating to an authentication agent through an anonymous pipe. I think people would be less inclined to discount the issue in that context. At a minimum I would think there'd be warning messages in man pages or elsewhere that remind people about the issue.
On Nov 6, 11:31 pm, Golden California Girls <gldncag...@aol.com.mil> wrote:
> Barry Margolin wrote: > > Actually, it might not be so hard, now that I think some more. Since > > this MITM has to be either root or the same UID as the pipe owner, it > > can also send the reader and writer processes SIGSTOP and SIGSTART. So > > it can stop the regular processes, read what it wants, write it back, > > then start them up again. Kind of like Hiro in Heroes....
> Why go to this length, just become the debugger of the program and intercept the > system calls.
I don't think that would work if the debugging symbols got stripped from a program. Here is what I get when I attempt to debug a stripped program.
[cdalten@localhost oakland]$ file zero zero: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.6.9, dynamically linked (uses shared libs), for GNU/Linux 2.6.9, stripped [cdalten@localhost oakland]$ gdb zero GNU gdb Red Hat Linux (6.5-8.fc6rh) Copyright (C) 2006 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i386-redhat-linux-gnu"... (no debugging symbols found) Using host libthread_db library "/lib/libthread_db.so.1".
(gdb) disassemble main No symbol table is loaded. Use the "file" command. (gdb)
K-mart Cashier <cdal...@gmail.com> writes: > On Nov 6, 11:31 pm, Golden California Girls <gldncag...@aol.com.mil> > wrote: >> Barry Margolin wrote: >> > Actually, it might not be so hard, now that I think some more. Since >> > this MITM has to be either root or the same UID as the pipe owner, it >> > can also send the reader and writer processes SIGSTOP and SIGSTART. So >> > it can stop the regular processes, read what it wants, write it back, >> > then start them up again. Kind of like Hiro in Heroes....
>> Why go to this length, just become the debugger of the program and >> intercept the system calls.
> I don't think that would work if the debugging symbols got stripped > from a program. Here is what I get when I attempt to debug a stripped > program.
You can always intercept the system calls, debugging symbols or not. Try running a stripped executable under strace and see for yourself.
Rainer Weikusat wrote: > For the purpose of UNIX(*), a 'user' is an entity identified by a > particular user id.
Not always. From the SUSv4 description of getlogin():
If getlogin() returns a non-null pointer, then that pointer points to the name that the user logged in under, even if there are several login names with the same user ID.
>> For the purpose of UNIX(*), a 'user' is an entity identified by a >> particular user id.
> Not always. From the SUSv4 description of getlogin():
> If getlogin() returns a non-null pointer, then that pointer points > to the name that the user logged in under, even if there are > several login names with the same user ID.
I was looking at SUSv4 as well, and there's possible confusion about whether there may be more than one user name per user id.
In the definition section, both user name and user id are used to determine a user is the user database. One can read that as - one user id determines one user - one user name determines one user - so there can only be one user name per user id.
The getpwuid() leaves it open whether there may be more than one user per uid, but is not very explicit and gives no pointer on how to retrieve the other matching users, or if 2 subsequent calls to the function are likely to retrieve the same entry (assuming the database has not been modified inbetween)
SUSv4's getpwnam() seems to also allow more than one user for a user name, though I don't know of any Unix implementation where the login name is not a unique key in the user database.
The example section has this though: SUSv4> The following example uses the getlogin() function to SUSv4> return the name of the user who logged in; this SUSv4> information is passed to the getpwnam() function to get SUSv4> the user database entry for that user. ~~~
I'd have expected "...to get a user database entry for that user name" given that getpwnam() is only meant to retrieve _a_ matching entry.