COMMAND

    informix

SYSTEMS AFFECTED

    Systems running informix

PROBLEM

    Nathan Neulinger  found following.   The security  hole is  severe
    enough  to   basically  null   out  any   security  database/table
    permissions that you use.

    The problem  boiled down  to -  they are  using BSD ruserok() type
    security for their  remote database access  for other unix  hosts,
    but they don't bother to check the source port.  So, if you enable
    another  host  (that  you  rightly  trust  on a secure network) to
    connect to your  database server, you  have unwittingly given  ALL
    users on  that host  access to  ALL users  in the database server.
    What's worse,  within a  couple of  minutes, a  user on the remote
    machine can  run a  program (rinetd  for example)  that will allow
    ANYONE from ANYWHERE to connect to the database as any user.

    Informix 5.x  and 7.x  (probably all  versions using Informix-NET)
    purport to support BSD rhosts()/hosts.equiv mechanism for  network
    access  control.   However,  the  server  relay process (sqlexecd)
    does not verify that the connection is from a reserved port.

    The basic setup  is that you  have a database  server, and several
    other client unix stations.  You  (root) are the only one who  has
    administrator authority on all the stations.  Each client  station
    has  lots  of  users  on  them,  only  some of which have database
    access.   For each  client station  that you  want to  be able  to
    access the database server, you add it to the hosts.equiv file  on
    the database server.

    So  far,  nothing  out  of  the  ordinary.  Since (in my case) the
    network between all  the stations is  secure there is  no security
    issue at this point.

    Since the informix daemon  process (sqlexecd) does not  verify the
    source port, this results in  a major security problem, since  the
    ONLY way of trusting a socket connection from a remote host is  if
    you trust the remote host, AND the connection comes from a  secure
    port.

    Hard Method:
    ============
    Any user on a trusted host can (by learning the informix  sqlexecd
    protocol,  or  replaying  a  previously captured conversation from
    another copy of informix  software) establish a connection  to the
    database server AS -ANY- userid.

    Easy Method:
    ============
    Any user can  run a rinetd  type of relay  on a trusted  host that
    relays  the  connection  from  the  trusted  host  to the database
    server.  After  doing this, anyone  from any host  on the internet
    can use their own personal copy of informix and open a  connection
    to the trusted host, as if it were the real database server.   The
    connection will then be passed on through, and the remote sqlexecd
    will accept what it is told without checking the remote userid.

    A similar  problem occurs  using .rhosts  instead of  hosts.equiv.
    When using rhosts, assuming  the entry "host1.domain anything"  in
    'joe's  account,  any  user  on  host1.domain  can  connect to the
    database server as joe.  The value of 'anything' doesn't matter.

    In summary,  when you  add a  trusted host  - the  BSD r-tools are
    only giving  access from  one userid  to the  matching userid. The
    sqlexecd is giving access from ANY userid to ANY other userid.

    In all of the above (trusted host == host in /etc/hosts.equiv).

    b) How would you envision it being used in an attack scenario:

    Case 1:
    =======
    A local user decides they want to make a change to a database they
    have no permissions to modify.

    Step 1: Start rinetd on  a trusted host (HOST-T) that  connects to
            the database server host (HOST-DB)
    Step 2: Install informix on another unix host anywhere (HOST-C)
    Step 3: Create a userid on HOST-C that matches a userid on HOST-DB
            that  has  database  privileges,  i.e. 'informix', the DBA
            userid.
    Step 4: Log in as 'informix' on HOST-C
    Step 5: Point  Informix software on  HOST-C at HOST-T,  and open a
            connection

    Voila. You  now have  a SQL  connection to  the database server as
    'informix', and can do whatever you want.

    Case 2:
    =======
    Local user grants access using rinetd type facility to the  entire
    database  server  to  other  users  outside the organization, even
    though the local user only has minimal or no database privileges.

    Case 3:
    =======
    Current employee leaves  (fired/quits/etc).  Before  leaving, they
    put in a rinetd  service on a trusted  host.  After leaving,  they
    can still access the databases.

    This has been tested under HpUX  9.x and 10.x.  Nathan tested  and
    verified that the problem occurs with the following connections:

        - 5.x client -> 5.x server (Online)
        - 7.x client -> 7.x server (Informix-SE)
        - 7.x client -> 5.x server (Online)

    Here is more  detailed explaination.   First, a short  explanation
    of BSD ruserok() security  mechanisms.  First requirement  is that
    you trust the network between the two computers.  (i.e. two  ports
    on a switch,  an internal network  that you have  complete control
    over, etc.), or  even a network  hooked to the  internet, provided
    that the two hosts have  a trusted network between them,  and that
    you have a reasonable  router configuration (i.e. protect  against
    spoofing).

    Second, you trust  root on both  machines.  With  that, since unix
    won't let non-root users (or not setuid-root) users bind to  ports
    less than 1024, you know that  if you receive a connection from  a
    trusted host, and  it's from a  port less than  1024 then you  can
    trust that either root or a root authorized process initiated  the
    connection.   Once  that  is   established,  you  can  trust   the
    information that is sent over the connection, i.e. the userid.

    Based on documentation in informix manuals, people often configure
    their trusted hosts  to be able  to access the  database via these
    mechanisms, putting the hosts in hosts.equiv or having  individual
    users set  up .rhosts  files.   Heres where  the problem  is.  The
    Informix sqlexecd's do not bother to check the source port to make
    sure it is less than 1024.  This gives up ALL the security  in the
    ruserok() mechanism.  Since anyone can open the connection at that
    point and send whatever data  they want. (i.e. a different  userid
    than who they really are).

    Now, the 5-minute-give-me-full-access-to-everything exploit:

        1. Get  a  userid  on  any  trusted  machine - i.e. you are  a
           current/ex employee, a hole in a cgi script, whatever
        2. Compile  a  program  like  'rinetd' - basically it  accepts
           inbound tcp connections on one port, and opens a connection
           to another host on the same or different port. (This is  as
           simple as a 20-30 line c program.) This program can be  run
           by any normal user and requires no special privileges.
        3. Configure the program  to accept connections on  port 37843
           or  some  other  arbitrary  port  number,  and tell them to
           connect  to  port  1525  (or  whatever  you  have  in  your
           services/sqlhosts file) on your  database server.  Run  the
           program.
        4. Go  to  ANY  other  host  on  the  internet, get a copy  of
           informix, or Info-Maker, or  pretty much anything that  can
           talk to an informix database server.
        5. Tell the software to  open up a connection to  the database
           server running at port 37843 on the host where you ran  the
           rinetd.  Claim to be whoever you want to be.  The  database
           server will log you in without a password.

    If you  use hosts.equiv,  all userids  on the  database server are
    vulnerable.   If you  use .rhosts,  any user  that uses .rhosts is
    vulnerable - no matter what userids they list in the file.

SOLUTION

    The problem  is that  sqlexecd is  not verifying  the source port.
    There are two possible fixes:

    1) If client software will  automatically try a <1024 source  port
       if it is setuid, then just change sqlexecd to require a  source
       port <1024. (As is pretty  much mandated by saying that  you're
       doing BSD security).

    2) Alternatively, sqlexecd could attempt to verify the remote user
       using ident.   Since you've  already stated  that root  on  the
       remote host is trusted, this isn't a security problem.