Architecting applications for personal computers is getting to a technical level similar to that of smartphones, and that requires changes in how applications are signed and deployed. For mobile app developers, distributing apps via the App Store has been a game-changing solution to problems like monetization, marketing, distribution, and update management. Both the Windows and Mac app stores now require apps to be cryptographically signed, and they follow certain sandboxing rules for security. iOS and Android apps are highly restricted when it comes to interacting with the system and other apps, and for good reason.

Locking down environments at the app level–often called sandboxingis designed to protect the OS and other apps from malevolence. Each app on iOS has its own self-contained, bundled file system that is separate from the OS and other installed apps. Sandboxing also requires executables to be signed with a valid developer certificate, making them more tamper proof.

The “Sandboxed World” is coming. Let’s explore some of the implications and alternatives to current best practices.

What does this mean for PC developers?

Both Apple and Microsoft offer app stores for their PC platforms, and running in a sandboxed mode is optional–for now. For mobile developers targeting iOS and Android, sandboxing is mandatory. This is because sandboxing apps is safer, so developers who choose not to embrace sandboxing may find they lose users, depending on the security configuration of their PCs.

Screen Shot 2015-03-17 at 4.34.14 PM

On a Mac, for example, navigating to System Preferences / Security & Privacy / General, a user can find options about which apps to trust. Is the executable signed?  If so, is it signed by a developer who is in the trust chain of the platform provider? Has the app been vetted by the App Store? On Windows 8, users see “Windows Store Apps” (formerly Metro Apps), which similarly are very well sandboxed and signed. Apps can also be restricted by what types of privileges they require, giving the user ultimate granular control of what types of apps can do which functions.

 

Implications of Sandboxing for Developers

Developing a sandbox app requires a shift in traditional PC approaches. An example of the shift in application life cycle that comes to mind is the waning need for installers. Since, on OSX for example, all application files are self-contained, the entire bundle can be dropped into the Applications folder or just deleted. The footprint is then cleaner as well, leaving no extraneous files that could be manipulated outside control of the app. One might ask: “if installers are no longer necessary, then how will I ask the user for escalated privileges?” There is a legitimate set of software which does need to run with escalated privileges, if the software needs to listen on a low port number, for example.

It’s not uncommon to come across mobile apps that require more privileges beyond those available to standard developers. Let’s look at Junos Pulse for iOS as an example. Pulse implements its own SSL VPN–separate from the native iOS system VPN. When first developing Pulse, Juniper needed special approval and joined Apple’s undocumented VPN API. A handful of other developers are doing this as well. In a sandboxed world, the platform providers hold the keys to special app privileges. On a PC, a sandboxed app may also ask the user for special permission using an API, but it is the user who authenticates the app (usually type in an admin password). Let’s take a look at a few of these APIs on Mac OS X.

 

Mac OSX APIs for Escalating Privilege

API: SMJobBless

The preferred method of managing privilege escalation on Mac OS X. There are many other APIs in the framework that must be used in conjunction with SMJobBless.

API: AuthorizationExecuteWithPrivileges

This API is deprecated. Once used, setuid() can be used to make the process a root process.

API: do shell script “scriptname” with administrator privileges

This is an AppleScript mechanism to run a shell script with administrator privileges.

The new preferred paradigm stays in line with the “Principle of least privilege.”  Instead of forcing the whole app to run with elevated privilege, “helpers” can do the privileged operations. Because the operation is short-lived, it is less likely that it could be exploited.

Let’s take a look at the SMJobBless way of doing things while achieving the following goals of:

  1. Preserving the ability to drag-install the application.
  2. Operating under the principle of least privilege by isolating privileged code in a separate process instead of having the entire application running with elevated privileges.
  3. Avoiding the use of setuid binaries.
  4. Requiring the user to authorize the privileged helper tool only the first time it’s used.
  5. Ensuring that the tool hasn’t been replaced by another potentially malicious tool.
  6. Ensuring that the tool hasn’t been co-opted by a different potentially malicious application.

* (From SMJobBless project Readme.txt https://developer.apple.com/library/mac/samplecode/SMJobBless/Introduction/Intro.html)

Within this project we have the actual app and we have the helper.  The helper has two corresponding plist files which would be used by launchd for execution and the traditional Info.plist.

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">

<plist version="1.0">
    <dict>
        <key>Label</key>
        <string>com.apple.bsd.SMJobBlessHelper</string>
    </dict>
</plist>

The label here “com.apple.bsd.SMJobBlessHelper” will be important later.  Consider the code below (from the project)

- (BOOL)blessHelperWithLabel:(NSString *)label error:(NSError **)errorPtr;

{
    BOOL result = NO;
    NSError * error = nil;
    AuthorizationItem authItem = { kSMRightBlessPrivilegedHelper, 0, NULL, 0 };
    AuthorizationRights authRights = { 1, &authItem };
    AuthorizationFlags flags = kAuthorizationFlagDefaults |
    kAuthorizationFlagInteractionAllowed |
    kAuthorizationFlagPreAuthorize |
    kAuthorizationFlagExtendRights;

    /* Obtain the right to install our privileged helper tool (kSMRightBlessPrivilegedHelper). */
    OSStatus status = AuthorizationCopyRights(self->_authRef, &authRights, kAuthorizationEmptyEnvironment, flags, NULL);

    if (status != errAuthorizationSuccess) {
        error = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil];
    } else {
        CFErrorRef  cfError;

    /* This does all the work of verifying the helper tool against the application
    * and vice-versa. Once verification has passed, the embedded launchd.plist
    * is extracted and placed in /Library/LaunchDaemons and then loaded. The
    * executable is placed in /Library/PrivilegedHelperTools.
    */
    result = (BOOL) SMJobBless(kSMDomainSystemLaunchd, (CFStringRef)label, self->_authRef, &cfError);
    if (!result) {
        error = CFBridgingRelease(cfError);
    }
}

if ( ! result && (errorPtr != NULL) ) {
    assert(error != nil);
    *errorPtr = error;
}
return result;

The label passed in here is the string from the plist above.  The _authRef member is created earlier upon launching when creating the “AuthorizationRef” object:

OSStatus status = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &self->_authRef);

This object describes the types of rights and behaviors we wish to bestow upon the helper.  Decisions to request authorization from the user, if it can be pre-authorized etc can be set here. HINT: There are notes about the flags in the Authorization.h

Once you have your AuthorizationRef object set up, it’s now time to call SMJobBless() and the helper will get called automatically by launchd after the launchd plist is placed under Library/LaunchDaemons.

In order for this to work both must be signed with an appropriate developer certificate obtained from developer.apple.com.

 

It’s a Mad Mobile World

The vast majority of app developers should not need to worry about such maneuvers. But those who do can enjoy the best of both worlds—sandboxing and privilege. Historically, software vendors needing even tighter OS integration—when installing a kernel module for example—would need platform vendor certification. The platform vendors often have formal third-party programs for this type of integration. It’s a sure bet that, moving forward, PC app development will become more restrictive to mitigate the increasing threat of malware.

This post is categorized in: