Configure player

Close

WWDC Index does not host video files

If you have access to video files, you can configure a URL pattern to be used in a video player.

URL pattern

preview

Use any of these variables in your URL pattern, the pattern is stored in your browsers' local storage.

$id
ID of session: wwdc2008-340
$eventId
ID of event: wwdc2008
$eventContentId
ID of session without event part: 340
$eventShortId
Shortened ID of event: wwdc08
$year
Year of session: 2008
$extension
Extension of original filename: m4v
$filenameAlmostEvery
Filename from "(Almost) Every..." gist: [2008] [Session 340] Creating Se...

WWDC08 • Session 340

Creating Secure Applications for iPhone and Mac OS X

Essentials • 51:20

Learn how to protect your customers from emerging security threats by adopting security mechanisms and secure coding practices for Mac OS X and iPhone.

Speakers: David Remahl, Braden Thomas

Unlisted on Apple Developer site

Downloads from Apple

SD Video (623.8 MB)

Transcript

This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.

Good afternoon and welcome. I'm happy to see that all of you could make it to this session on how to create secure applications for iPhone and Mac OS X. My name is David Remahl and I'm a software security engineer at Apple. So let's get started. I'll start by talking about the context that we operate in, some of the motivation and background for security work. And then I'll go on to talk about the security mechanisms that exist on our platform. And for the second part of the talk, Braden Thomas will give you some concrete coding tips that you can apply to your applications.

So let's look at the security landscape. Well, we have three separate groups that I'll talk briefly about. We have the attackers, the hackers that want our platform to be insecure and they develop various attacks against it. One thing we've seen is that attacks, web-based attacks where files get downloaded to a user's system and cause the users to run malicious software have been on the increase. And this can happen even through trusted websites like CNN or whatever website you're visiting through advertising that happens to be malicious or compromised.

We've also been seeing a continued focus on fuzzing attacks and for those of you who didn't attend last year's talk, fuzzing attacks are where legitimate file types are fed with malicious software with corrupt data, purposefully corrupt data, which will cause your application to misbehave. And this is a common method for finding flaws in, for example, image codecs. And we've also seen attacks against local networks and the domain name system. And we'll talk about some methods for countering those attacks.

So, now I want to talk some about what Apple is doing to counter these issues. We've been working on adding protection to the compiler and to the system that apply to all applications on the system, thereby increasing the overall security. A technology we introduced in Leopard is called Quarantine, which protects users against downloaded files and warns them if they're about to execute something that could have unexpected side effects, such as a Trojan horse.

And we're also investing, continuing to invest in security frameworks like Keychain and FileVault and other user-level features. And finally, you, all of you out there who... are here to attend this presentation to learn about what you can do to increase the security of your applications. We believe that you should take advantage of the hardening technologies that we've developed.

And just... Often this means just toggling a switch and enabling some hardening options. We hope that you use our frameworks to secure your user data. And we hope that you test proactively, since the attackers will be using fuzzing techniques. And we hope that you should also be using the same techniques to find the bugs before you deploy your application.

It's important to know the platform you're developing for in order to produce secure products. So I'll start by going over the differences and similarities between the desktop security model and what we have on the mobile devices. So this diagram of desktop computer system, and I'll show you some of the trust boundaries that exist. Probably the most important and the most obvious one is the trust boundary to the network. We don't want attackers, remote attackers to be able to access your system. And we enforce this through secure services, firewalling, and things like that.

Another important security boundary that exists in the system is the separation between the regular users of the system and the operating system, the kernel and the slash system, for example. Since Mac OS X is inherently a multi-user system, we have strong boundaries between users. It's important to make sure that one user can't mess with files created and owned by another user. The strong Unix foundation makes sure that we have that security.

We also have some separation between applications, as I'm sure you're aware. We have virtual memory, protected memory. So processes are separated from each other. But in fact, if you look at the processes running as one particular user, they can often interfere with each other if they're truly malicious. They can install plugins and use various methods of getting into another process address space and cause harm to that application.

