登录社区:用户名: 密码: 忘记密码 网页功能:加入收藏 设为首页 网站搜索  

文档

下载

图书

论坛

安全

源码

硬件

游戏
首页 信息 空间 VB VC Delphi Java Flash 补丁 控件 安全 黑客 电子书 笔记本 手机 MP3 杀毒 QQ群 产品库 分类信息 编程网站
  立华软件园 - 安全技术中心 - 技术文档 - 漏洞分析 技术文章 | 相关下载 | 电子图书 | 攻防录像 | 安全网站 | 在线论坛 | QQ群组 | 搜索   
 安全技术技术文档
  · 安全配制
  · 工具介绍
  · 黑客教学
  · 防火墙
  · 漏洞分析
  · 破解专题
  · 黑客编程
  · 入侵检测
 安全技术工具下载
  · 扫描工具
  · 攻击程序
  · 后门木马
  · 拒绝服务
  · 口令破解
  · 代理程序
  · 防火墙
  · 加密解密
  · 入侵检测
  · 攻防演示
 安全技术论坛
  · 安全配制
  · 工具介绍
  · 防火墙
  · 黑客入侵
  · 漏洞检测
  · 破解方法
 其他安全技术资源
  · 攻防演示动画
  · 电子图书
  · QQ群组讨论区
  · 其他网站资源
最新招聘信息

Apache mod_ssl ssl_util_uuencode_binary buffer over 分析和调试方法
发表日期:2006-03-12作者:watercloud[转贴] 出处:安全焦点  

原文由dumplogin发表在Unix hacking版:
https://www.xfocus.net/bbs/index.php?act=ST&f=19&t=37176


Apache mod_ssl ssl_util_uuencode_binary buffer over 分析和调试方法
ver 1.0
(bkbll#cnhonker.net, http://www.cnhonker.net 2004/06/03)

1. 前言
    最近有一些linux厂商说要升级apache的公告,具体问题是出在mod_ssl的ssl_util_uuencode_binary函数上,
    CVE:http://cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2004-0488
    buftraq: http://www.securityfocus.com/bid/10355
    漏洞描述(from CVE):
    Stack-based buffer overflow in the ssl_util_uuencode_binary function in ssl_util.c for Apache mod_ssl when mod_ssl is

configured to trust the issuing CA,
may allow remote attackers to execute arbitrary code via a client certificate with a long subject DN.
    当时看到不是默认配置就有的,所以就没怎么看它. 后来看到论坛有人问一些相关信息, 又有邮件来问, 决定研究一下.
    调试平台:Redhat Linux 默认安装,apache 2.0.40
    [root@mobilelinux httpd]# rpm -qa|grep mod_ssl
    mod_ssl-2.0.40-8

2. 漏洞成因:
   这里:http://lists.netsys.com/pipermail/full-disclosure/2004-May/021610.html有比较详细的描述,我copy过来:
+---------------------------------------------------------------------------------+
in ssl_util.c there is:
-------------------------------------
void ssl_util_uuencode_binary(
    unsigned char *szTo, const unsigned char *szFrom, int nLength, BOOL bPad)
{
    const unsigned char *s;
    int nPad = 0;

    for (s = szFrom; nLength > 0; s += 3) {
        *szTo++ = ssl_util_uuencode_six2pr[s[0] >> 2];
/*PROPOSED PATCH: add "if (--nLegth ==0 ) ..." */
        *szTo++ = ssl_util_uuencode_six2pr[(s[0] << 4 | s[1] >> 4) & 0x3f];
        if (--nLength == 0) {
            nPad = 2;
            break;
        }
        *szTo++ = ssl_util_uuencode_six2pr[(s[1] << 2 | s[2] >> 6) & 0x3f];
        if (--nLength == 0) {
            nPad = 1;
            break;
        }
        *szTo++ = ssl_util_uuencode_six2pr[s[2] & 0x3f];
        --nLength;
    }
    while(bPad && nPad--)
        *szTo++ = NUL;
    *szTo = NUL;
    return;
}
+-----------------------------------------------------------------------------+
我们来看一下szTo和szFrom的定义:
In ssl_engine_kernel.c:

int ssl_hook_UserCheck(request_rec *r)
{
    SSLConnRec *sslconn = myConnConfig(r->connection);
    SSLSrvConfigRec *sc = mySrvConfig(r->server);
    SSLDirConfigRec *dc = myDirConfig(r);
    char buf1[MAX_STRING_LEN], buf2[MAX_STRING_LEN];
    char *clientdn;
    const char *auth_line, *username, *password;
    
    ...................
    
    apr_snprintf(buf1, sizeof(buf1), "%s:password", clientdn);
    ssl_util_uuencode(buf2, buf1, FALSE);

    apr_snprintf(buf1, sizeof(buf1), "Basic %s", buf2);
    
    ...............
    
}

In ssl_util.c:

void ssl_util_uuencode(char *szTo, const char *szFrom, BOOL bPad)
{
    ssl_util_uuencode_binary((unsigned char *)szTo,
                             (const unsigned char *)szFrom,
                             strlen(szFrom), bPad);
}

从调用关系就可以看出来,szTo和szFrom其实就是ssl_hook_UserCheck里面的buf2,buf1
大小为:MAX_STRING_LEN,来看看这个大小:
[root@DUMPLOGIN E:\download\linux\httpd-2.0.40]# grep MAX_STRING_LEN include/* -r

include/httpd.h:#define MAX_STRING_LEN HUGE_STRING_LEN
include/mpm_common.h:extern char ap_coredump_dir[MAX_STRING_LEN];

[root@DUMPLOGIN E:\download\linux\httpd-2.0.40]#grep HUGE_STRING_LEN include/* -r

include/httpd.h:#define MAX_STRING_LEN HUGE_STRING_LEN
include/httpd.h:#define HUGE_STRING_LEN 8192

大小就是0x2000

那么从ssl_util_uuencode_binary很容易看出,szTo可以大概被覆盖(0x2000/3).
我们来看看调用时候内存结构图:

低地址                         -->             高地址

|---[buf2]---|---[buf1]---| somedata |pointer | pointer | pointer | saved ebp | saved eip |------
buf2既然可以被覆盖大概0x2000/3字节,那么他能覆盖且只能覆盖到buf1,而且还不能完全覆盖buf1.
当调用ssl_util_uuencode_binary时候,buf2和buf1之间同样没有其他变量可以覆盖,所以想在这里覆盖点什么基本上
不大可能,我们只能希望于调用结束后能利用buf2做其他的事情,
但我们来看:
apr_snprintf(buf1, sizeof(buf1), "%s:password", clientdn);
ssl_util_uuencode(buf2, buf1, FALSE);

apr_snprintf(buf1, sizeof(buf1), "Basic %s", buf2);
ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,"Faking HTTP Basic Auth header: \"Authorization: %s\"", buf1);
return DECLINED;

一直到函数返回,buf2除了用做写到buf1的apr_snprintf函数一个参数外,没其他用处.
结论:在x86系统上基本没什么大作用,连让进程崩溃都不大可能.

3. 调试方法
   这里就涉及到很多关于httpd.conf配置和ssl配置方面的东西,本来很简单,但有人问起来就写下吧,其实写这个才是
本文章的主要目标.
   调试系统:redhat linux 8.0 x86默认安装.
   (1). 修改服务端配制,主要要点在于修改ssl.conf打开信任CA等相关开关.
   在此之前你需要一个ca.pl文件,该文件在各版本openssl tgz包中都有.
   [root@DUMPLOGIN E:\download\linux]#dir "openssl-0.9.7d\apps\CA.pl"
   驱动器 E 中的卷是 DOCUMENT
   卷的序列号是 F015-E42A

   E:\download\linux\openssl-0.9.7d\apps 的目录

    2004-03-17  08:08p               5,392 CA.pl
               1 个文件          5,392 字节
               0 个目录  2,449,305,600 可用字节
