XcodeGhost: verify your Xcode

Posted by | September 28, 2015 | No Comments
XcodeGhost

Recently a malware issue for the iOS app store (which is a rarity in itself) called XcodeGhost made its appearances. I’m not going into the gory details, but it boils down to a malware injection through a patched version of Xcode. When building iOS apps with such an Xcode, the app binary is modified transparently, injecting malwareware into your app at runtime. Nothing is downloaded from the internet, the malware just gets compiled into your app.

There’s not a lot to do about this, except to make sure that you’re using a legit Xcode. You can do this by never-ever downloading a version of Xcode from a location other than Apple’s, which is either from the Mac App Store, or from http://developer.apple.com (I know this is easier said than done, saying this from my chair in the middle of super-connected Europe).

But, once you have an Xcode installed, it doesn’t hurt to verify it’s authenticity once in a while, especially if you use a build server to deliver your products.

In the communication Apple released about XcodeGhost, they mention a simple tool to verify your Xcode. Fire up the command line and enter:

spctl --assess --verbose /Applications/Xcode.app

The spctl command is a command that manages the security assessment policy subsystem of OSX, which is used to defince the system policy and code signing requirements.

If you get back a response which includes accepted (e.g. /Applications/Xcode.app: accepted source=Mac App Store or /Applications/Xcode.app: accepted source=Apple) you’re in the safe zone and Xcode is not compromised. If you get back something else, the chance exists that your Xcode is compromised. It doesn’t necessarily means that: if you accidentally edited a header file in the .app bundle, the assessment tool also notices this and will report an error. However, if you see a mention CoreServices passing by in the output of spctl, you’re probably going to have a problem. By the way, the command can take a while so don’t worry if it doesn’t pony up an answer right away.

In any case, if you get an error it cannot hurt do download a fresh copy to be safe. Verify the downloaded app again, to make sure you updated it correctly.

Jenkins

Now, you don’t want to be doing this manually on a regular basis, especially on a build server. At iCapps, we have more than one Xcode on the server in order to support older projects (or until they are upgraded to newer versions of Xcode). So what we did was create a small shell script which fires off the spctl command which takes an Xcode.app path as an argument we have and have that script run each morning to verify all our versions. The script returns with a faulty exit code if the spctl output doesn’t contain accepted, causing that job to fail. The failed job sends of an email to the development team so we get notified pretty quick in case something would go wrong.

Xcode

The script itself is pretty simple, like I said:

#!/bin/bash

echo "Validating '$1'. This can take a while."
OUTPUT=`spctl --assess --verbose $1 2>&1`

echo $OUTPUT

if [[ $OUTPUT =~ accepted ]]; then
    echo "'$1' validates just fine."
    exit 0
fi;

echo "'$1' does not validate."
exit 1

Should be pretty obvious. There’s one thing to point out: the spctl command outputs it’s assessment on stderr so we need to pipe that output to stdout so that the backtick invocation can grab it. You do this by adding 2>&1 to your command invocation (standard error = file number 2, standard output = file number 1). If you don’t do this, the script fails even though the command finds no error.

We added this script to a git repo, set up a jenkins job with that repo and had it run periodically:

Why use a repo and not install the script on the server directly? First of all it’s a lot easier to keep track of and in case it needs changing you can do the changes locally, try them out and push to the repo. The server is updated automatically at the next validation job run.

And that job, all it does is invoke the script:

Build

The parameter obviously changes for each Xcode install: just change the path to the Xcode.app you want to verify.

Like I said, we have this on a periodic schedule, on our case each morning:

Schedule

But you could schedule this however you wanted, of course.

Finally, set up a post build email notification so that you actually get a warning when something goes south:

Post-build actions

And that’s it. You’re a bit safe now in this cruel, cruel world. Not entirely safe: if somebody gains access to your server away and messes with you Xcodes they’ll probably find & disable these jobs too. But this is better than nothing at all.

The best part: if you Do Things Right, this should never bother you. 😉

Fastlane

And oh, the fabulous Fastlane toolchain by Felix Krause also provides a verify action that you can use in your Fastfiles, making sure that you verify the Xcode you’re going to use for that build is valid. The build will take longer of course, but it’s the price to pay for ensured security. So if you’re using Fastlane and want to make sure your builds are “safe of malware” add this action to your Fastfile.

Leave a Reply

Your email address will not be published.