Fire & Ice: making and breaking mac firewalls
Wardle, Patrick
In the ever raging battle between malicious code and anti-malware tools, firewalls play an essential role. Many a malware has been generically thwarted thanks to the watchful eye of these products. However on macOS, firewalls are rather poorly understood. Apple's documentation surrounding it's network filter interfaces is rather lacking and all commercial macOS firewalls are closed source. This talk aims to take a peek behind the proverbial curtain revealing how to both create and 'destroy' macOS firewalls. In this talk, we'll first dive into what it takes to create an effective firewall for macOS. Yes we'll discuss core concepts such as kernel-level socket filtering—but also how to communicate with user-mode components, install privileged code in a secure manner, and simple ways to implement self-defense mechanisms (including protecting the UI from synthetic events). Of course any security tool, including firewalls, can be broken. After looking at various macOS malware specimens that proactively attempt to detect such firewalls, we'll don our 'gray' (black?) hats to discuss various attacks against these products. And while some attacks are well known, others are currently undisclosed and can generically bypass even today's most vigilant Mac firewalls. But all is not lost. By proactively discussing such attacks, combined with our newly-found understandings of firewall internals, we can improve the existing status quo, advancing firewall development. With a little luck, such advancements may foil, or at least complicate the lives of tomorrow's sophisticated Mac malware!
 All right, Aloha, and welcome to my talk on making and breaking Mac firewalls. My name is Patrick. I work at Digital Security, where we are creating cybersecurity tools for the Mac enterprise. I'm also the creator of the Mac security website, Objective C. Woo! So today, thank you, thank you, we're going to be talking about creating or making a Mac firewall. And then we're going to kind of shift gears and talk about breaking and bypassing such products. So about a year ago, I decided I wanted to write a firewall for Mac OS because there were no free open source options. So in this section of the talk, we'll describe this process, creating Lulu, which is my free open source Mac firewall. Now, there are many reasons you might want to create or install a firewall. They're actually pretty good security tools. Probably the two main reasons are one, to protect your privacy or two, to thwart cyber attacks, because most firewalls are able to generically detect malware when the malware connects out, perhaps to expiltrate data or connect to a command and control server for tasking. So what our firewall is going to do is monitor all network traffic, allowing traffic out that's trusted and ideally blocking or prevented unauthorized or malicious traffic. Now, since we're going to need to monitor all traffic globally, we're going to have to write a kernel extension. In Mac OS, Apple provides network kernel extensions, or NKEs, as a way to extend or modify the network infrastructure. And one type of NKE is a socket filter, which, as its name suggests, allows code to filter network traffic at the socket level, which for a firewall is perfect. That's exactly what we need. Now, there are two steps to register a socket filter. First, we populate a socket filter structure. And this structure contains various callbacks that, once registered, will be automatically invoked by the operating system on certain socket operations, which then gives our firewall the ability to examine these socket actions and determine whether they should be allowed or blocked. So the second step is then to invoke the socket filter register function to install your socket filter. Now, besides the populated structure, this also takes a socket domain type and protocol, which means if you want to filter all socket domains, types, and protocols, you should invoke this method or function several times. OK, so now let's talk about these callbacks, which, as I mentioned, once your socket filter is registered, will be automatically invoked by the operating system on socket events. The first callback is the attached callback, and as we can see on the slide, it will be invoked any time a new socket is created. So it's created with a cookie parameter that's designed to hold any socket-specific information. You can really put whatever you want there. So what we do is we allocate a chunk of memory, and based on the PID of the process that's creating the socket, we either set it to allow, for example, if it's a trusted system daemon, or block if it's a process that the user has chosen to block. Now, if it's a process we don't recognize, we set this action to ask, and then we're going to have to do some extra logic to determine what action to take. So next is the connect out callback. This is called before initiating an outgoing connection. Again, it takes the same cookie, which we've set to either allow, block, or ask, and the socket and the remote address that the socket is trying to connect to. So this obviously allows us to examine the endpoint. Now, if the action has been set to allow, we just return OK. This tells the operating system we are OK with allowing this connection to continue. If it's set to block, we return an error code from this function, which tells the operating system we want to block or not allow the connection. And if it's set to ask, we have to execute some extra logic to determine what action to take. So in other words, we have to figure out whether to allow or block the connection. So what we do is we first put the thread to sleep that's trying to perform the socket operation. This will pause the action. We then ask our user mode firewall component for assistance. And we pass the information from the kernel, specifically the PID and the socket via a shared queue. Once the daemon gets this request from the kernel socket filter, it maps the PID to a path and first checks a rules database to see if that path is in the database. If it's not found, perhaps it's a brand new application or a piece of malware that has somehow gotten onto your system, what it does is it sends a message to another firewall component that's running in the user's session. And this is what actually displays the firewall alert to the user. Now, the user's response, they'll either have to click allow or block, will then be passed back to the daemon. The daemon will save this response to the rules database, so moving forward, it knows what to do, and then also sends this response back to the kernel component via an IO kit interface. The kernel extension will then wake up the thread that was put to sleep and then apply the action, either allowing the connection or blocking it. So that's basically all that's needed to create a comprehensive firewall for macOS. And putting this all together, we have Lulu. As I mentioned, Lulu is a free firewall, I don't think, and users should have to pay for security products. And also, the full source for the firewall is online on GitHub. And as of today, you can download and install version 1.0. Awesome. Thank you. Free-friendly audience today. I really like this. All right, so Defcon, in my opinion, is predominantly a hacker conference about breaking things and exploits and vulnerabilities. So let's kind of switch gears and talk about now breaking and bypassing such firewall products. So imagine you're an attacker or a piece of malicious code that has somehow made it onto an end system. Unfortunately, there's a firewall that's installed. So if you are going to connect out, perhaps to exfiltrate data or connect to a command and control server, the firewall is going to detect and block this. So your goal is simple. How can you connect out without the firewall blocking this data? So in this section, we'll first look at some firewall-aware malware. We'll then look at some security vulnerabilities in firewall products and then end with ways to completely bypass the firewalls. So first, it's definitely important for malware or an implant to detect if a firewall is installed on the box. Otherwise, it really might be there undoing, as the firewall may detect a previously undetected malware when it tries to connect out. And as we can see on the slide, this has happened. Now, I've yet to see any public Mac malware that tries to specifically bypass Mac firewalls, but there are some specimens that are firewall-aware. And what I mean by that is they will enumerate installed processes or look specifically for firewalls, and if they see an installed firewall, they will not persistently infect that system. One example of this is Devil Robber. And what Devil Robber did is it looked for little snitch, which is a popular Mac firewall. If that was installed, it would not infect the system. It would just execute a benign instance of the application it had infected and then simply exit. Okay, now onto some security issues. Software such as firewalls often very complex, and firewalls often run with elevated privileges or even in the kernel. Now, unfortunately, they're not as well written as the operating system, nor have been audited as well, which makes them excellent targets for local privilege vulnerabilities. So I talked about this bug at DefCon a while ago, but just briefly to go over, it's kind of a neat kernel bug that affected the little snitch firewall kernel extension. Basically, the firewall extension took a 64-bit value from user mode and used that in an allocation and a copy routine. Unfortunately, the allocation routine expected a 32-bit value, so it truncated that. However, the copy routine expected a full 64-bit value, so it allowed us to have a controllable mismatch between the allocation and then the copy routine, which led to an exploitable heap overflow in the kernel, allowing us to execute arbitrary code in ring zero. Another issue I found while briefly looking at little snitch affected its installer and updater component. In short, the firewall installer did not validate the components it was going to install. So a local unprivileged attacker could modify these components, and then the firewall installer or updater would naively install and execute them as root, again, giving a local unprivileged attacker a very reliable way to elevate their privileges. All right, now on to bypassing firewalls. We'll first look at some product-specific bypasses, but then we'll also look at some more powerful generic ones that can bypass all third-party firewalls. Again, the goal here is network access without being blocked. Now, I do want to reiterate that, in my opinion, these bypasses are not security issues per se, like they don't deserve a CVE, but, however, they're still very valuable, especially for an attacker or piece of malware, which may otherwise be thwarted by the firewall. So first up, we have radio silence. It's a popular firewall for macOS. It kind of takes an interesting approach in that it allows any new process, but the user can explicitly blacklist certain applications. However, if we look at the blacklisting logic in the kernel extension, we can see it looking for a name of a process, and it appears if the process is named launchD, it cannot be blacklisted nor blocked. So let's test this. We take some malware. We name it launchD. Again, the path doesn't matter, just the name. And then we manually create a rule to blacklist this process. We then run it, and as we can see on the slide, it's still allowed out, because, again, it is named launchD. So kind of lame, but, again, fully bypasses this firewall. Another popular mac firewall is named handsoff, and it turns out that we can pretty easily bypass this via a synthetic click. So for example, if we execute curl, which is something that mac malware often does, for example, to download additional components, as expected, the firewall will detect this unauthorized activity and display an alert. What the attacker or malware can then do is send a programmatic synthetic click to that allow button, which will click the allow button, basically hiding the alert and allowing the connection. And it also turns out there are ways you can do this without the user noticing. So there are ways that you can do this invisibly so that the user is not going to see the alert and the synthetic mouse click. Next up, we have lulu. By default, lulu trusts Apple binaries. Yeah, I'm picking on everyone including my own tools. I think it's only fair. So lulu by default trusts Apple signed processes. However, it gray lists certain Apple binaries, which could potentially be abused for malicious activity. So, for example, netcat and curl, even those are signed by Apple, it will still alert anytime anybody executes them. So the question is, can we find another signed Apple utility that is not on the gray list? And the answer is yes. Turns out you can exfiltrate data via the who is utility. This was news to me. So as we can see on the slide in the lulu debug log, if we execute this, the firewall will see the outgoing connection, because again, it's global, it sees all network traffic. However, because who is is signed by Apple proper and is not on the gray list, it will be allowed. Now note this has been fixed. I've basically added who is to the gray list. And finally, we have little snitch. Little snitch is the de facto most well-known firewall for Mac OS. Turns out it has an undelatable rule that says any process can talk to iCloud.com domains or URLs. This means any process, even malware, is allowed to talk to Apple servers. To test this, we can manually create a deny rule for curl. And then we can execute curl with an iCloud URL, and it is still allowed. So a while back, I reverse engineered the iCloud protocol and built a CNC server on iDrive for testing purposes. Don't get mad at me, Apple. So it actually is a great drop box like CNC server, because you can get alerts when files are uploaded. It's really great. Once we understand the protocol, what we can do is write some custom code that we can use to exfiltrate data. Now, even if little snitch is installed and sees the connection, it will be allowed because the endpoint we are talking to matches or maps to an iCloud domain. Okay, so those were some product-specific bypasses. Kind of neat, kind of funny. But in my opinion, they're still a little bit lame. And they're lame because first an attacker would have to enumerate and determine the specific firewall product that was installed, and then have one of these product-specific bypasses. Way more powerful are generic bypasses, which can just bypass any installed firewall. And these are all possible because the firewall is essentially disadvantaged. It has to allow some network traffic off the box. For example, trusted system daemons, or the user is probably going to fully allow certain things like browsers. So the first thing we do to find a generic bypass is once we're on a system as a piece of malware or an attacker, is passively sniff to see what traffic is allowed off the box. And we can do this via the LSOF utility. So if we execute this on a box, even though I have my firewall installed, obviously there's going to be some traffic that is allowed out. So for example, we can see browsers, chat applications, some Adobe licensing crap, et cetera, et cetera. So now we know what traffic or what processes are allowed through the firewall. So for the first generic bypass, we're going to indirectly exploit the trust of a process via a trusted protocol. So on macOS, any time a DNS request is made, this is handled by Apple's MDNS responder. This means if a random application or piece of malware tries to resolve a domain, the malware or the application actually does not generate the network request. It's sent locally to the system daemon, which then on the application's behalf will resolve the domain. So what malware can do is basically abuse this fact, because yes, again, the firewall is going to see this DNS resolution. But since it's just a DNS request coming from the Apple sign trusted DNS daemon, which is handling all DNS requests for the entire system, the firewall is going to allow it. So very easily, we can build a bi-directional command control protocol purely based on DNS. Next up, let's talk about abusing browsers. The simple fact is if you have a browser installed, it's going to be able to access the network. Even if you maybe say only port 80 and 443, you're probably going to give it indiscriminate access to talk to any web server. And again, we can passively determine this via LSOF. So the first way we can abuse browsers is via AppleScript. So as we can see on the slide, we have kindly asked Safari to invisibly browse to an attacker-controlled URL. And any data we want to exfiltrate, we can put in as a get parameter. Again, the firewall will see this connection, but as it's Safari simply browsing to a URL, it will not be locked. Now, an even better way to bypass any installed firewall is to abuse browsers' command line interfaces. Really doesn't get any easier than this. All major browsers now support a command line interface, so you can very easily programmatically execute them from a script, piece of malware, from the command line. And again, the firewall will see this connection, but it's just the browser browsing to some URL, so it will not block it. Yet another way to generically bypass all third-party firewall products is to simply inject a library or code into an application or a binary that the firewall trusts. And again, via LSOF, we can determine passively what those are. Now, once this code, this library, is running in that trusted process, from the firewall's point of view, it will also be given that same level of trust, and thus can access the network. For example, if the browser is trusted and you inject code into the browser, and that malicious code connects out, the firewall will allow it because it just sees it's the browser. Now, there's many ways on macOS to inject into especially third-party applications. We don't have time to go into all of them, but I have listed them here on the slide. The final way to bypass kernels involves, or firewalls rather, involves getting code into the kernel. And the simple fact is, if an attacker is able to get code running in the kernel, it's completely game over for the firewalls. First, a lot of firewalls will generically allow traffic that is originated from the kernel. And, secondarily, if malicious code is running in the kernel, it can actually unregister or unhook any installed socket-filtered driver. This will then transparently disable the firewall, and then the attacker's code, even from user mode, can connect out without having to worry about the firewall. Okay, so let's start wrapping this all up. So today we talked about building a firewall for macOS. We saw that using a socket-filter kernel extension, really not that complicated. As I mentioned, the source code for Lulu is on GitHub, so if you're interested in more of the details and specifics, I would recommend checking that out. We then talked about breaking firewalls. We showed that a lot of them actually have significant security flaws, which are very problematic because the firewalls often run with root privileges or even in the kernel. And then we also showed that the unfortunate reality is these products are all trivial to generically bypass. Now, this doesn't mean we should uninstall our firewall products, but I think it makes a good case for a defense-in-depth strategy. For example, maybe some other host-based security products that can perhaps block some of the prerequisites for these attacks. For example, preventing die-lib injection, or perhaps can detect that the browser is running from the command line when the user isn't active. Like, that's not something a firewall should detect, per se, but perhaps another security tool should. And finally, today I'm really excited to announce a brand new Mac Security conference called Objective By The Sea. We have a really cool lineup of Mac Security researchers. It's also going to be at this awesome resort in Hawaii. And if you're a supporter of Objective Sea, which you can be for $1, the conference to attend is completely free. I just want to reiterate that it's in Hawaii. This is the actual resort of where it's going to be, November 3rd and 4th. So I would love if you could all attend. And for more information, check out ObjectiveByTheSea.com. Okay, that's a wrap. I really want to thank you all for attending. Also, I want to thank the partners of Objective Sea, which are Digita Security and Mauerbytes. And we have 13 seconds for questions. But I will be around here after the talk to obviously answer any other questions. Thank you.
 All right, Aloha, and welcome to my talk on making and breaking Mac firewalls.  My name is Patrick.  I work at Digital Security, where we are creating cybersecurity tools for the Mac enterprise.  I'm also the creator of the Mac security website, Objective C.  Woo!  So today, thank you, thank you, we're going to be talking about creating or making a Mac firewall.  And then we're going to kind of shift gears and talk about breaking and bypassing such products.  So about a year ago, I decided I wanted to write a firewall for Mac OS because there were no free open source options.  So in this section of the talk, we'll describe this process, creating Lulu, which is my free open source Mac firewall.  Now, there are many reasons you might want to create or install a firewall.  They're actually pretty good security tools.  Probably the two main reasons are one, to protect your privacy or two, to thwart cyber attacks,  because most firewalls are able to generically detect malware when the malware connects out,  perhaps to expiltrate data or connect to a command and control server for tasking.  So what our firewall is going to do is monitor all network traffic, allowing traffic out that's trusted  and ideally blocking or prevented unauthorized or malicious traffic.  Now, since we're going to need to monitor all traffic globally, we're going to have to write a kernel extension.  In Mac OS, Apple provides network kernel extensions, or NKEs, as a way to extend or modify the network infrastructure.  And one type of NKE is a socket filter, which, as its name suggests, allows code to filter network traffic at the socket level,  which for a firewall is perfect. That's exactly what we need.  Now, there are two steps to register a socket filter.  First, we populate a socket filter structure.  And this structure contains various callbacks that, once registered, will be automatically invoked by the operating system on certain socket operations,  which then gives our firewall the ability to examine these socket actions and determine whether they should be allowed or blocked.  So the second step is then to invoke the socket filter register function to install your socket filter.  Now, besides the populated structure, this also takes a socket domain type and protocol,  which means if you want to filter all socket domains, types, and protocols, you should invoke this method or function several times.  OK, so now let's talk about these callbacks, which, as I mentioned, once your socket filter is registered, will be automatically invoked by the operating system on socket events.  The first callback is the attached callback, and as we can see on the slide, it will be invoked any time a new socket is created.  So it's created with a cookie parameter that's designed to hold any socket-specific information. You can really put whatever you want there.  So what we do is we allocate a chunk of memory, and based on the PID of the process that's creating the socket, we either set it to allow,  for example, if it's a trusted system daemon, or block if it's a process that the user has chosen to block.  Now, if it's a process we don't recognize, we set this action to ask, and then we're going to have to do some extra logic to determine what action to take.  So next is the connect out callback. This is called before initiating an outgoing connection.  Again, it takes the same cookie, which we've set to either allow, block, or ask, and the socket and the remote address that the socket is trying to connect to.  So this obviously allows us to examine the endpoint.  Now, if the action has been set to allow, we just return OK. This tells the operating system we are OK with allowing this connection to continue.  If it's set to block, we return an error code from this function, which tells the operating system we want to block or not allow the connection.  And if it's set to ask, we have to execute some extra logic to determine what action to take.  So in other words, we have to figure out whether to allow or block the connection.  So what we do is we first put the thread to sleep that's trying to perform the socket operation. This will pause the action.  We then ask our user mode firewall component for assistance.  And we pass the information from the kernel, specifically the PID and the socket via a shared queue.  Once the daemon gets this request from the kernel socket filter, it maps the PID to a path and first checks a rules database to see if that path is in the database.  If it's not found, perhaps it's a brand new application or a piece of malware that has somehow gotten onto your system, what it does is it sends a message to another firewall component that's running in the user's session.  And this is what actually displays the firewall alert to the user.  Now, the user's response, they'll either have to click allow or block, will then be passed back to the daemon.  The daemon will save this response to the rules database, so moving forward, it knows what to do, and then also sends this response back to the kernel component via an IO kit interface.  The kernel extension will then wake up the thread that was put to sleep and then apply the action, either allowing the connection or blocking it.  So that's basically all that's needed to create a comprehensive firewall for macOS.  And putting this all together, we have Lulu. As I mentioned, Lulu is a free firewall, I don't think, and users should have to pay for security products.  And also, the full source for the firewall is online on GitHub.  And as of today, you can download and install version 1.0.  Awesome. Thank you.  Free-friendly audience today. I really like this.  All right, so Defcon, in my opinion, is predominantly a hacker conference about breaking things and exploits and vulnerabilities. So let's kind of switch gears and talk about now breaking and bypassing such firewall products.  So imagine you're an attacker or a piece of malicious code that has somehow made it onto an end system.  Unfortunately, there's a firewall that's installed. So if you are going to connect out, perhaps to exfiltrate data or connect to a command and control server, the firewall is going to detect and block this.  So your goal is simple. How can you connect out without the firewall blocking this data?  So in this section, we'll first look at some firewall-aware malware.  We'll then look at some security vulnerabilities in firewall products and then end with ways to completely bypass the firewalls.  So first, it's definitely important for malware or an implant to detect if a firewall is installed on the box.  Otherwise, it really might be there undoing, as the firewall may detect a previously undetected malware when it tries to connect out.  And as we can see on the slide, this has happened.  Now, I've yet to see any public Mac malware that tries to specifically bypass Mac firewalls, but there are some specimens that are firewall-aware.  And what I mean by that is they will enumerate installed processes or look specifically for firewalls, and if they see an installed firewall, they will not persistently infect that system.  One example of this is Devil Robber. And what Devil Robber did is it looked for little snitch, which is a popular Mac firewall.  If that was installed, it would not infect the system. It would just execute a benign instance of the application it had infected and then simply exit.  Okay, now onto some security issues. Software such as firewalls often very complex, and firewalls often run with elevated privileges or even in the kernel.  Now, unfortunately, they're not as well written as the operating system, nor have been audited as well, which makes them excellent targets for local privilege vulnerabilities.  So I talked about this bug at DefCon a while ago, but just briefly to go over, it's kind of a neat kernel bug that affected the little snitch firewall kernel extension.  Basically, the firewall extension took a 64-bit value from user mode and used that in an allocation and a copy routine.  Unfortunately, the allocation routine expected a 32-bit value, so it truncated that.  However, the copy routine expected a full 64-bit value, so it allowed us to have a controllable mismatch between the allocation and then the copy routine,  which led to an exploitable heap overflow in the kernel, allowing us to execute arbitrary code in ring zero.  Another issue I found while briefly looking at little snitch affected its installer and updater component.  In short, the firewall installer did not validate the components it was going to install.  So a local unprivileged attacker could modify these components, and then the firewall installer or updater would naively install and execute them as root,  again, giving a local unprivileged attacker a very reliable way to elevate their privileges.  All right, now on to bypassing firewalls.  We'll first look at some product-specific bypasses, but then we'll also look at some more powerful generic ones that can bypass all third-party firewalls.  Again, the goal here is network access without being blocked.  Now, I do want to reiterate that, in my opinion, these bypasses are not security issues per se, like they don't deserve a CVE,  but, however, they're still very valuable, especially for an attacker or piece of malware, which may otherwise be thwarted by the firewall.  So first up, we have radio silence.  It's a popular firewall for macOS.  It kind of takes an interesting approach in that it allows any new process, but the user can explicitly blacklist certain applications.  However, if we look at the blacklisting logic in the kernel extension, we can see it looking for a name of a process,  and it appears if the process is named launchD, it cannot be blacklisted nor blocked.  So let's test this.  We take some malware.  We name it launchD.  Again, the path doesn't matter, just the name.  And then we manually create a rule to blacklist this process.  We then run it, and as we can see on the slide, it's still allowed out, because, again, it is named launchD.  So kind of lame, but, again, fully bypasses this firewall.  Another popular mac firewall is named handsoff, and it turns out that we can pretty easily bypass this via a synthetic click.  So for example, if we execute curl, which is something that mac malware often does, for example, to download additional components,  as expected, the firewall will detect this unauthorized activity and display an alert.  What the attacker or malware can then do is send a programmatic synthetic click to that allow button,  which will click the allow button, basically hiding the alert and allowing the connection.  And it also turns out there are ways you can do this without the user noticing.  So there are ways that you can do this invisibly so that the user is not going to see the alert and the synthetic mouse click.  Next up, we have lulu.  By default, lulu trusts Apple binaries.  Yeah, I'm picking on everyone including my own tools.  I think it's only fair.  So lulu by default trusts Apple signed processes.  However, it gray lists certain Apple binaries, which could potentially be abused for malicious activity.  So, for example, netcat and curl, even those are signed by Apple, it will still alert anytime anybody executes them.  So the question is, can we find another signed Apple utility that is not on the gray list?  And the answer is yes.  Turns out you can exfiltrate data via the who is utility.  This was news to me.  So as we can see on the slide in the lulu debug log, if we execute this, the firewall will see the outgoing connection,  because again, it's global, it sees all network traffic.  However, because who is is signed by Apple proper and is not on the gray list, it will be allowed.  Now note this has been fixed.  I've basically added who is to the gray list.  And finally, we have little snitch.  Little snitch is the de facto most well-known firewall for Mac OS.  Turns out it has an undelatable rule that says any process can talk to iCloud.com domains or URLs.  This means any process, even malware, is allowed to talk to Apple servers.  To test this, we can manually create a deny rule for curl.  And then we can execute curl with an iCloud URL, and it is still allowed.  So a while back, I reverse engineered the iCloud protocol and built a CNC server on iDrive for testing purposes.  Don't get mad at me, Apple.  So it actually is a great drop box like CNC server, because you can get alerts when files are uploaded.  It's really great.  Once we understand the protocol, what we can do is write some custom code that we can use to exfiltrate data.  Now, even if little snitch is installed and sees the connection, it will be allowed because the endpoint we are talking to matches or maps to an iCloud domain.  Okay, so those were some product-specific bypasses.  Kind of neat, kind of funny.  But in my opinion, they're still a little bit lame.  And they're lame because first an attacker would have to enumerate and determine the specific firewall product that was installed, and then have one of these product-specific bypasses.  Way more powerful are generic bypasses, which can just bypass any installed firewall.  And these are all possible because the firewall is essentially disadvantaged.  It has to allow some network traffic off the box.  For example, trusted system daemons, or the user is probably going to fully allow certain things like browsers.  So the first thing we do to find a generic bypass is once we're on a system as a piece of malware or an attacker, is passively sniff to see what traffic is allowed off the box.  And we can do this via the LSOF utility.  So if we execute this on a box, even though I have my firewall installed, obviously there's going to be some traffic that is allowed out.  So for example, we can see browsers, chat applications, some Adobe licensing crap, et cetera, et cetera.  So now we know what traffic or what processes are allowed through the firewall.  So for the first generic bypass, we're going to indirectly exploit the trust of a process via a trusted protocol.  So on macOS, any time a DNS request is made, this is handled by Apple's MDNS responder.  This means if a random application or piece of malware tries to resolve a domain, the malware or the application actually does not generate the network request.  It's sent locally to the system daemon, which then on the application's behalf will resolve the domain.  So what malware can do is basically abuse this fact, because yes, again, the firewall is going to see this DNS resolution.  But since it's just a DNS request coming from the Apple sign trusted DNS daemon, which is handling all DNS requests for the entire system, the firewall is going to allow it.  So very easily, we can build a bi-directional command control protocol purely based on DNS.  Next up, let's talk about abusing browsers.  The simple fact is if you have a browser installed, it's going to be able to access the network.  Even if you maybe say only port 80 and 443, you're probably going to give it indiscriminate access to talk to any web server.  And again, we can passively determine this via LSOF.  So the first way we can abuse browsers is via AppleScript. So as we can see on the slide, we have kindly asked Safari to invisibly browse to an attacker-controlled URL.  And any data we want to exfiltrate, we can put in as a get parameter.  Again, the firewall will see this connection, but as it's Safari simply browsing to a URL, it will not be locked.  Now, an even better way to bypass any installed firewall is to abuse browsers' command line interfaces.  Really doesn't get any easier than this.  All major browsers now support a command line interface, so you can very easily programmatically execute them from a script, piece of malware, from the command line.  And again, the firewall will see this connection, but it's just the browser browsing to some URL, so it will not block it.  Yet another way to generically bypass all third-party firewall products is to simply inject a library or code into an application or a binary that the firewall trusts.  And again, via LSOF, we can determine passively what those are.  Now, once this code, this library, is running in that trusted process, from the firewall's point of view, it will also be given that same level of trust, and thus can access the network.  For example, if the browser is trusted and you inject code into the browser, and that malicious code connects out, the firewall will allow it because it just sees it's the browser.  Now, there's many ways on macOS to inject into especially third-party applications.  We don't have time to go into all of them, but I have listed them here on the slide.  The final way to bypass kernels involves, or firewalls rather, involves getting code into the kernel.  And the simple fact is, if an attacker is able to get code running in the kernel, it's completely game over for the firewalls.  First, a lot of firewalls will generically allow traffic that is originated from the kernel.  And, secondarily, if malicious code is running in the kernel, it can actually unregister or unhook any installed socket-filtered driver.  This will then transparently disable the firewall, and then the attacker's code, even from user mode, can connect out without having to worry about the firewall.  Okay, so let's start wrapping this all up.  So today we talked about building a firewall for macOS.  We saw that using a socket-filter kernel extension, really not that complicated.  As I mentioned, the source code for Lulu is on GitHub, so if you're interested in more of the details and specifics, I would recommend checking that out.  We then talked about breaking firewalls.  We showed that a lot of them actually have significant security flaws, which are very problematic because the firewalls often run with root privileges or even in the kernel.  And then we also showed that the unfortunate reality is these products are all trivial to generically bypass.  Now, this doesn't mean we should uninstall our firewall products, but I think it makes a good case for a defense-in-depth strategy.  For example, maybe some other host-based security products that can perhaps block some of the prerequisites for these attacks.  For example, preventing die-lib injection, or perhaps can detect that the browser is running from the command line when the user isn't active.  Like, that's not something a firewall should detect, per se, but perhaps another security tool should.  And finally, today I'm really excited to announce a brand new Mac Security conference called Objective By The Sea.  We have a really cool lineup of Mac Security researchers.  It's also going to be at this awesome resort in Hawaii.  And if you're a supporter of Objective Sea, which you can be for $1, the conference to attend is completely free.  I just want to reiterate that it's in Hawaii.  This is the actual resort of where it's going to be, November 3rd and 4th.  So I would love if you could all attend.  And for more information, check out ObjectiveByTheSea.com.  Okay, that's a wrap.  I really want to thank you all for attending.  Also, I want to thank the partners of Objective Sea, which are Digita Security and Mauerbytes.  And we have 13 seconds for questions.  But I will be around here after the talk to obviously answer any other questions.  Thank you.
