Application Playpen

Application Playpen

Overview


We have developed a methodology of managing enterprise and/or shared environment unfriendly applications that has evolved over the years at the Marriott Library or other locations on campus that we support. We affectionately call it the  “Crappy App” model which we use sanitize applications with exceptional requirements.

These requirements include:

  • Application has insecure permissions
  • Application has hardcoded variables (usernames, paths, etc.)
  • Application tries to update with every launch
  • Application requires access to locations we’d prefer they not have access
  • Application requires to be launched by a specific user or group
  • Application requires additional configuration pre or post launch

Originally, we developed this methodology to better secure the Classic environment running in our shared environments. Classic implemented Mac OS 9 running as an application within earlier versions of Mac OS X, allowing you to use your older “Classic” applications. The Classic environment had security & state issues and some Classic applications may not function properly from a System Folder that can’t be written, provides a good security measure to prevent startup from Mac OS 9 and ensures that each user starts with a pristine System Folder. To resolve the issues but not hinder the needed functionality we developed a workaround that included placing the Classic System Folder in a read-only disk image, then hack the “Classic Startup” application to mount the image as read-write with a shadow file saved during the Mac OS X user session.

For example, the following command would mount the Classic image with a shadow file.

hdid /Classic.dmg -shadow ∼/Library/Management

This file can then be mounted, and used, but will not save any information once the user is logged out. Any application can take advantage of this method, allowing for more secure and easier to cleanup environments.

For example, the AppleScripts below will run VirtualPC with a ’shadow’ file…

Mike Bombich (aka Carbon Copy Cloner fame) developed a GUI application version that helped simplify and automate the steps into his “Shadow Classic” application. This application implements a shell script that will mount your read-only Classic disk image with a shadow file so that it appears to users and applications as read-write.  This allows users and applications to make changes to the System Folder or applications on the disk image at will.  When the next user logs in and starts Classic, the disk image is mounted again with a fresh shadow file, having none of the changes imposed by the last user.

For example, this is shell script included with the ShadowClassic application…

ShadowClassic implements the equivalent commands…

Then it replaces the Classic Startup executable with a shell script that mounts your Classic image with a shadow file and launches the “Real Classic Startup” application.

Why Distribute Crappy Apps?
This methodology has been extended and implemented for multiple “crappy applications”. Since we are a higher education institution, in a large decentralized research university, our department is in a campus central location, and the campus main library; we tried to meet the computing and software needs for campus which is often defined by multiple departments, colleges and groups with different and varying needs and goals.  With that in mind, we have try to address these needs by sanitizing software that other environments like corporations could simply say NO to distributing and supporting in their fleet. But, as in our environment we try to make a best effort in sanitizing the “crappy app” to safely distribute.

We would strongly recommend to document and give the “crappy app” developer feedback on why their application is enterprise unfriendly and that unless its changed you will transition to another application to provide needed functionality and try to get others in the Mac Admins community to do the same (i.e., carrot). In the past, we maintained a “crappy app” shame page, but we decided that this wasn’t a priority for our group or wasn’t the most effective strategy in motivating a company to change their development methodologies and practices (i.e., stick).

Carrot or Stick | Pace

Mac’s Are Secure/Resilient?
Other arguments against taking a little extra time and effort to sanitize needed “crappy apps” is that Mac are secure and one bad application won’t break the entire Apple system. But, with presentations from Apple knowledgeable persons like Patrick Wardle, who recently presented at MacTECH about the “Protecting the Garden of Eden“, Mac systems are being more and more targeted and are having increasing Common Vulnerabilities and Exposures (CVE) or publicly known cybersecurity vulnerabilities. And since Apple has implemented System Integrity Protection (SIP) in OS X El Capitan, which comprises a number of mechanisms that are enforced by the kernel including protection of system-owned files and directories against modifications. And with newer macOS versions Apple has increased scope of these mechanisms to improve privacy, security, resilience and stability of the system. Seems we should try to follow, and try to implement the principle of least privilege to justify taking a little extra effort to sanitizing “crappy applications” in our environment.