[root@mobilelinux ca]# ls
ca.pl
[root@mobilelinux ca]# pwd
/root/ca
[root@mobilelinux ca]# ./ca.pl -newca
CA certificate filename (or enter to create)

Making CA certificate ...
Using configuration from /usr/share/ssl/openssl.cnf
Generating a 1024 bit RSA private key
...................++++++
....++++++
writing new private key to './demoCA/private/cakey.pem'
Enter PEM pass phrase:
Verifying password - Enter PEM pass phrase:
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [GB]:
State or Province Name (full name) [Berkshire]:guangdong
Locality Name (eg, city) [Newbury]:guangzhou
Organization Name (eg, company) [My Company Ltd]:www.my.com
Organizational Unit Name (eg, section) []:test
Common Name (eg, your name or your server's hostname) []:10.10.10.114
Email Address []:bkbll@cnhonker.net
[root@mobilelinux ca]# ls
ca.pl  demoCA
[root@mobilelinux ca]# ./ca.pl -newreq
Using configuration from /usr/share/ssl/openssl.cnf
Generating a 1024 bit RSA private key
..............++++++
..++++++
writing new private key to 'newreq.pem'
Enter PEM pass phrase:
Verifying password - Enter PEM pass phrase:
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [GB]:
State or Province Name (full name) [Berkshire]:guangdong
Locality Name (eg, city) [Newbury]:guangzhou
Organization Name (eg, company) [My Company Ltd]:www.my.com
Organizational Unit Name (eg, section) []:test
Common Name (eg, your name or your server's hostname) []:homelinux
Email Address []:bkbll@tom.com

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
Request (and private key) is in newreq.pem
[root@mobilelinux ca]# ./ca.pl -sign
Using configuration from /usr/share/ssl/openssl.cnf
Enter PEM pass phrase:
Check that the request matches the signature
Signature ok
The Subjects Distinguished Name is as follows
countryName           :PRINTABLE:'GB'
stateOrProvinceName   :PRINTABLE:'guangdong'
localityName          :PRINTABLE:'guangzhou'
organizationName      :PRINTABLE:'www.my.com'
organizationalUnitName:PRINTABLE:'test'
commonName            :PRINTABLE:'homelinux'
emailAddress          :IA5STRING:'bkbll@tom.com'
Certificate is to be certified until Jun  2 11:17:20 2005 GMT (365 days)
Sign the certificate? [y/n]:y


1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
Signed certificate is in newcert.pem
[root@mobilelinux ca]# ls
ca.pl  demoCA  newcert.pem  newreq.pem
[root@mobilelinux ca]# openssl rsa < newreq.pem > newkey.pem
read RSA key
Enter PEM pass phrase:
writing RSA key
[root@mobilelinux ca]# ls
ca.pl  demoCA  newcert.pem  newkey.pem  newreq.pem
[root@mobilelinux ca]# mv newcert.pem server_cert.pem
[root@mobilelinux ca]# mv newkey.pem  server_key.pem
[root@mobilelinux ca]# mv newreq.pem  server_req.pem
然后将拷贝几个文件(demoCA/cacert.pem, server_cert.pem,server_key.pem,server_req.pem)
到随便那个目录,我的是/etc/httpd/conf/ssl/目录.
然后需要修改/etc/httpd/conf.d/ssl.conf文件:

SSLCertificateFile /etc/httpd/conf/ssl/server_cert.pem
SSLCertificateKeyFile /etc/httpd/conf/ssl/server_key.pem
SSLCACertificatePath /etc/httpd/conf/ssl.crt   /* 这个目录本来就有,就指定这个吧 */
SSLCACertificateFile /etc/httpd/conf/ssl/cacert.pem
SSLVerifyClient require
SSLVerifyDepth  10
SSLOptions +FakeBasicAuth    /* 这个一定要 */

修改/etc/httpd/conf/httpd.conf:
加这个:

<Directory /var/www/html/usage>
SSLVerifyClient      require
SSLVerifyDepth       5
SSLCACertificateFile /etc/httpd/conf/ssl/cacert.pem
SSLCACertificatePath /etc/httpd/conf/ssl.crt
SSLOptions           +FakeBasicAuth
SSLRequireSSL
AuthName             "test mod_ssl overflow site"
AuthType             Basic
AuthUserFile         /etc/httpd/conf/httpd.passwd    /* 这个文件随便指定 */
require              valid-user
</Directory>

修改后,重新启动apche
(2) 触发漏洞的client配置(IE)
在linux上给客户端生成一个证书:
[root@mobilelinux ca]# ./ca.pl -newreq
Using configuration from /usr/share/ssl/openssl.cnf
Generating a 1024 bit RSA private key
......................++++++
..++++++
writing new private key to 'newreq.pem'
Enter PEM pass phrase:
Verifying password - Enter PEM pass phrase:
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [GB]:
State or Province Name (full name) [Berkshire]:guangdong
Locality Name (eg, city) [Newbury]:guangzhou
Organization Name (eg, company) [My Company Ltd]:www.my.com
Organizational Unit Name (eg, section) []:test
Common Name (eg, your name or your server's hostname) []:dumplogin
Email Address []:dumplogin@yahoo.com

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
Request (and private key) is in newreq.pem
[root@mobilelinux ca]# ./ca.pl -sign
Using configuration from /usr/share/ssl/openssl.cnf
Enter PEM pass phrase:
Check that the request matches the signature
Signature ok
The Subjects Distinguished Name is as follows
countryName           :PRINTABLE:'GB'
stateOrProvinceName   :PRINTABLE:'guangdong'
localityName          :PRINTABLE:'guangzhou'
organizationName      :PRINTABLE:'www.my.com'
organizationalUnitName:PRINTABLE:'test'
commonName            :PRINTABLE:'dumplogin'
emailAddress          :IA5STRING:'dumplogin@yahoo.com'
Certificate is to be certified until Jun  2 11:26:58 2005 GMT (365 days)
Sign the certificate? [y/n]:y


1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
Signed certificate is in newcert.pem
[root@mobilelinux ca]# openssl pkcs12 -export -in newcert.pem -inkey newreq.pem -name "MY CERTIFICATE" -certfile

demoCA/cacert.pem -out mycert.p12
Enter PEM pass phrase:
Enter Export Password:
Verifying password - Enter Export Password:
[root@mobilelinux ca]# ls
ca.pl   mycert.p12   newreq.pem       server_key.pem
demoCA  newcert.pem  server_cert.pem  server_req.pem
[root@mobilelinux ca]#

将mycert.p12拷贝到windows下,安装该证书.
将newcert.pem拷贝到/etc/httpd/conf/ssl.crt/(SSLCACertificatePath /etc/httpd/conf/ssl.crt)  重命名为.crt扩展名的文件.
将ssl.crt/目录下的Makefile.crt重命名为Makefile
运行make,会自动生成一个link文件.
再将这个crt的内容添加到cacert.pem文件(SSLCACertificateFile /etc/httpd/conf/ssl/cacert.pem)
cat newcert.crt >> /etc/httpd/conf/ssl/cacert.pem
  重新启动apache.

  (3). 调试工具.
  linux下当然用gdb, windows下我用windbg,以方便server端能attach进程.
  (4). 开始调试
  启动浏览器,配置一下,将 使用ssl2,ssl3,tls1.0 全部勾上.
  然后打开windbg, F6 attach到该浏览器, 设置断点:bp ws2_32!send
  然后bd 0,暂时禁止断点.
  从浏览器上输入linux机器的地址(注意要是刚才在httpd.conf里定义的保护站点,就是usage目录),如果以上步骤正确的话,应该会出来一个选

择证书的对话框:
  选择刚才linux颁发的证书,不要点确定哦,回到windbg,按ctrl+break,be 0,启动断点,g,这个时候回到
  IE窗口,点确定,ok,IE挂起来了.
  回到linux,在root用户下寻找到处理该请求的进程ID:
  [root@mobilelinux ca]# netstat -antp |grep ":443"|grep ESTABLISHED
  tcp        0      0 10.10.10.114:443        10.10.10.111:4625       ESTABLISHED 2563/httpd
  [root@mobilelinux ca]#
  PID 2563就是我们所要的.
  [root@mobilelinux ca]# gdb -q -se /usr/sbin/httpd
(no debugging symbols found)...(gdb) attach 2563
Attaching to program: /usr/sbin/httpd, process 2563
Reading symbols from /usr/lib/libz.so.1...done.
Loaded symbols for /usr/lib/libz.so.1
Reading symbols from /lib/libssl.so.2...done.
.............................

Loaded symbols for /usr/lib/liblber.so.2
Reading symbols from /usr/lib/libsasl.so.7...done.
Loaded symbols for /usr/lib/libsasl.so.7
Reading symbols from /lib/libnss_nisplus.so.2...done.
Loaded symbols for /lib/libnss_nisplus.so.2
0x420d224b in poll () from /lib/i686/libc.so.6
(gdb)
然后输入断点:
(gdb) b *ssl_hook_UserCheck
Breakpoint 1 at 0x4096a0e0
(gdb) b *ssl_util_uuencode
Breakpoint 2 at 0x40975cc0
(gdb) b *ssl_util_uuencode_binary
Breakpoint 3 at 0x40975d10
这个时候就已经不需要windbg设置的断点了,bd 0,g
再回到刚才的linux窗口:
(gdb) c
Continuing.
[Switching to Thread 8192 (LWP 3331)]

Breakpoint 1, 0x4096a0e0 in ssl_hook_UserCheck ()
   from /etc/httpd/modules/mod_ssl.so
(gdb) c
Continuing.

Breakpoint 2, 0x40975cc0 in ssl_util_uuencode ()
   from /etc/httpd/modules/mod_ssl.so
(gdb) x/4wx $esp
0xbfffb88c:     0x4096a229      0xbfffb8d0      0xbfffd8d0      0x00000000
(gdb) x/bs 0xbfffd8d0
0xbfffd8d0:      "/C=GB/ST=guangdong/L=guangzhou/O=www.my.com/OU=test/CN=10.10.10.114/Email=dumplogin@yahoo.com:password"
(gdb) x/bx 0xbfffd8d0
0xbfffd8d0:     0x2f
(gdb) c
Continuing.

Breakpoint 3, 0x40975d10 in ssl_util_uuencode_binary ()
   from /etc/httpd/modules/mod_ssl.so
(gdb)

剩下的事情就不需要我多说了,enjoy it :)

4. 参考:
[1]. http://cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2004-0488
[2]. http://www.modssl.org/docs/2.8/ssl_howto.html
[3]. http://www.drh-consultancy.demon.co.uk/pkcs12faq.html
[4]. http://www.redhat.com/docs/manuals/stronghold/Stronghold-3.0-Manual/admin-guide/chapter2.fm.html
[5]. http://www.freebsddiary.org/openssl-client-authentication.php

我来说两句】 【发送给朋友】 【加入收藏】 【返加顶部】 【打印本页】 【关闭窗口
中搜索 Apache mod_ssl ssl_util_uuencode_binary buffer over 分析和调试方法

 ■ [欢迎对本文发表评论]
用  户:  匿名发出:
您要为您所发的言论的后果负责,故请各位遵纪守法并注意语言文明。

最新招聘信息

关于我们 / 合作推广 / 给我留言 / 版权举报 / 意见建议 / 广告投放 / 友情链接  
Copyright ©2001-2006 Lihuasoft.net webmaster(at)lihuasoft.net
网站编程QQ群   京ICP备05001064号 页面生成时间:0.00207