|
Vulnerability informix Affected Systems running informix Description 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.