Related image


Principle of Least Privilege

The principle of least privilege requires that in a particular abstraction layer of a computing environment, every module like a process, a user, or a program must be able to access only the information and resources that are necessary for its legitimate purpose and are essential to perform its intended function. This principle is widely recognized as an important design consideration in enhancing the protection of data and functionality from faults (fault tolerance) and malicious behavior (system security).

Benefits of the principle include:

  • Condensed Attack Surface
    Limiting privileges for people, processes, and applications means the pathways and ingresses for exploit are also diminished.
  • Reduced Malware Infection and Propagation
    Least privilege helps dramatically reduce malware infection and propagation, as the malware should be denied the ability to elevate processes that allow it to install or execute.
  • Improved Operational Performance
    When it comes to applications and systems, restricting privileges to the minimal range of processes to perform an authorized activity reduces the chance of incompatibility issues cropping up between other applications or systems, and helps reduce the risk of downtime.
  • Easier to Achieve and Prove Compliance
    By constraining the activities that can possibly be performed, least privilege enforcement helps create a less complex, and thus, a more audit-friendly, environment.

The following Apple Developer documentation on “Elevating Privileges Safely” covers the basics of the Principle of Least Privilege.

Details


The basic process for creating a Application Playpen launcher for a “crappy application” is as follows:
  1. Start with the Application Playpen launcher template
  2. Create the read-only image of the “crappy application”
  3. Place the image into the Application Playpen launcher application
  4. Update the Application Playpen launcher main.scpt AppleScript file
  5. Update the Application Playpen launcher icons files to match “crappy application”
  6. Update the Application Playpen launcher Info.plist to match “crappy application”
  7. Test, test and test again

Currently, we use the following AppleScript template to build the Application Playpen launcher.

Application Playpen Launcher Template
All of the logic for launching and managing configuration is handled in the /Contents/Resources/Scripts/main.scpt file.

Create the Read-only Image of the “Crappy Application”
While I’m sure all of this can be done in Disk Utility, we will use the hdiutil command in the terminal to ensure everything gets set properly. The hdiutil tool uses the DiskImages framework to manipulate disk images. We’ll create the image in the ~/Library/Application Support/[CRAPPY APPLICATION] directory, which will allow the shadow file to be saved in each user’s home folder and keep or removed it based on the system’s configuration type.

For example, for student systems, we would disregard any user home folder modifications including the created shadow file on student logout. For staff, the home folder contents including the shadow file are retained on staff logout, so, modifications to a “crappy app” environment could be retained if beneficial to the staff.

Change Directory to tmp

Create Crappy App Image File
To create a read/write image to install the “crappy application”, enter the following commands:

  • -size
    This option allows you to specify a image size of 5 GB
  • -fs
    This option allows you to specify the filesystem of the image such as HFS+, HFS+J (JHFS+), HFSX, JHFS+X, APFS, FAT32, ExFAT, or UDF.
  • -type
    This option is particular to create and is used to specify the format of empty read/write images. UDIF is the default type, but SPARSE creates a UDSP, a read/write single-file image which expands as is is filled with data.
  • -volname
    The newly-created filesystem will be named [CRAPPY APP]

For example…

Mount Crappy App Image Volume
Next, to mount the “crappy application” image volume to begin installation process, enter the following commands:

At this point, you should have the volume mounted to the default location: /Volumes/CrappyApp

And see it mounted in Finder on the Desktop:

 

Install Application to Image
Now run the “crappy app” installer package, and when presented with a choice of “Where should this application be installed to?”, specify the “CrappyApp” volume. Some installers ask for a specific directory or if the “crappy app” installer doesn’t support this and it is a application package, you could simply copy it over to the mounted disk. An a application package is a file system directory that is normally displayed to the user by the Finder as if it were a single file or application.