So that's something we don't protect against. There's also a very weak boundary between the system and the kernel. So let's compare this to what we have on OS X iPhone. We obviously have the same separation to the network and it's probably even more important since iPhones and iPod Touches, they move around a lot, get used on malicious networks like probably what we have in here today.

And we have the same separation between the processes running on the iPhone and the operating system. Since the iPhone is a single user system, most phones have a single individual using them. We don't have separations between various user-created users, but instead we have a separation between the user data and the applications run by the single user.

We've also hardened the separation between applications running on the phone. So the intent is for, if one application gets compromised, it shouldn't be able to compromise another application running on the same system. So if a malicious third party application would get installed on your system, it ideally shouldn't be able to compromise your mail program, for example.

The separation between the kernel and the operating system has also been hardened. So even if an attacker would be able to get root access to your system, he wouldn't necessarily be able to compromise the kernel. On the desktop, this is obviously possible since root can load kernel extensions and does get code to run within the kernel space.

You might notice from this image that the applications they actually need to get to the data. So for this purpose, we have services that negotiate this access. And that means that you should access the user data through APIs, and they will take care of fetching the data securely from disk.

So next, let's review some of the architectural hardening that we have on the phone and on Mac OS X. And there are some differences, and I'll go over those. One important hardening feature that was added to Leopard was the non-executable stack. And in case you're not aware what this means, it's a technique for making exploitation of buffer overflows more difficult. A common way of exploiting a stack buffer overflow is to redirect the flow of execution onto some code that you've placed on the stack. And thanks to this CPU feature, that attack will fail and the program will just crash.

On the phone and the x86-64 platforms, we also have a non-executable heap. This means that if you allocate memory anywhere using malloc, you will not be able to run code in that space. And this further increases the difficulty of exploiting a stack or heap of Roboflow. Another feature that we added to Leopard was library randomization. And all of the system frameworks are moving around in memory when you start your application.

And it's also opt-in, so you can make your application move around to random addresses in memory. And the intent of this is to make it more difficult for an attacker to find some particular piece of exploitable memory. And on the phone, we're not supporting library randomization at this point, but it's certainly something we're looking into. Thank you.

Code signing, if you've looked at the SDK and maybe joined the developer program, you know that code signing is an integral part of the iPhone. And the iPhone won't run a non-signed code. And we also support code signing on Mac OS X since Leopard. And I'll talk some more about that later. So yeah, on the phone you don't have an option but to sign it. And in the future, we're looking into how to use code signing better on the desktop or more completely.

Sandboxing, another Leopard technology, allows a sandbox to be applied to a process. And this sandbox limits the actions that a process can take beyond those that would normally be permitted by Unix. So certain system calls can be disallowed and you can limit access to files on a per-path basis, for example.

And on the phone, most of the applications are running in a sandbox. And this includes every third-party application. And I'll talk some about what this means to you developing for that platform. And I'm sure there will be other sessions on that as well. In Mac OS X, we've just been sandboxing certain services. And applications can currently not run in a sandbox on Mac OS X.

Finally, we've worked on reducing the number of set UID binaries. Set UID binaries are binaries with special privileges. They run as the user who owns them, which is most commonly root. And because the user who starts the application controls the environment, this is a very significant attack surface, which we've often seen exploited for local privilege escalation.

And on the iPhone, we have zero set UID binaries, and we're working hard on reducing the number on Mac OS X. And we hope that if your application uses a set UID binary, that you move to using launchD instead, because that gives you control over the environment instead of the user who happens to be starting here executable. So let's look at some of the technologies used specifically on the phone. Here we go.

It only runs signed code. And due to the non-executable stack and heap, code generation is prevented. And this makes it significantly harder for an attacker to move from finding an exploit to actually getting the system to execute arbitrary code. But you should always remember that attacks get better and if you have memory corruption in your program such as in Overflow, it's very likely to be exploitable in some manner. But these technologies significantly raise the threshold for attack.

The applications are shielded from each other, and the way this works is that the shared data is accessed through APIs. And we're extending this support. Currently, some frameworks directly access data on disk instead of going through a launchd service. But this might change in the future, and when the framework changes, your application will break if it tries to access the data directly without going through the API.

About the sandbox, Mail and Safari, two very full-featured applications on the phone, are running in a sandbox that's very, very similar to what your applications will be running in. And every third-party application runs in the same sandbox, and it's not possible to remove nor add restrictions to that sandbox. And you should think about the application container in which your application lives as your home directory. It has the same subdirectories like documents and library, and that's where you should store your data.

The approved locations for writing specifically are temp inside of the application container, slash library, and slash documents. And as I mentioned, some other parts of the file system may be accessible. The sandbox may allow you access, but the sandbox might get tighter in the future and your application would break in that case.

Keychain is a framework that many of you are familiar with from Mac OS X. And it exists on the phone, but it's somewhat different due to the single-user nature of the iPhone and iPod Touch. It's automatically unlocked when the system starts, and that means you don't have to enter your password.

You might ask, what's the point of encrypting it if the key is on the device and it's automatically unlocked when it starts? And one of the reasons that this is a good idea is that backups will remain. So if someone steals a backup of a phone, he won't have access to the data.

We've also, the key that's used is unique to each device and stored on a chip. So it's pretty difficult for an attacker to extract this key without completely compromising a phone. If your application stores some data in the keychain, you can rest assured that other applications will not be able to access that data.

The security framework is also different from Mac OS X to the iPhone. And we have a framework called Certificates, Key and Trust Services, which provide many useful security services such as certificates, signatures and encryption. Common Crypto, which you know from Mac OS X is there. And there's a randomization library, which you can use if you need access to cryptographically secure random data. And there's the keychain, which I already talked about.

Some things are missing from the phone, and this includes secure transport or open SSL. So if you need to make secure socket layer connections, you should use CF network or NSURL request to make those connections. And Braden will show you some sample code on how to do that later in the session. Since it's a single user system, there's no way of escalating privileges and this means that there are no authentication dialogues or authorization and there's obviously no interface for that either, so those frameworks are missing.

And now let's move on to some specifics about the Mac OS X technologies. I mentioned quarantine, which is a warning that a user gets if he tries to start an application that was downloaded from the internet. And it shows the source of the file and tells him what kind of file it is, if it's a web application or an application. And hopefully helps the user to make an educated decision about whether to run that program or not.

And the Apple's application, Apple's applications automatically apply quarantine information to the files they download. And we hope that your applications will do the same thing. So if your application downloads information from the internet, we think that you should use these APIs. And they're pretty simple. It's like three or five functions that you need to worry about. And if your needs are very simple, then you might even get along with just setting up a security application.

And you might wonder how does that affect preference files, for example. And the fact is that if the user... If the user doesn't go through the finder and open a file, then the quarantine bits don't do anything really. So it shouldn't cause any problems for your application. And you can even combine these technologies, the info property list and the functions, to annotate the downloads, for example, with the source URL.

Code signing exists on the desktop. It was initially available on the desktop in Leopard, and we hope that you continue to sign your applications if you already started, or that you start to sign your applications with your own key. And this is useful for end users, since technologies such as Keychain take advantage of code signing to present fewer dialogues to the user, bothering him less often for his password. And it's also useful for institutional customers who want to enforce policy on their network, for example.

Finally, I want to talk about file system permissions. They're sort of the last line of defense of the operating system. If someone has compromised the system and started to run code on it, he'll likely want to escalate privileges. And insecure file system permissions might be one way of doing that. So to reduce that risk, we want to tighten the default permissions on the system.

