Re: [HACKERS] Fwd: init scripts and su

2004-08-09 Thread Peter Eisentraut
Tom Lane wrote:
> (a) And there would be untrusted code running as postgres exactly
> why?

Because someone has cracked the PostgreSQL server.

> (b) Seems to me the real security bug here is the mere existence of
> that ioctl call.

Probably.  I'm just pointing out the findings about the environment 
we're operating in.  The fact is that right now "run as postgres to 
protect your root account" won't work on some systems and with 
unfortunately written init scripts.

-- 
Peter Eisentraut
http://developer.postgresql.org/~petere/


---(end of broadcast)---
TIP 4: Don't 'kill -9' the postmaster


Re: [HACKERS] Fwd: init scripts and su

2004-08-06 Thread Andreas Pflug
Tom Lane wrote:
Christopher Kings-Lynne <[EMAIL PROTECTED]> writes:
I was asked on IRC just why we can't have user=postgres and 
group=postgres in the postgresql.conf, and simply when we are run as 
root, switch to that user and group.

I should think that running as root up until sometime after we have read
postgresql.conf would open up more security issues.  It's certainly not
a way to close this one...
postmaster could use postgres/postgres by default, overridable by 
command line.

Regards,
Andreas
---(end of broadcast)---
TIP 6: Have you searched our list archives?
  http://archives.postgresql.org


Re: [HACKERS] Fwd: init scripts and su

2004-08-05 Thread Tom Lane
Christopher Kings-Lynne <[EMAIL PROTECTED]> writes:
> I was asked on IRC just why we can't have user=postgres and 
> group=postgres in the postgresql.conf, and simply when we are run as 
> root, switch to that user and group.

I should think that running as root up until sometime after we have read
postgresql.conf would open up more security issues.  It's certainly not
a way to close this one...

regards, tom lane

---(end of broadcast)---
TIP 9: the planner will ignore your desire to choose an index scan if your
  joining column's datatypes do not match


Re: [HACKERS] Fwd: init scripts and su

2004-08-05 Thread Christopher Kings-Lynne
During the time between the daemon launch and it closing it's file
handles and calling setsid(2) (which some daemons don't do because
they are buggy) any other code running in the same UID could take over
the process via ptrace, fork off a child process that inherits the
administrator tty, and then stuff characters into the keyboard buffer
with ioctl(fd,TIOCSTI,&c) (*).

(a) And there would be untrusted code running as postgres exactly why?
(b) Seems to me the real security bug here is the mere existence of that
ioctl call.
I was asked on IRC just why we can't have user=postgres and 
group=postgres in the postgresql.conf, and simply when we are run as 
root, switch to that user and group.

Chris
---(end of broadcast)---
TIP 8: explain analyze is your friend


Re: [HACKERS] Fwd: init scripts and su

2004-08-05 Thread Tom Lane
Peter Eisentraut <[EMAIL PROTECTED]> writes:
> For your amusement...

> During the time between the daemon launch and it closing it's file
> handles and calling setsid(2) (which some daemons don't do because
> they are buggy) any other code running in the same UID could take over
> the process via ptrace, fork off a child process that inherits the
> administrator tty, and then stuff characters into the keyboard buffer
> with ioctl(fd,TIOCSTI,&c) (*).

(a) And there would be untrusted code running as postgres exactly why?

(b) Seems to me the real security bug here is the mere existence of that
ioctl call.

regards, tom lane

---(end of broadcast)---
TIP 2: you can get off all lists at once with the unregister command
(send "unregister YourEmailAddressHere" to [EMAIL PROTECTED])


[HACKERS] Fwd: init scripts and su

2004-08-05 Thread Peter Eisentraut
For your amusement...

-- 
Peter Eisentraut
http://developer.postgresql.org/~petere/
--- Begin Message ---
The start scripts for some daemons do "su - user" or use
"start-stop-daemon -c" to launch the daemon, postgresql is one example.