Convert Read/Write Image to Read-Only
We would recommend opening a Finder window and checking that everything seems installed properly in the mounted image. Then, go back to the terminal to finalize our image creation process by running the following commands…

The above commands unmount or disconnect (i.e., detach ) the read/write image from the system, then converts the read/write image into a UDIF read-only image (i.e., UDRO )

Customize Launcher & Save As Application
Next, customize your the above AppleScript template and save it as an application.
Move Image Into Launcher Application
And you should have a read-only disk image with the .dmg file extension containing your application. Put the disk image into the correct location within the application package. Within the launcher bundle (which is named “Crappy App.app” for example), put the image into Contents/Resources/. This is where the launch script assumes the image will be located.
If you’ve never modified the insides of an application before, you’ll have to find the application in Finder and right-click it, then select “Show Package Contents” to get inside.
Or just do all the moving in the terminal, for example…

From inside the wrapper application, navigate to Contents/Resources/Scripts and open the main.scpt file in AppleScript Editor. We’ve tried to abstract as much of the code as possible, so all you should really need to change is the variable at the top named appName and the application-specific binary launcher location. Its given value is <TEMPLATE> . Change this value to be the name of your application.

For example, change…

To…

The script assumes that you’ve named everything identically, so the image file is CrappyApp.dmg and it mounts to /Volumes/CrappyApp , and the real application will be at /Volumes/CrappyApp/Applications/CrappyApp.app . This might not necessarily be true and so you will need to change the appPath variable accordingly.

For example…

Update Icon Image
To make the launcher application appear as the real application to Spotlight and to convince our users that it’s the regular application, we’ll include the original application’s icons file. Mount the disk image we made and navigate in Finder to the application’s .app bundle within the mounted volume. Inside of the bundle, look in the Contents/Resources/ directory for a file ending in ‘ .icns ‘. This is an Apple icons file, note there may be more than one; so make sure you use the correct main application icon. Copy this .icns file to our launcher application and rename it with the application’s name (i.e., [CrappyApp].icns ). Then replace the applet.icns file with the your application icon file.

 

Property List Customizations
Inside the launcher application’s top directory, Contents , there is a property list file named Info.plist . This file contains the information describing how the launcher application presents itself to the user, such as the name, version number, and icons to display.

You’ll have to use your own discretion here, but the fields that you will probably need to change are:
  • CFBundleIconFile – the .icns file (“CrappyApp”)
  • CFBundleIdentifier – the unique identifier of our bundle (“my.domain.CrappyAppLauncher”)
  • CFBundleName – the name of the application (“CrappyApp”)
  • CFBundleShortVersionString – the version for the application. Simply copy the value from the regular application, such as “4R7 P3” or “1.58.27”, etc.

Test
No matter what, you should always double- and triple-check your compiled playpen application before considering pushing it to your enterprises distribution cycle (i.e., development, testing, production).

Helper Script Elevated Privileges
Some “crappy app” implementations require administrative privileges to make modifications to effective use this methodology like for example with Xcode we add a user explicitly using Xcode to _Developer group.  To aid in the setup, we created python script to help administrators manage their sudoers file to allow scripts to run with elevated privileges but allow standard users to unknowingly use these scripts called “Sudoers Manager” and made it available to the community.

There is a file located at /etc/sudoers which contains a list of rules for privilege escalation. This file allows users to run commands as other users. Most frequently, this file is used to grant super-user (“root”) privileges to non-root users. The administration of the sudoers file is intricate, and it’s important that you don’t make mistake or else you risk losing all administrative access on the given computer (unless your root account has a password that you know). Our python script simplifies & automates the process of modifying the sudoers file for your environment on a fleet of systems.

Drop-In Rules Directory
Note, that you can use the sudoers #includedir directive and then distribute sudoers rule files to /etc/sudoers.d directory as part of installation package, script or other methods. Internally, we have updated our “Sudoers Manager” to support sudoers.d with validation and automatically creating the rule files, but currently haven’t pushed the update to our public GitHub repository.