And if you want to cooperate with this effort, we hope that you follow some pretty simple guidelines. We've, ever since 10.0, we've been telling you to not modify the application bundle inside of the /applications folder. And this obviously remains true that you shouldn't do that. We're considering tightening the restrictions on /applications and /library. So if you need to write to those locations, do it during install when you're writing files as root.

We also hope that you avoid using the world writable locations on the system, and these include /library/caches/temp. And we have API for getting other directories that can be used to store temporary files or caches that Braden will go into more detail about. So with that, I want to hand over to Braden Thomas, who will present the second part of this talk.

Hi, my name is Braden Thomas, and I'm a product security engineer at Apple. And today I'm going to show you some secure coding tips that you can use to improve the security of your application. So I'm going to show you three scenarios in which you can apply these secure coding tips to improve the security of your application.

The first is synchronization between multiple components. Today, your application may have a server back-end or multiple components or even have a peer-to-peer synchronization, and you want to securely synchronize data between those components, and I'm going to show you how to do that. Second, all your data might not come from a server back-end.

You might be accepting data from the user or from the network, and so to process this user-created data, I'm going to tell you how to handle untrusted data properly and also how to interact with the file system, which may itself be untrusted, and how to do so securely. And finally, I'm going to give you some simple security hardening measures that you can add to your application very easily to secure your application with very little effort by you. So first, let's begin with data synchronization.

So the iPhone especially has platform constraints such as disk space and processing constraints that may encourage you to have multiple like a server back end. Additionally, it's a highly mobile platform and as David mentioned, because of the security landscape, you should expect man in the middle attacks between your application and your server back end.

You can't trust DNS and so instead you should rely on cryptographic security to ensure that the communication is secure. I'll show you how to do that in a minute. Additionally, as the mobile device will increasingly have private data on it, such as data returned by core location, you should adopt a stringent privacy policy to always ask first before transmitting this data to your back end server.

So let's look at an application, an example application, in this case a shopping list application. So this shopping list is acquired from a back-end server, but it's also accessible to the user via a web page where they can review their shopping list. Clearly this is a very simple example. But for this data synchronization strategy, you need to consider three aspects. The first is authentication, how your applications are authenticating to your backend server. Second, the integrity of the data being returned to your applications. And third, encryption of the data being communicated across all channels.

The concern with authentication is a brute force attack whereby a hacker provides a dictionary of passwords to your server and if one of them is correct, gets valid user data back. Let's look at how you can prevent that. We recommend the use of client-side certificates because we have the support built into the APIs. It provides improved security because client-side certificates are far harder to brute force than passwords because as much as we want our users to create secure passwords, it's very rare that they actually do.

Second, if the user changes passwords on one platform, as they generally do when they're using platforms, they have to go through that annoying process of synchronizing all those passwords manually on their various systems. And if they use client-side certificates, they can just stick with that one certificate. So let's look at how you would do that with iPhone APIs. First, you need to generate and sign that certificate on the server.

Second, you transmit that certificate in the form of a PKCS12 blob down to your iPhone in an encrypted format. Then you import the data from that PKCS12 blob and get out a Sec Identity. Finally, when you're actually doing the communication that requires authentication to the server, you want to use that Sec Identity as a SSL certificate's property in your CF Readstream. And so that's how you handle authentication. Let's consider the next aspect of data synchronization, which is integrity.

Now the concern here is that an attacker can insert himself in the middle of your communication and return malicious data to your applications. So as you can see in our example here, you might be buying a Plasma TV, which you didn't want to buy, but the attacker made you think you did. Or you could be running malicious JavaScript in a web browser.

So, to perform integrity checking, all you need to do is use an NSURL connection with an HTTPS URL or a CF read stream with an HTTPS URL. Now, the difference between the two is that with the foundation layer, you need to use a trusted certificate, whereas with the CF layer, you don't need to use a trusted certificate. You may want to consider and weigh the pros and cons of both approaches. Now, obviously, a trusted certificate is going to cost you some money since you'll need to pay a CA to sign that certificate for you.

