Box cutting, or how I stumbled onto a serious security flaw in Box Sync for Mac
07 Feb 2015 by Pepijn BruienneTL;DR - Update to Box Sync for Mac 4.0.6035 immediately. The app exposes several sensitive bits of data like API keys, internal user IDs, URLs and passwords. Read on for details.
The trouble with Box Sync
Recently I revisited the convoluted mess that is the Box Sync application for Mac. If you are a Mac Admin in charge of even a small deployment environment you probably know how tedious it is to deploy the Box Sync application and manage its settings. Its only deployment method is an application bundle, which would be fine if it behaved like a normal drag and drop application: to deploy it your mass-deployment tool simply copies the application to /Applications
, uses a profile or MCX to configure settings published by the vendor and all is well. Not so with Box Sync. Box offers instructions on how to deploy Box Sync for large scale clients which require the Mac Admin does the following:
- Copy the Box Sync application to
/Applications
- Copy
/Applications/Box Sync.app/Contents/Resources/com.box.sync.bootstrapper
to/Library/PrivilegedHelperTools
- Run
sudo /Applications/Box Sync.app/Contents/Resources/com.box.sync.bootstrapper
which performs first run setup
To many Mac Admins it will occur that these steps would be better handled by using a standard Apple PKG, and they would be correct. Performing manual copy operations followed by running commands to finalize the installation by hand doesn’t scale very well. Apple installer packages are rather good at placing files in specific filesystem locations with specific ownerships and permissions (step one and two in the Box Sync install process) and afterwards running post-install commands to further configure the application for use by the end user (step three). Further complications arise once the Box Sync application is installed because of its default behavior to automatically update in the background. This is fine for home users but in a large deployment where an admin maintains a workflow where all software updates flow through “testing”, “QA” and “production” stages this is problematic. Very little information is available from Box regarding changing the application’s default preferences, nor does the application’s Settings tab offer much:
In our environment we follow the aforementioned testing/QA/production workflow so having the Box Sync client update itself without allowing us to ensure its compatibility within our environment was a problem. Lacking any documentation from Box and on a hunch I took it upon myself to check out if there was any configuration information buried inside the Box Sync bundle.
Time to go spelunking
At first glance the app bundle contents seem pretty unassuming:
Nothing too interesting in Frameworks either, just Python and Growl. The bundled Python framework makes sense (though, what’s wrong with System Python?) since we know that the Box service, like Dropbox’s, is partly written in Python:
The Resources folder has a lot of PNG images used as icons for document types and the UI, as well as a number of .nib files so we’ll ignore those. We see some more signs of Box being written in Python:
Let’s check out the include
and lib
folders, familiar-looking names for anyone who has had to install a Python application that has Python modules as dependencies:
It appears that the include
folder contains just the pyconfig.h
header file, so we’ll look at the lib
folder which seems to have more contents:
The most interesting item here is the site-packages.zip
file which is another familiar name to those who have deployed Python applications before. OS X itself has a folder named site-packages
located inside /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7
. Inside are third party Python modules that can be installed through easy_install
or pip
and are meant to be available to all Python applications. Let’s see what’s inside, shall we? The unzipped site-packages
folder is over 20 MB in size, containing 51 subfolders and nearly 140 .pyo
files. The .pyo
files are Python optimized bytecode files, essentially just like the .pyc
files Python automatically creates when running a Python .py
program file. More about these in a bit as we dive into the contents of the folders next.
Further down the rabbit hole we go
Most of the folders contain commonly used Python modules one would expect to see in an app of Box Sync’s magnitude: a number of PyObjc modules to call Apple frameworks, XML, SSL, JSON, SQLite, NTLM modules and various other modules that don’t seem too interesting. What does look promising are the box
and boxsdk
folders:
Looking at the contents of the box
folder our eye is drawn to the conf
subfolder since we’re still hunting for clues about somehow configuring the application a little better. At this point we’ll look at the Python optimized bytecode filetype again that we’ve determined all the .pyo
files have. A quick Google search of “Python pyo files” tells us that they are trivial to revert back to regular Python code using the uncompyle2 tool which is available through either easy_install
or pip
. Once installed we run uncompyle2
against the contents of the entire site-packages
folder using the -r
switch to recursively process it. If there’s other places where interesting configuration options may be lurking, we’re bound to find them.
$ easy_install uncompyle2 $ uncompyle2 -o /tmp/site-packages-decomp -r -p 8 /Applications/Box Sync.app/Contents/Resources/lib/site-packages # 2015.02.07 01:36:54 EST decompiled 1 files: 1 okay, 0 failed, 0 verify failed decompiled 1 files: 1 okay, 0 failed, 0 verify failed decompiled 1 files: 1 okay, 0 failed, 0 verify failed decompiled 1 files: 1 okay, 0 failed, 0 verify failed decompiled 1 files: 1 okay, 0 failed, 0 verify failed decompiled 1 files: 1 okay, 0 failed, 0 verify failed <snip>
After the processing is done we check out the contents of /tmp/site-packages-decomp
and see that uncompyle2
produced files with a .pyo_dis
extension, which are just plain .py
files at this point. We could rename them all, but any text editor will read them now so we won’t bother.
Deep dive for plists
Opening up the /tmp/site-packages-decomp
folder in an app like Textmate or BBEdit is going to be the easiest way to search the entire codebase for anything related to preferences, like a plist file. To start off we’ll use Textmate 2 to search for any files containing the text “plist”:
That wasn’t too hard, was it? It looks like the file at site-packages/box/conf/base.pyo_dis
has references to a file named /Library/Preferences/com.box.sync.plist
:
conf.set(u'preferences.mac_plist_file.path', u'/Library/Preferences/com.box.sync.plist')
Eureka! This file is normally not to be found on systems with Box Sync installed and configured for the user, so this is a great start. Some more searching reveals the _overridable_settings
list in configuration.py
which contains a key named auto_update.enabled
! Exactly the kind of setting we were looking for. Its inclusion in a list of settings named “overridable settings” further increases our confidence. To test that this setting actually works we start by writing a new /Library/Preferences/com.box.sync.plist
file using defaults
like so:
$ sudo defaults write /Library/Preferences/com.box.sync.plist auto_update.enabled -bool False
And indeed, when tested by installing an older version of Box Sync with the /Library/Preferences/com.box.sync.plist
preference file in place with the auto_update.enabled
key set to False
the application indeed no longer attempts to auto-update. Mission accomplished, go home? Well… almost.
Things get kinda real at this point.
Once I started to scroll around a bit more in the base.py
and auto_update_release.pyo
files and saw what else was in it, my reaction can be summarized as follows:
As it turns out, the development team at Box embedded a lot of rather sensitive information in the files belonging to the conf
module. A quick scan reveals sensitive-looking key/value pairs such as:
app.remote_control_port app.remote_control_auth_key api_key #(Mac/Windows specific) client_secret #(Mac/Windows specific) upload_only_auth_token_for_log_folder auto_update.internalqa_user_ids mac_api_key win_api_key mac_client_secret win_client_secret au_password v1_internal_admin_login_url s3_access_key s3_secret_key jenkins_url
This is probably not a good thing. Since bots exist that scan Github and other public version control services for unintentionally checked in API keys and secrets, Box probably didn’t mean to expose all this information in the Box Sync application. To be clear, I did not try to use any of the information I found to gain access to any Box systems. I am also not publishing the full source code or complete key/value pairs, this is left up to the inquisitive reader to pursue. In early January, after realizing what I had found, I reported the issue to the Box Security team and after receiving acknowledgment of the severity of the issue I was asked to delay disclosure to give the Box development team time to develop and ship a fix. On February 6th I was notified that an updated version 4.0.6035 had been released which is supposed to resolve the issue. Since the update is now available I am publishing my findings in order to give a heads up to fellow Mac Admins and anyone else who uses or deploys Box Sync to ensure that the 4.0.6035 update is applied ASAP. There is no way of knowing who else has been aware of the exposed information before me and whether or not it may have been used to access Box customer data. This is especially important in environments that use a managed software update workflow which may be holding back automatic updates until specific action is taken by an admin.
Conclusion
I hope this information will be useful to Mac Admins and individual Mac users alike and again stress that every Box Sync user make sure that their installed version is at version 4.0.6035 or above.