For example, you need to edit the /etc/sudoers file to allow support of the #includedir directive:

Be aware that sudo will skip file names that end in ~' or contain a .’ character to avoid causing problems with editor or other temporary/backup files.

Validating Rules File
You can validate your sudoers rules file, before distributing or packing it by using the following command:

/usr/sbin/visudo -csf /path/to/your/sudoers_rules_file

We would recommend that these rule files should be owned by root and with permissions 0440. Then the root user can read the file but not write to it!

For example…

Sudo Make Me a Sandwich Robot, Inspired By A XKCD Comic

Mac Support
Note, some older versions of macOS might not fully support sudoers.d drop-in files. You can try manually add the #includedir directive and /etc/sudoers.d directory and see if it works properly. The above command will show you all the files sudo is parsing and show potential issues.

Example
We use sudoers.d with rules files with or custom “Tablet Driver Installer” application, which allows standard users (students, staff & faculty) take multiple versions of tablets to a system and install the correct version based on the tablet make and model.

For example, here is the python script we use with our custom “Table Driver Installer” application to install drivers with elevated permissions using sudoers and sudoers.d with rules file.

Other Workarounds
Not all “crappy apps” can’t be solved using this application playpen methodology and we implement other solutions like using a location of the file system to validate & restore the pristine state of “crappy apps” location(s) at logout, startup, etc.

Examples


Here are some examples of applications that we have implemented the “crappy apps” model and use in our environment.

Xcode
Xcode is Apple’s development environment. It’s used to develop applications on Macs, iOS devices like iPhones and the Apple Watch. However, Xcode requires users to have _Developer group privileges to allow the debugger and emulators to work correctly. We give our users only the least privileges they need to get their work done and we take great pains to secure our environment. We felt giving every user _Developer rights was unnecessary and something solve using the “crappy app” methodology.

We use the following shell script named AddUIDToDevGroup.sh that adds the current user launching our Xcode “crappy app” application, then adds the user to the _Developer group and then launches the “real Xcode application. We then could remove the user from the group at user logout and/or startup.

NVivo

With NVivo we originally did activation as part of system maintenance, but with the amount of new & temporary systems installed & number of times maintenance was run our sales representative from QSR International, the developers of NVivo, thought that the software was very popular at the University of Utah, maybe the most popular location in the world ;-). We provided them with KeyServer statistics &  logs with concurrent usage and explained our maintenance activation and shared our scripts, but they didn’t completely believe us 🙁

So, we decided to implement NVivo using our “crappy app” methodology where activation would only happen when a user explicitly launches NVivo.

For example, here is NVivo activation python script we use the the application playpen launcher:

The user uses Finder or Spotlight and gets our “application playpen” NVivo, which mounts the image, modifies the NVivo activation xml file and then launches the “real” NVivo.

To use this script in your environment, you need to change the [ACTIVATION CODE] with your NVivo activation code.

Unity
The challenge with Unity is that it continuously updates on application launch and we wanted to support multiple versions like standard & pro on the same system or older versions of the software.

With Unity Pro we used the following python script to automatically setup the serialization in a classroom environment using the “crappy app” methodology:

If you want to use this Unity Pro serialization script, change [SERIAL NUMBER] , [USERNAME] & [USER PASSWORD] will need to be changed for your environment.

Future


In the future, we will be moving this project to Python and Tkinter to provide user interface along with a command line equivalent. There will be a “creator” script/application that will automate the creation of the “launcher” script/application and allow including a pre or post scripts or commands that could be executed before or after launch of the “real” crappy application. We are also debating based on frequency of updates, demands and number of “crappy applications” we need to maintain, creating an AutoPkg processor to automatically build the “crappy application” launchers. The project is in development and if you are interested, please give use feedback, as this might help change our priority or motivate us to focus on this project.

No Comments

Leave a Reply