 Andy Grant here to talk to us a little bit about, uh, Mac OS packaging. Thank you. Awesome, thank you, yeah. So I'm gonna talk about the packages used to install software on Mac systems on Apple software laptops. First, I'm gonna start a little bit about myself. I've been doing professional security for 11 years focusing on application security. I've been doing security as a hobby for 20 plus years. I came to DEF CON 9 as my first DEF CON. Uh, I went up through self-taught ranks when I was in my early teens, got a computer science degree from Stanford University focusing on computer security. Went on to join the com- the security consulting group, ISAC partners. I was acquired by NCC group and continued to do that to today. I got started just doing the regular pen tests, looking at, uh, applications, finding the vulnerabilities, moved my way up the ranks to become, um, uh, the leader of the San Francisco team, joined the management, did that for five years, ran a team of 30 people, spent most of my time running that team of 30 people, trying to find an excuse to do the projects my team was supposed to be doing. So I gave up the management stuff and I'm back doing the technical work and here presenting today. I, thank you. Uh, I'm probably best known though by my alias of Dana Volmer's husband and, um, and you can find out more about me and my time off to support her career online. So we're going to talk about what led me to looking at packages and installers, then open up the packages, look inside, uh, and then see what can go wrong in, uh, with these installations. So first, I've got trust issues. X-Wix got me into computer security at the start, digging into what was going on in my laptop. I wanted to better understand what was happening. You have these pop-ups sometimes when you're installing software that says, this package is going to run a program, do you want to continue? And then you don't get to know what that program is or what got ran, just, it's going to run something. Plus, I'm lucky enough that I get paid to do this, as I was saying, and sometimes the client pays you to look at their application and their application doesn't work. So really all you have to go on is the installer and the process and then you kind of have to give them their money's worth out of just that working environment. So let's look inside what these packages are. So their technical term, their full name is Mac OS X installer flat packages. They have a .pkg extension. There's not a whole lot of documentation provided by Apple on them, uh, but you can find some reverse engineered unofficial documentation, but it's kind of out of date and, um, and incomplete. Uh, the flat package aspect of this is that it's a single file. It's actually an extensible archiver's arm. And in pre-10.5 OS X, these used to be bundles, uh, bundle packages, and so those were more like directories like your .app package, uh, app bundles. There's some helpful tools. One even comes pre-installed on, uh, Mac OS called package util. This allows you to inspect, uh, the packages installed on your system, inspect a specific package and go through and open, open them up, which is what we're going to get into. There's a nifty, uh, third party, uh, package out there that specifically is designed to look at the security aspects of these packages. And that's called suspicious package. It will highlight the code signing signature. It'll, it'll let you look at the some of the files that gets run and will highlight some, um, nuances of the application that might raise a red flag if it might be a malware installation. So let's, let's look inside. What's inside these? The easiest way to do it is to use your pre-installed package util, give it the expand command and then give it the package and the output directory and it'll expand everything out there. But we don't want the easy way. We want to do it the hacker way. We got trust issues. We don't trust what package util is doing. We want to make our own directory. We understand that command. We go into that directory because the, uh, ways are to extract these files works. It just, um, outputs right into the current working directory. And so now we're going to go through and extract the package files. After you've extracted them, this is sort of the typical structure you find inside. You have a distribution XML file. You have a resources directory and then you have one or more package directories. These package directories contain a bill of materials, a package info, another plain text XML file, and then two compressed archives, uh, payload and scripts. So the distribution file, this is the customization of the installer window. It's a, it gives it the title, the welcome text, if there's a license, if there's, um, a read me, the background logo that, that is displayed and sort of, uh, determines whether you restart or shut down or don't need to do anything after the installation is complete. These can also include JavaScript, specifically a subset called installer.js. And this is supposed to be what triggers that pop up of some, uh, code is going to run to check to see if your system's compatible. It's in the compatibility check. You have the package info. This is more information about the individual packages that are just installed with that distribution. It has the specific requirements of that package. The install location where that payloads, uh, that package payload will be extracted to. And then it will also include any paths to the scripts that will be run. And then you have the bill of materials. This is, um, a special file that lists out all the files that will be installed, updated, or removed during the installation process. And it includes their file permissions, the owner and group that they will have, the size of the files and creation time and some other, uh, file metadata. Now we have these, um, compressed archives. These archives are actually CPIO archives that have been GZIP compressed. The payload includes all those files that are going to be installed that are listed in the, um, bill of materials. And the installation process here is actually just extracting this archive into the install location specified in the package info. You have the scripts, um, if there's any scripts to be run before afterwards. Same type of archive, CPIO archive. You have pre-installation and post-installation scripts. But really, this can contain any executable file that has an appropriate shebang at the first line. So it's typically bash Python Perl. Uh, this gets extracted, um, during the by the installer into a random directory and gets executed from that location. So to unpackage those packages, those archives within, within it, you, um, you can go, like I said, it's a GZIP CPIO file. And so you can cap this, the archive into the decompression, into the archive extraction. Or CPIO actually natively detects that Xbin GZIP compressed. And so you can just put it right into the CPIO and say it's input and, um, and away you go. It'll dump right into the current directory, all the contents of that. If you did it, the easy way to begin with the expand command actually goes ahead and extracts this, uh, archive already. And instead of having the scripts, um, object to be a, uh, archive, it is already a directory with the contents inside of it. You do the same thing as scripts for payload. You go through the CPIO command, um, sometimes in going through that payload and extracting the files, it has further packages in it. So you just recurse through if you want to find everything that's going to happen during the course of your install. Unlike with scripts though, the package util does not auto expand this. And you do have to go through the manual process of extracting the payload files if you want to see what's going to be installed on the system. So let's walk through what happens when you actually launch the installer with one of these packages. The, you start with the distribution file, um, they were working through sort of more the, the code execution flow. So it checks to see is there any installer check? If so, it looks for the JavaScript that's going to be there. That JavaScript is defined within the XML file between script tags and it goes through and executes that JavaScript. Then if the package info, um, said there was any pre-installation scripts, it goes and runs that pre-installation script. Then you install the files. You extract the payload into an install location. And then you do the post-installation scripts if there was any specified in the package info. So now we're going to get into sort of the security concerns that can happen during the installation that, um, that can occur. You have the scripts in the payload, which is where most of this is happening. In the scripts, you're going to look at the pre-installation, the post-installation. These can also include helper scripts and other files. So you'll want to look at what's going on there. They're plain text. Like I was saying, bash Python Perl, pretty easy to audit and understand what's going on and look for common mistakes. Within the payload, you also have, um, you can also have more scripts. You've, I've seen an uninstallation scripts that are easy to audit. Some helper scripts for debugging or logging or error reporting that gets installed. And then you also have your normal native apps that get installed, the b, actual application binary, the kernel modules, the libraries. And if you want to go into it, you can go and look at for native application flaws through reverse engineering, fire up hopper. So the types of issues I was seeing when looking at these packages largely amount to time of check, time of use, except they weren't doing any checks. They're, they're operating within the temp directory, which is world writable by anybody. And, uh, they're doing reads out of it that are untrusted. They're doing writes into it that are untrusted or they're executing files in it without confirming that file is what they believe it should be. I've also seen the, um, some of these installers go through and set 777 permissions on what gets installed or what's get written into different locations. And that just allows everybody to mess with whatever you wrote there and it's no longer a trusted install. So now we're going to dig into the actual vulnerabilities I got to see while looking at this for the past couple months. So I've found a number of privilege escalation issues, um, did some symbolic link abuse, uh, and got some arbitrary code execution, which was fun. So the first one, we have this installation. We're going to go through the payload installs, uh, um, installer util binary. That's just a helper program for the installation to go through. And then the post install script actually calls that with sudo with super user powers and, um, and executes it. This is written to the temp directory. Temp directory is world writable. This is actually, um, the payload is installing as the current user, um, the way this installation was working. And then the post install is calling that user owned, uh, file with super user powers. So in this instance, I'm possibly an unprivileged user asking my IT administrator to install video conferencing software so I can join a meeting later that afternoon. So I would have audited this program, looked at, at this, seen this vulnerability and then written up a little script to run in the background a while loop say, while this file doesn't exist, do nothing. And then when it, when it does exist, remove that file and put in my payload, um, in, in its place. And then the post install is going to come around and execute that with root privileges. And I've just escalated from my unprivileged user to my IT administrators, uh, root powers over my laptop. Another package I saw, um, during the pre-installation it tries to do some cleanup in case it had previously run the installer. It deletes this, um, install, installation file in the temp directory. And then later on it writes to that and wants to make sure further installations unassociated with this install can also write to it. So it sets 777 permissions using sudo and then also makes the owner of it, um, the current console user. So in this attack, any user on the system, any process that can write to temp, the temp directory, which should be all of them, can attack the system administrator or whoever's install, installing the software. So you go ahead and you, you touch that file ahead of time so it exists. So then your Y loop can say while this file exists, wait and do nothing. And then once that file has been deleted during the pre-installation, go through and create a symbolic link to a directory that you want to gain right access to such as slash applications and link that to that file's name. Now when they're going through the post-installation, they'll try to write to this, it'll fail, things fail silently unless you're doing an explicit checking of failure states during these scripts. And then when you get to this sudo change permissions to 777, that's going to follow that symbolic link and make slash applications world writable. And then it'll also go through and have the, the happenstance of changing the ownership of applications to the current user. At this point we don't really care about that because it's world writable, we can drop whatever applications we want onto the system now. Another package was privilege escalation. This is not to current user to root. This is any user to the current installing user's privileges. So they go through, they, during the pre-installation in case it had run before, it deletes the 7-zip file, 7-zip archive binary in the temp directory. And then it goes through and tries to extract this 7-zip file that came with the payload and then execute that 7-zip file. This is all happening within slash temp. So pretty straightforward. Before this install was ever run, I just put my payload as that name. You notice none of this is sudo, this isn't running with root privileges. So they can't delete my file that's sitting there. So the RM fails, the overwrite from the unzip fails, but the execution happens. Because like I said, these fail silently inside the scripts. So I just went from just putting a file there on the system, the installer happily goes through and executes it as the current installing user and I've gained the privilege as them. Another example we have here is another symbolic link attack, helper script outside of the payload. So once you're running the application, this was for some debug reporting back to the developer. It tries to clean up some of the logging it was doing in the temp directory to capture that debug log. And so it does an RM-RF of this temp directory slash star and then it does remove the directory notably with a slash at the end of the path. So the attack here is before the scripts ever run, any user can go and write to that temp directory. I have a typo in my slides, I say slash var, I realize instead of slash temp. But in the payload it should be slash temp slash SDU. And the way the symbolic links work, that RM-RF with a slash star will follow the symbolic link and delete everything in the user's home directory in this example. And then the remove directory command with the slash at the end will follow that symbolic link and blow away their home directory also. So now you hear left with a symbolic link that points to nothing because everything's been deleted. Next we have a vulnerability that has in the package info it says we're going to extract the payload into slash temp, specifically this razor synapse place using root privileges we're running as the root user. So you don't even need sudo here, everything just runs as the super user. During the post installation we're going to change into that directory and then we're going to look for star dot PKGs and install them once again with root privileges. So this has been fixed by razor and so we're going to use this as our demo today going through everything I've talked about here. We're going to download the package, extract the files, audit the package, find this vulnerability, develop an exploit for it and then drop the payload and watch it take place. So here I go through and I download the package. Once it's on my system I'm going to go through the hacker way to create the directory, extract the contents of that package into the directory and then I'm going to go look at the file. So I'm looking at the distribution file first to see if there's any installer checks. They don't see any installer checks so I'm going to move on, I'm going to look at the package info to see what's going on. Here we have that it's extracting to the temp directory, it's installing as root and there's extra little tidbit there that it's going to ask to restart at the end. It also notes here that there is a post install script so let's go see what's happening in that post install script. We're going to create our, our, our collection directory so we don't clutter the current directory, extract the, the scripts into it and then we have all these extra files in here but we're interested in what it named, the post install script. So now this is the whole post install script, we're, we're reading it, we're really fast at finding vulnerabilities. Here's our vulnerability that, that we just looked at. So we're going to go through, we're going to, and now we're going to take advantage of this. Now that we know about this vulnerability we can become the malicious user. So Mallory is going to take over and she's going to go through and develop the, a malicious payload, a package that will be installed as part of this exploit. So we create our scripts directory, we create our pre-installation script, so we put in the shebang, we touch, we just touch a temp file and echo the current running user into it so we know what privilege this exploit runs at and then every good proof of concept pops calc and so we'll also pop calc as part of our proof of concept. Now we have to make that executable or else it doesn't run. Now we use package build to make up our package. We can give it identifier, this isn't really necessary, but it just shows another aspect that you can label and call what these are. Here I specify that there's no payload here, there's no files being extracted and so it doesn't try to look to create that payload archive. I script only package. I create the package, I create that directory because Razer hasn't been installed yet and I move the payload into that directory and now I'm done. Now I wait for Bob to come around and run the installer. Bob's going to do it right now. Bob's not actually an administrator on here so Alice is going to have to come and type in her admin password. It's going to continue through pop calc and then we go and look at the temp directory file to see that we just ran as the root user here. In my final minute I want to make some notes about what we just observed that there was some unexpected things happen when you do this no payload package that I just created there. When you install anything with a payload, the installer creates a receipt and you can look at your system of all the packages that have been installed by that identifier and then you can give the package util that identifier and look at all the files that were installed during that process. However, if no files are installed because there's no payload, there's no receipt that that package installer ever ran. So there's no appropriate system record that you could look up and audit to see that this ran. Also, if you get super fancy for minimal clicks and user interaction, you can actually have that installer check in the distribution XML file. That JavaScript can call system.run and execute any scripts that are inside that script file. So within the system check when it's like do you want to check if your system is compatible, it will actually execute script which can extract an zip file and copy those files around your system and that's a one-click install instead of all the multiple clicks you normally have to go through. And then for for extra fun you can then call killall installer and installer quits itself and the user is immediately back to its desktop. Some of these tips and tricks have been used by the people over at Paterian. They wrote an awesome blog post series, two parts, about bypassing application whitelisting specifically Google Santa to using the installer. The quick quick version of that is application whitelisting happens at the basically the process executing level and installer is whitelisted reasonably and all of this installer check JavaScript all the pre and post scripts run as part of that installer process and so they're all whitelisted also. I'll be stepping off to the stage as I think I ran a minute long and so I don't have time to take your questions right now but I'll be happy to talk to you here.