During the time between the daemon launch and it closing it's file handles and 
calling setsid(2) (which some daemons don't do because they are buggy) any 
other code running in the same UID could take over the process via ptrace, 
fork off a child process that inherits the administrator tty, and then stuff 
characters into the keyboard buffer with ioctl(fd,TIOCSTI,&c) (*).

To address these issues for Fedora I have written a program named init_su.

init_su closes all file handles other than 1 and 2 (stdout and stderr).  File
handles 1 and 2 are fstat()'d, if they are regular files or pipes then they
are left open (no attack is possible through a file or pipe), otherwise they
are closed and /dev/null is opened instead.  /dev/null is opened for file
handle 0 regardless of what it might have pointed to previously.  Then
setsid() is called to create a new session for the process (make it a group
leader), this invalidates /dev/tty.  Then the uid is changed and the daemon
is started.


I have attached the source code to init_su, please check it out and tell me
what you think.  After the discussion concludes I will write a patch for 
start-stop-daemon to give similar functionality.


(*)  On system boot and shutdown there is no problem.  It's when the
administrator uses /etc/init.d/postgresql to start or stop the database that
there is potential for attack.


http://www.redhat.com/archives/fedora-devel-list/2004-July/msg01314.html

I have also started a similar discussion on the Fedora development list about 
this issue, see the above URL.

--
http://www.coker.com.au/selinux/   My NSA Security Enhanced Linux packages
http://www.coker.com.au/bonnie++/  Bonnie++ hard drive benchmark
http://www.coker.com.au/postal/Postal SMTP/POP benchmark
http://www.coker.com.au/~russell/  My home page
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

void usage(const char * const msg)
{
  if(msg)
fprintf(stderr, "Error: %s\n\n", msg);
  fprintf(stderr, "Usage: init_su [-l] user -c command\n");
  exit(1);
}

int main(int argc, char **argv)
{
  int i, fd;
  int login = 0;
  char *command = NULL, *user = NULL, *shell = NULL, *nu_argv[4];
  struct passwd *pw;

  int int_c = 0;
  while(int_c != -1)
  {
int_c = getopt(argc, argv, "-lc:s:");
switch(int_c)
{
  case 1:
if(!strcmp(optarg, "-"))
{
  login = 1;
}
else
{
  user = optarg;
}
  break;
  case 'l':
login = 1;
  break;
  case 's':
shell = optarg;
  break;
  case 'c':
command = optarg;
  break;
}
  }
  if(!user || !command)
usage(NULL);
  pw = getpwnam(user);
  if(!pw)
usage("User unknown.");
  if(setregid(pw->pw_gid, pw->pw_gid))
usage("Can't setgid(), are you root?");
  if(setreuid(pw->pw_uid, pw->pw_uid))
usage("Can't setuid(), are you root?");
  if(!shell)
shell = pw->pw_shell;
  if(login)
  {
nu_argv[0] = strrchr(shell, '/');
if(!nu_argv[0])
  usage("Bad shell.");
nu_argv[0] = strdup(nu_argv[0]);
nu_argv[0][0] = '-';
  }
  else
nu_argv[0] = shell;
  nu_argv[1] = "-c";
  nu_argv[2] = command;
  nu_argv[3] = NULL;
  close(0);
  for(i = 3; i < 1024; i++)
close(i);
  openlog("initrc_su", LOG_CONS | LOG_NOWAIT, LOG_DAEMON);
  fd = open("/dev/null", O_RDWR);
  if(fd == -1)
  {
syslog(LOG_ERR, "Can't open /dev/null when trying to execute program %s", command);
return 1;
  }
  for(i = 0; i < 3; i++)
  {
struct stat sbuf;
if(i != fd && (fstat(i, &sbuf) == -1 || (!S_ISREG(sbuf.st_mode) && !S_ISFIFO(sbuf.st_mode)) ))
{
  close(i);
  if(dup2(fd, i) != i)
  {
syslog(LOG_ERR, "Can't dup2() when trying to execute program %s", command);
return 1;
  }
}
  }
  if(fd >= 3)
close(fd);
  setsid();  /* it's OK if this fails as we get the right result anyway */
  execv(shell, nu_argv);
  syslog(LOG_ERR, "Can't exec program %s", command);
  return 1;
}
--- End Message ---

---(end of broadcast)---
TIP 2: you can get off all lists at once with the unregister command
(send "unregister YourEmailAddressHere" to [EMAIL PROTECTED])