DEF_CON_26_-_Patrick_Wardle_-_Fire_and_Ice_Making_and_Breaking_macOS_Firewalls_UlT5KFTMn2k_0_1211.png DEF_CON_26_-_Patrick_Wardle_-_Fire_and_Ice_Making_and_Breaking_macOS_Firewalls_UlT5KFTMn2k_1212_3467.png DEF_CON_26_-_Patrick_Wardle_-_Fire_and_Ice_Making_and_Breaking_macOS_Firewalls_UlT5KFTMn2k_3468_4007.png DEF_CON_26_-_Patrick_Wardle_-_Fire_and_Ice_Making_and_Breaking_macOS_Firewalls_UlT5KFTMn2k_4008_5267.png DEF_CON_26_-_Patrick_Wardle_-_Fire_and_Ice_Making_and_Breaking_macOS_Firewalls_UlT5KFTMn2k_5268_7715.png DEF_CON_26_-_Patrick_Wardle_-_Fire_and_Ice_Making_and_Breaking_macOS_Firewalls_UlT5KFTMn2k_7716_8375.png DEF_CON_26_-_Patrick_Wardle_-_Fire_and_Ice_Making_and_Breaking_macOS_Firewalls_UlT5KFTMn2k_8376_11483.png DEF_CON_26_-_Patrick_Wardle_-_Fire_and_Ice_Making_and_Breaking_macOS_Firewalls_UlT5KFTMn2k_11484_11567.png DEF_CON_26_-_Patrick_Wardle_-_Fire_and_Ice_Making_and_Breaking_macOS_Firewalls_UlT5KFTMn2k_11568_13043.png DEF_CON_26_-_Patrick_Wardle_-_Fire_and_Ice_Making_and_Breaking_macOS_Firewalls_UlT5KFTMn2k_13044_15191.png DEF_CON_26_-_Patrick_Wardle_-_Fire_and_Ice_Making_and_Breaking_macOS_Firewalls_UlT5KFTMn2k_15192_16895.png DEF_CON_26_-_Patrick_Wardle_-_Fire_and_Ice_Making_and_Breaking_macOS_Firewalls_UlT5KFTMn2k_16896_18515.png DEF_CON_26_-_Patrick_Wardle_-_Fire_and_Ice_Making_and_Breaking_macOS_Firewalls_UlT5KFTMn2k_18516_20183.png DEF_CON_26_-_Patrick_Wardle_-_Fire_and_Ice_Making_and_Breaking_macOS_Firewalls_UlT5KFTMn2k_20184_21155.png DEF_CON_26_-_Patrick_Wardle_-_Fire_and_Ice_Making_and_Breaking_macOS_Firewalls_UlT5KFTMn2k_21156_24407.png DEF_CON_26_-_Patrick_Wardle_-_Fire_and_Ice_Making_and_Breaking_macOS_Firewalls_UlT5KFTMn2k_24408_25031.png DEF_CON_26_-_Patrick_Wardle_-_Fire_and_Ice_Making_and_Breaking_macOS_Firewalls_UlT5KFTMn2k_25032_26147.png DEF_CON_26_-_Patrick_Wardle_-_Fire_and_Ice_Making_and_Breaking_macOS_Firewalls_UlT5KFTMn2k_26148_26651.png DEF_CON_26_-_Patrick_Wardle_-_Fire_and_Ice_Making_and_Breaking_macOS_Firewalls_UlT5KFTMn2k_26652_27179.png DEF_CON_26_-_Patrick_Wardle_-_Fire_and_Ice_Making_and_Breaking_macOS_Firewalls_UlT5KFTMn2k_27180_29591.png DEF_CON_26_-_Patrick_Wardle_-_Fire_and_Ice_Making_and_Breaking_macOS_Firewalls_UlT5KFTMn2k_29592_29795.png DEF_CON_26_-_Patrick_Wardle_-_Fire_and_Ice_Making_and_Breaking_macOS_Firewalls_UlT5KFTMn2k_29796_30161.png
All right, Aloha, and welcome to my talk on making and breaking Mac firewalls. My name is Patrick. I work at Digital Security, where we are creating cybersecurity tools for the Mac enterprise. I'm also the creator of the Mac security website, Objective C. Woo! So today, thank you, thank you, we're going to be talking about creating or making a Mac firewall. And then we're going to kind of shift gears and talk about breaking and bypassing such products. So about a year ago, I decided I wanted to write a firewall for Mac OS because there were no free open source options. So in this section of the talk, we'll describe this process, creating Lulu, which is my free open source Mac firewall. Now, there are many reasons you might want to create or install a firewall. They're actually pretty good security tools. Probably the two main reasons are one, to protect your privacy or two, to thwart cyber attacks, because most firewalls are able to generically detect malware when the malware connects out, perhaps to expiltrate data or connect to a command and control server for tasking. So what our firewall is going to do is monitor all network traffic, allowing traffic out that's trusted and ideally blocking or prevented unauthorized or malicious traffic. Now, since we're going to need to monitor all traffic globally, we're going to have to write a kernel extension. In Mac OS, Apple provides network kernel extensions, or NKEs, as a way to extend or modify the network infrastructure. And one type of NKE is a socket filter, which, as its name suggests, allows code to filter network traffic at the socket level, which for a firewall is perfect. That's exactly what we need. Now, there are two steps to register a socket filter. First, we populate a socket filter structure. And this structure contains various callbacks that, once registered, will be automatically invoked by the operating system on certain socket operations, which then gives our firewall the ability to examine these socket actions and determine whether they should be allowed or blocked. So the second step is then to invoke the socket filter register function to install your socket filter. Now, besides the populated structure, this also takes a socket domain type and protocol, which means if you want to filter all socket domains, types, and protocols, you should invoke this method or function several times. OK, so now let's talk about these callbacks, which, as I mentioned, once your socket filter is registered, will be automatically invoked by the operating system on socket events. The first callback is the attached callback, and as we can see on the slide, it will be invoked any time a new socket is created. So it's created with a cookie parameter that's designed to hold any socket-specific information. You can really put whatever you want there. So what we do is we allocate a chunk of memory, and based on the PID of the process that's creating the socket, we either set it to allow, for example, if it's a trusted system daemon, or block if it's a process that the user has chosen to block. Now, if it's a process we don't recognize, we set this action to ask, and then we're going to have to do some extra logic to determine what action to take. So next is the connect out callback. This is called before initiating an outgoing connection. Again, it takes the same cookie, which we've set to either allow, block, or ask, and the socket and the remote address that the socket is trying to connect to. So this obviously allows us to examine the endpoint. Now, if the action has been set to allow, we just return OK. This tells the operating system we are OK with allowing this connection to continue. If it's set to block, we return an error code from this function, which tells the operating system we want to block or not allow the connection. And if it's set to ask, we have to execute some extra logic to determine what action to take. So in other words, we have to figure out whether to allow or block the connection. So what we do is we first put the thread to sleep that's trying to perform the socket operation. This will pause the action. We then ask our user mode firewall component for assistance. And we pass the information from the kernel, specifically the PID and the socket via a shared queue. Once the daemon gets this request from the kernel socket filter, it maps the PID to a path and first checks a rules database to see if that path is in the database. If it's not found, perhaps it's a brand new application or a piece of malware that has somehow gotten onto your system, what it does is it sends a message to another firewall component that's running in the user's session. And this is what actually displays the firewall alert to the user. Now, the user's response, they'll either have to click allow or block, will then be passed back to the daemon. The daemon will save this response to the rules database, so moving forward, it knows what to do, and then also sends this response back to the kernel component via an IO kit interface. The kernel extension will then wake up the thread that was put to sleep and then apply the action, either allowing the connection or blocking it. So that's basically all that's needed to create a comprehensive firewall for macOS. And putting this all together, we have Lulu. As I mentioned, Lulu is a free firewall, I don't think, and users should have to pay for security products. And also, the full source for the firewall is online on GitHub. And as of today, you can download and install version 1.0. Awesome. Thank you. Free-friendly audience today. I really like this. All right, so Defcon, in my opinion, is predominantly a hacker conference about breaking things and exploits and vulnerabilities. So let's kind of switch gears and talk about now breaking and bypassing such firewall products. So imagine you're an attacker or a piece of malicious code that has somehow made it onto an end system. Unfortunately, there's a firewall that's installed. So if you are going to connect out, perhaps to exfiltrate data or connect to a command and control server, the firewall is going to detect and block this. So your goal is simple. How can you connect out without the firewall blocking this data? So in this section, we'll first look at some firewall-aware malware. We'll then look at some security vulnerabilities in firewall products and then end with ways to completely bypass the firewalls. So first, it's definitely important for malware or an implant to detect if a firewall is installed on the box. Otherwise, it really might be there undoing, as the firewall may detect a previously undetected malware when it tries to connect out. And as we can see on the slide, this has happened. Now, I've yet to see any public Mac malware that tries to specifically bypass Mac firewalls, but there are some specimens that are firewall-aware. And what I mean by that is they will enumerate installed processes or look specifically for firewalls, and if they see an installed firewall, they will not persistently infect that system. One example of this is Devil Robber. And what Devil Robber did is it looked for little snitch, which is a popular Mac firewall. If that was installed, it would not infect the system. It would just execute a benign instance of the application it had infected and then simply exit. Okay, now onto some security issues. Software such as firewalls often very complex, and firewalls often run with elevated privileges or even in the kernel. Now, unfortunately, they're not as well written as the operating system, nor have been audited as well, which makes them excellent targets for local privilege vulnerabilities. So I talked about this bug at DefCon a while ago, but just briefly to go over, it's kind of a neat kernel bug that affected the little snitch firewall kernel extension. Basically, the firewall extension took a 64-bit value from user mode and used that in an allocation and a copy routine. Unfortunately, the allocation routine expected a 32-bit value, so it truncated that. However, the copy routine expected a full 64-bit value, so it allowed us to have a controllable mismatch between the allocation and then the copy routine, which led to an exploitable heap overflow in the kernel, allowing us to execute arbitrary code in ring zero. Another issue I found while briefly looking at little snitch affected its installer and updater component. In short, the firewall installer did not validate the components it was going to install. So a local unprivileged attacker could modify these components, and then the firewall installer or updater would naively install and execute them as root, again, giving a local unprivileged attacker a very reliable way to elevate their privileges. All right, now on to bypassing firewalls. We'll first look at some product-specific bypasses, but then we'll also look at some more powerful generic ones that can bypass all third-party firewalls. Again, the goal here is network access without being blocked. Now, I do want to reiterate that, in my opinion, these bypasses are not security issues per se, like they don't deserve a CVE, but, however, they're still very valuable, especially for an attacker or piece of malware, which may otherwise be thwarted by the firewall. So first up, we have radio silence. It's a popular firewall for macOS. It kind of takes an interesting approach in that it allows any new process, but the user can explicitly blacklist certain applications. However, if we look at the blacklisting logic in the kernel extension, we can see it looking for a name of a process, and it appears if the process is named launchD, it cannot be blacklisted nor blocked. So let's test this. We take some malware. We name it launchD. Again, the path doesn't matter, just the name. And then we manually create a rule to blacklist this process. We then run it, and as we can see on the slide, it's still allowed out, because, again, it is named launchD. So kind of lame, but, again, fully bypasses this firewall. Another popular mac firewall is named handsoff, and it turns out that we can pretty easily bypass this via a synthetic click. So for example, if we execute curl, which is something that mac malware often does, for example, to download additional components, as expected, the firewall will detect this unauthorized activity and display an alert. What the attacker or malware can then do is send a programmatic synthetic click to that allow button, which will click the allow button, basically hiding the alert and allowing the connection. And it also turns out there are ways you can do this without the user noticing. So there are ways that you can do this invisibly so that the user is not going to see the alert and the synthetic mouse click. Next up, we have lulu. By default, lulu trusts Apple binaries. Yeah, I'm picking on everyone including my own tools. I think it's only fair. So lulu by default trusts Apple signed processes. However, it gray lists certain Apple binaries, which could potentially be abused for malicious activity. So, for example, netcat and curl, even those are signed by Apple, it will still alert anytime anybody executes them. So the question is, can we find another signed Apple utility that is not on the gray list? And the answer is yes. Turns out you can exfiltrate data via the who is utility. This was news to me. So as we can see on the slide in the lulu debug log, if we execute this, the firewall will see the outgoing connection, because again, it's global, it sees all network traffic. However, because who is is signed by Apple proper and is not on the gray list, it will be allowed. Now note this has been fixed. I've basically added who is to the gray list. And finally, we have little snitch. Little snitch is the de facto most well-known firewall for Mac OS. Turns out it has an undelatable rule that says any process can talk to iCloud.com domains or URLs. This means any process, even malware, is allowed to talk to Apple servers. To test this, we can manually create a deny rule for curl. And then we can execute curl with an iCloud URL, and it is still allowed. So a while back, I reverse engineered the iCloud protocol and built a CNC server on iDrive for testing purposes. Don't get mad at me, Apple. So it actually is a great drop box like CNC server, because you can get alerts when files are uploaded. It's really great. Once we understand the protocol, what we can do is write some custom code that we can use to exfiltrate data. Now, even if little snitch is installed and sees the connection, it will be allowed because the endpoint we are talking to matches or maps to an iCloud domain. Okay, so those were some product-specific bypasses. Kind of neat, kind of funny. But in my opinion, they're still a little bit lame. And they're lame because first an attacker would have to enumerate and determine the specific firewall product that was installed, and then have one of these product-specific bypasses. Way more powerful are generic bypasses, which can just bypass any installed firewall. And these are all possible because the firewall is essentially disadvantaged. It has to allow some network traffic off the box. For example, trusted system daemons, or the user is probably going to fully allow certain things like browsers. So the first thing we do to find a generic bypass is once we're on a system as a piece of malware or an attacker, is passively sniff to see what traffic is allowed off the box. And we can do this via the LSOF utility. So if we execute this on a box, even though I have my firewall installed, obviously there's going to be some traffic that is allowed out. So for example, we can see browsers, chat applications, some Adobe licensing crap, et cetera, et cetera. So now we know what traffic or what processes are allowed through the firewall. So for the first generic bypass, we're going to indirectly exploit the trust of a process via a trusted protocol. So on macOS, any time a DNS request is made, this is handled by Apple's MDNS responder. This means if a random application or piece of malware tries to resolve a domain, the malware or the application actually does not generate the network request. It's sent locally to the system daemon, which then on the application's behalf will resolve the domain. So what malware can do is basically abuse this fact, because yes, again, the firewall is going to see this DNS resolution. But since it's just a DNS request coming from the Apple sign trusted DNS daemon, which is handling all DNS requests for the entire system, the firewall is going to allow it. So very easily, we can build a bi-directional command control protocol purely based on DNS. Next up, let's talk about abusing browsers. The simple fact is if you have a browser installed, it's going to be able to access the network. Even if you maybe say only port 80 and 443, you're probably going to give it indiscriminate access to talk to any web server. And again, we can passively determine this via LSOF. So the first way we can abuse browsers is via AppleScript. So as we can see on the slide, we have kindly asked Safari to invisibly browse to an attacker-controlled URL. And any data we want to exfiltrate, we can put in as a get parameter. Again, the firewall will see this connection, but as it's Safari simply browsing to a URL, it will not be locked. Now, an even better way to bypass any installed firewall is to abuse browsers' command line interfaces. Really doesn't get any easier than this. All major browsers now support a command line interface, so you can very easily programmatically execute them from a script, piece of malware, from the command line. And again, the firewall will see this connection, but it's just the browser browsing to some URL, so it will not block it. Yet another way to generically bypass all third-party firewall products is to simply inject a library or code into an application or a binary that the firewall trusts. And again, via LSOF, we can determine passively what those are. Now, once this code, this library, is running in that trusted process, from the firewall's point of view, it will also be given that same level of trust, and thus can access the network. For example, if the browser is trusted and you inject code into the browser, and that malicious code connects out, the firewall will allow it because it just sees it's the browser. Now, there's many ways on macOS to inject into especially third-party applications. We don't have time to go into all of them, but I have listed them here on the slide. The final way to bypass kernels involves, or firewalls rather, involves getting code into the kernel. And the simple fact is, if an attacker is able to get code running in the kernel, it's completely game over for the firewalls. First, a lot of firewalls will generically allow traffic that is originated from the kernel. And, secondarily, if malicious code is running in the kernel, it can actually unregister or unhook any installed socket-filtered driver. This will then transparently disable the firewall, and then the attacker's code, even from user mode, can connect out without having to worry about the firewall. Okay, so let's start wrapping this all up. So today we talked about building a firewall for macOS. We saw that using a socket-filter kernel extension, really not that complicated. As I mentioned, the source code for Lulu is on GitHub, so if you're interested in more of the details and specifics, I would recommend checking that out. We then talked about breaking firewalls. We showed that a lot of them actually have significant security flaws, which are very problematic because the firewalls often run with root privileges or even in the kernel. And then we also showed that the unfortunate reality is these products are all trivial to generically bypass. Now, this doesn't mean we should uninstall our firewall products, but I think it makes a good case for a defense-in-depth strategy. For example, maybe some other host-based security products that can perhaps block some of the prerequisites for these attacks. For example, preventing die-lib injection, or perhaps can detect that the browser is running from the command line when the user isn't active. Like, that's not something a firewall should detect, per se, but perhaps another security tool should. And finally, today I'm really excited to announce a brand new Mac Security conference called Objective By The Sea. We have a really cool lineup of Mac Security researchers. It's also going to be at this awesome resort in Hawaii. And if you're a supporter of Objective Sea, which you can be for $1, the conference to attend is completely free. I just want to reiterate that it's in Hawaii. This is the actual resort of where it's going to be, November 3rd and 4th. So I would love if you could all attend. And for more information, check out ObjectiveByTheSea.com. Okay, that's a wrap. I really want to thank you all for attending. Also, I want to thank the partners of Objective Sea, which are Digita Security and Mauerbytes. And we have 13 seconds for questions. But I will be around here after the talk to obviously answer any other questions. Thank you.
creating cybersecurity tools for the Mac options. So in this section of the talk, we'll many reasons you might want to create or install attacks, because most firewalls are able to extension. In Mac OS, Apple provides network of NKE is a socket filter, which, as its name which then gives our firewall the ability to it takes the same cookie, which we've set to examine the endpoint. Now, if the action has been what action to take. So in other words, we have comprehensive firewall for macOS. And putting should have to pay for security products. And also, the full source for the firewall is online you're an attacker or a piece of malicious code to detect and block this. So your goal is simple. firewall products and then end with ways to are some specimens that are firewall-aware. And such as firewalls often very complex, and little snitch firewall kernel extension. have a controllable mismatch between the attacker could modify these components, and then attacker or piece of malware, which may otherwise be thwarted by the firewall. So first up, we have However, if we look at the blacklisting logic in the kernel extension, we can see it looking for a we can pretty easily bypass this via a synthetic Apple proper and is not on the gray list, it will URLs. This means any process, even malware, is process via a trusted protocol. So on macOS, any to bypass kernels involves, or firewalls rather, involves getting code into the kernel. And the from the kernel. And, secondarily, if malicious these products are all trivial to generically another security tool should. And finally, today