However, it won't provide you any cryptographic benefit because at the end of the day, the same cryptography is occurring. But Foundation is probably a simpler implementation for your application, and that same certificate can be shared with a web interface where the user requires a trusted certificate to be able to view the details on your website and verify that they're connecting to the correct site.

If you do choose to use a non-trust certificate, which may be right for your application, there's a couple steps you need to take. First, before connecting, you need to disable chain validation. And you do this by setting the SSL validates chain property to false. And then you go ahead and do the connection, reading out the data.

After you read the data and have performed the connection, before processing it, to verify the peer trust, You pull out the SSL peer trust property. And then you set your own anchor certificate to whatever you want your anchor certificate to be, if it's maybe your own CA embedded in the application. And you evaluate the trust to verify that you're receiving a valid certificate.

So that's integrity. Let's look next at encryption. Of course, the standard attack for encryption is an attacker is on your local network or some node on the way to your server and is able to read user private data. So you, of course, get this for free if you're using an HTTPS server. And this works with NSURL connection or CFREAD stream as shown in the prior example. This is most critical when you're transmitting any kind of personally identifiable data, such as a user's location.

So, as I mentioned before, all your data, of course, isn't going to come from your server back end. Some of that data may come from the user himself. Here's your application, and you want to receive this user-created data over the network or if you're running on the desktop via the file system. You have to consider things like buffer overflows, integer overflows, format string vulnerabilities. These are your standard memory management corruption vulnerabilities.

However, if you're receiving untrusted data, you also need to consider if that data is HTML. So let's look at this closer. Additionally, when you're interacting with the file system, if you're on a desktop system, you have to consider that the file system itself could be untrusted if there's local attackers potentially on that system. So we need to consider race conditions.

So first, let's look at buffer overflows. Buffer overflows, as you probably know, are when data is copied into a buffer that's too small. And this commonly occurs when you're using unsafe string functions. We recommend using the following string functions as opposed to the strcat and strcopy or the strcat and strcopy functions. We recommend the L variety. Or the sprintf vsprintf.

We recommend the snprintf and vsprintf. And finally, you should never use the gets function. So, string functions will only help you so far. If you're doing manual memory copying from one buffer to another, you need to perform your own sanity checking. But let's look closer at these string functions.

Here you have a destination buffer that's five bytes, and you're copying in a string that's six characters long with a null termination that's seven bytes into the smaller buffer. If you use stir copy, you're going to get a simple buffer overflow overriding uninitialized memory past the size of the buffer. This is probably exploitable for code execution.

We don't recommend this for obvious reasons. Next, if you use the stir in copy, you're not going to overwrite the uninitialized data past the destination buffer size. However, you do have to be concerned because no null termination of your destination buffer has occurred. So if you're later using this destination buffer, whether it's an insecure string function, or if you're trying to determine the length, you've lost that length value. It's no longer a C string, null terminate C string, so it's more difficult for you to determine the length of that buffer. This could possibly lead to your application crashing by reading into uninitialized memory.

So instead, we recommend using the strlcopy function. This will null terminate the destination buffer and not perform a buffer overflow. However, you still have to consider what sort of application-specific consequences occurred by truncating whatever data is being copied. And that really just needs to be handled in code, and you can check the return value of the strlcopy function to determine if truncation has occurred.

So that's buffer overflows. Let's look at another very common memory corruption issue, integer overflows. An integer overflow occurs when you're performing an arithmetic operation and the integer that you're performing that operation on exceeds or goes under the size of the data type that that integer is. For example, on a 32-bit platform, an int would be 32 bits, where on 64-bit, it would be 64 bits. So here's a common code pattern that we commonly see integer overflows occurring in. And I'm going to walk you through it.

First, we define a binary data structure. And this binary data structure defines data that is a number of entries followed by memory allocated for those entries. Entry itself is a structure with a static size that I don't show here. So we're reading data in as this data blob. We're then going to copy this data blob into another data blob. And what we do is we first allocate the destination by multiplying the number of entries by the size of each entry. And that's pretty intuitive.

We then step through each entry and we copy them one by one into our destination. But the highlighted code here has a problem and it's an integer overflow. So when we multiply the number of entries by the size of each entry, the resulting value could potentially overflow and allocate less memory than we thought. When we then do the one-by-one copy, it would result in a heap overflow, leading to code execution.

So for example, if the size of an entry is 10 bytes and an attacker passes in a number of entries, which is 1-9999-A, the resulting multiplication would overflow the one past the 32 bits available, and the 32-bit type would be truncated to four. So we'd only have four bytes allocated for our destination, and when we did the one-by-one copy, we would overflow that buffer very quickly.

So we introduced in Leopard the CheckInt.h API, which is a header file containing macros you can use to prevent integer overflows in your application. To show how this would solve the problem in the example, first we include the checkint.h header. Then, when we perform the multiplication, we actually use the check unsigned int 32 multiply macro.

The first two arguments are the two values that we're going to multiply together. The third argument is a pointer to an integer. And this integer is an error value. If that value is ORed with an error, then when we return, we know that an integer overflow has occurred. So check this integer value after you perform the multiplication. If there's no error, then you can go on through your code and you know that you're safe to do the copy.

So a next common type of memory vulnerability is a format string vulnerability. This occurs when you take a format string function like printf and you don't pass a format specifier string. A format specifier string is just the percent s or the percent d that you see in this printf example. If you don't do this, you open yourself up to code execution. So while you may know about this in terms of printf, you might not have known that all these other functions exist that also take format strings.

And you should be very careful when using any one of these functions to ensure that you're not causing format string vulnerability in your application. We recently saw a lot of exploitation with the month of Apple bugs with the NS alert and alert methods because people weren't entirely certain that these actually accepted format strings.

So let's look at what an attacker can do with such a format string vulnerability. So this simple program just copies an argument from the command line into a buffer and then prints it out. Now the copy is safe because we're using the STOREL copy and passing the size of the destination buffer, but the printf is unsafe because it doesn't contain a format specifier string.

So the attacker will first try and run this with, say, 4% Xs. Now, because the parameter area occurs before the local variable area in the stack, these 4% Xs, which would normally just print out the hex value of arguments to the printf, since there's no arguments to the printf aside from the buffer, this will just print out data that occurs next on the stack.

So you see we have this BFF92D sum data on the stack, followed by 400, followed by 0, followed by this 41414141. This value is special because it is the hex equivalent of this AAAA. Now, what that tells the attacker is that he has now hit the local variable area, because he's printing out this AAAA, which is existing in this buffer allocated in the local variable area.

Now, what the attacker can now do is use the %n specifier. Now, this is rarely used by modern programs, but what it does is it writes the number of bytes printed by a printf function into a variable stored in that argument. Because there's no arguments here, we've replaced the last percent X, which corresponded to the 41, 41, 41, with this percent in.

So we now know that we're going to be writing some value into this address. And if you can see here, GDB showed that we crashed trying to write into that address. And this 41, 41, 41, 41 is just used as an example, but an attacker could specify any arbitrary address here.

So we know what he's writing into. What is he writing? So if you use the percent 100,000X, this will print out a whole bunch of values, artificially increasing the number of bytes that have been printed. So the attacker can kind of indirectly specify what data is going to be written into that value.

And as you can see in GDB, the instruction is trying to write this 32-bit value into the address 41414141. And what it's trying to write, as you can see, is 100,000 and some change because that's what the attacker has specified. And so he can use this write what where to attack your application and easily cause code execution. And so that's why you have to be very careful with format string functions.

So those are common memory handling vulnerabilities. Let's look at some other untrusted data. One type of untrusted data that you might be receiving is HTML. So on Mac OS X, if you were displaying HTML that you received off the network, you could use web preferences to turn off JavaScript and plugins in your application. But on iPhone, we don't support the web preferences currently. So you have to be very careful with HTML that's loaded from the local zone from a file.

This might hit you if you're using some kind of HTML template where you have the HTML already, and then you're formatting in user-supplied data. So what an attacker could do is he could supply his own data to inject malicious JavaScript into the HTML displayed, for example, in your UI web view, and cause undesired effects, or potentially he could read arbitrary files off the system, so anyway, you want to avoid using these kind of HTML templates unless you're very certain that your application won't be subject to these kind of cross-site scripting attacks.

Finally, I also want to mention the NS Archiver format. Now, this format is commonly used in nib files, and some people might even use it as a simple document type. But it really acts as frozen code, and it's not intended for use as a generic document, because if an attacker can supply arbitrary data to NS Unarchiver, he can unarchive any number of classes that you're not expecting, and he can probably use that to get code execution. So instead, we recommend using property lists, whether you're using NS property list serialization or one of the convenience functions in foundation classes, like write to file.

So that's untrusted data. Let's look at untrusted file systems very briefly in terms of a Mac OS X desktop application. So what we have here is a pretty common example of how an application might read or might delete an old cache file and then create a new cache file. This operation probably occurs in the course of a few milliseconds where he's removing the old cache and then opening and writing the new cache.

However, in the meantime, an attacker could create a symlink there. The result is when the new cache file is opened and written, the data is actually sent to the attacker-supplied path. This could overwrite user-created documents, causing data loss. It could even potentially decode execution. So to prevent this on iPhone, this is very easy. You just stay in your application container. You don't have to worry about any of this stuff.

On Mac OS X, you don't have to worry about any of this stuff. On Mac OS X, as David mentioned earlier, you need to avoid /tmp and /library/caches since they're world-writable locations and you're subject to this attack. You should really only use these locations if it's absolutely critical that your application share data that's writable by multiple processes that have multiple users. But if you're only sharing data amongst one user, you should instead use the protected var folders alternative because this is a per-user location. So in Cocoa, to do this, you use the NSTemporaryDirectory API.

And this will get you a directory that you're probably already using this API. It will give you a directory that is safe to use on a per-user basis and won't be subject to race conditions like /tmp. If you're operating at a lower level, you can use the CAPI compster. If you pass in the DarwinUserTempter constant, you'll get out the same value as NSTemporaryDirectory.

If you pass in the DarwinUserCaster constant, you'll get out a cache directory that's per-user that's constant across boot. And we really recommend you use this instead of /library slash caches. And if you're interested in what one of these locations looks like, you can use the shell tool, gitconf, and you can pass in like DarwinUserTempter or DarwinUserCaster to see what one of these locations looks like. And as you can see, they're very unique per-user because of the UUID that's in there.

So that's managing untrusted data. Let's look at what you can do in your application to harden it against attackers. Some of these are very easy. So first of all, we recommend the use of privilege separation where applicable. A privilege separation involves factoring your application into multiple components. And when you do that, each component has less code and reduces attack surface. But you have to ask, where do you do this factoring? So you want to factor out things that are extremely high risk, for example.

And these high risk components can be easily sandboxed or they can be run with reduced privileges. And I'll give you an example use case for that. And with these privilege separated helpers, you're probably going to be doing communication over CF message port or local socket. Additionally, in Snow Leopard, we're introducing a service management API that makes adding jobs and privileged helpers much easier. Because you can just use API.

Previously, you had to use an authorization execute with privileges trampoline to install a P list directly into launch day. And you no longer need to do that in Snow Leopard. However, you will need to opt into code signing because the application has to trust which job it's starting and the job has to trust which application it's communicating with. So both of those processes need to be code signed. Additionally, you will need to still obtain rights to add a helper. And that is the add privilege job authorization right. And the application would pre-authorize then call the service management API.

So let's look at a couple of use cases that are very commonly used where privilege separation would help you in your application. The first is authorized tasks. If you currently have an authorized task, you may be using authorization execute with privileges. You may be using a set UID or self-repairing tools. We don't recommend that you do that because, as David mentioned, especially with set UIDs, that's generally very difficult to do correctly and often will lead to security vulnerabilities in your application.

So instead, we recommend using one of these privileged helpers and sending an authorization ref in external form over a CF message port or over a local socket. And if you want, you can look at the better authorization sample on developer.apple.com, which uses a local Unix socket to pass over a serialized authorization ref. And you can just grab that source and use it right there.

So additionally, another common use case for privilege separation is if, for example, you have a really complex media format or document format and you're a little nervous about your code. You're not sure that it's 100% secure against any kind of corrupted data. So, for example, we use this internally on H.264 decoding, and we have this thing called the SBX Profile Pure Computation.

And you can pass this in Sandbox init, and it will create a sandbox for that helper that will only be used for pure computation. And file system and network access is not allowed. And in such a case, you would receive the raw data, maybe off the network or from the main application. And you would return these parsed and vetted structures. Basically, the meat of the decoding occurs in this helper tool.

So now let's look at some security hardening compiler flags that David briefly mentioned earlier, and these provide you with some free security. So the first is defortify source equals two. Now, this converts some certain insecure string functions like the ones I showed earlier into a secure variant. Now, this isn't a silver bullet because the compiler needs to determine at compile time what the size of the destination buffer is.

And the compiler is not as intelligent as the developer who wrote the code is, so not all of these uses will be converted. So we're actually planning to implement this by default in Snow Leopard, but it's a good idea for you to use it now to work out any possible issues you should have.

Second, there's the fstackprotector compiler flag. This will add stack canaries to your code, and what a stack canary does is it sits like a little canary right before the return address on the stack. And if an attacker manages to overwrite the stack and overwrite that return address, the canary dies.

And when the canary dies, the program dies. We're also planning on implementing this by default in Snow Leopard, and again, we recommend using it now to make sure that there aren't any issues with your program. For example, in Snow Leopard, when we turned these things on, in one or two applications, we found that we actually had a latent overflow that occurred that we were able to fix because we turned this on.

Next, there's the linker flag for position independence. David mentioned this briefly. It's the PI flag, and it will randomize the load address of an executable, your executable. And currently, by default, all system libraries will be randomized. However, you're executable, and whatever libraries that you load on the fly or whatever libraries you supply won't be randomized.

So by turning this on, you improve library randomization, and that makes it much more difficult for an attacker to use these return to libc attacks, where he jumps into known code that performs some operation he can use to his benefit. Finally, there's a warning flag, W Format Security. And this warning flag just provides additional warnings at compile time that will warn you if you're maybe using format string functions in an insecure manner.

So to summarize what Dave and I talked about today, the security of OS X and iPhone is continually improving. And if your applications opt in early, they can get the benefit of these improvements and ease the process. Additionally, if your application is receiving files, we recommend that you turn on quarantine, whether programmatically or via the Info.plist.

Especially with iPhone and mobile devices, you should expect a malicious network. So never trust DNS. Rely on cryptographically secure communication. If you're handling untrusted data or files, be sure to avoid things like buffer overflows, integer overflows, format string vulnerabilities. And if you can, use privilege separation to put the meat of your processing code in a separate process and sandbox that process.

Finally, we showed you some compiler flags you can use to provide additional security hardening for your application with very little effort by you, the developer. Here's some contact information that you can use to get additional information. We recommend these sessions. You might want to see them if you're really interested in security on the iPhone. And we're going to be, especially in the Mac OS X security labs, we recommend these security labs.