
Kernel RCE in iOS/macOS with ICMP - dogecoinbase
https://lgtm.com/blog/apple_xnu_icmp_error_CVE-2018-4407
======
jerf
The Ping of Death rides again!

Ok, yeah, not exactly the same, but humor me. It's a Halloween undead miracle!

------
cesarb
The worst part, is that you just known some sysadmins are going to use this as
an excuse to block all ICMP, worsening the PMTU blackhole problem; and the
"these ICMP bugs were all from the 90s" argument won't work anymore.

~~~
jsjohnst
Except this isn’t triggered with an ICMP packet. All it takes to trigger the
crash is a specially formatted TCP packet.

------
saagarjha
TL;DR: Heap buffer overflow in the network stack allowed for sending ICMP
packets that would crash devices. Bug was marked as "RCE" because it's
possible that it could be used for code execution, though the current PoC only
causes a crash. Bug has been reported to Apple and fixed in iOS 12 and macOS
Mojave 10.14. There's an excellent drawing by the author at the end of the
author summarizing the exploit ;)

As an aside:

> Even on a Mac, XNU is highly non-trivial to build.

I find it to be an extremely sad state of affairs when it requires scouring
the internet for a blog post from a Darwin engineer to build an outdated XNU
:(

~~~
pcwalton
> I find it to be an extremely sad state of affairs when it requires scouring
> the internet for a blog post from a Darwin engineer to build an outdated XNU
> :(

Large projects at companies tend to be hard to build, simply because it takes
a lot of effort to make the build system for something so complex easy. If
community contributions aren't particularly valued (which they aren't for
XNU), then it's hard to internally justify spending the effort. Linux hackers
are spoiled…

XNU isn't even one of the worst offenders. Try compiling Google's Skia, for
example…

~~~
lunixbochs
Really? I found Skia easier to compile than actually use.

~~~
pjmlp
One needs to duplicate Google's build infrastructure, which is quite a pain
versus other open source projects that rely on more mainstream tooling.

~~~
hoaw
Which would be fine if they provided some straight forward way to replicate
that (like a container). It really seems like open source doesn't have that
high of a standing at Google (anymore?). I guess limiting hardware
manufacturers use of open source, not spending time making sure other people
can build open source code, is what gives you the promotion these days

------
pjmlp
Another day, another buffer overflow caused by C's memory model.

At least ARM is getting pointer tagging.

~~~
int0x80
Caused by Apple copy pasting networking BSD code, missing a crucial bounds
check in the process (as noted by another reply ITT).

Here:
[https://news.ycombinator.com/item?id=18351533](https://news.ycombinator.com/item?id=18351533)

~~~
pjmlp
Which in a language with bounds checking would usually mean a panic instead of
a memory corruption leading to possible exploit.

Unless the same mistake would have been done inside an _unsafe_ code
block/module.

If anything, C's history of memory corruption errors and how they come to be,
proves that even the best aren't able to follow best practices that apparently
all good C coders do.

Linux kernel is full of such CVEs in spite of the approval processes in place
to accept new code into the kernel, and I assume Apple does have similar
practices in place.

~~~
int0x80
Yeah. C gives you little safety nets. But the problem here is a missing check.
Do the same (logic mistakes) in Rust, Java, C#, JavaScript etc and you will,
sooner or later, give access to your admin account, to your DB, to a command
shell or to memory, writting not permitted values by omiting a validation
check etc.

I see your point, and I agree partly, some languages can avoid the particular
secuence of events in this bug or make it more difficult.

In this case, imagine:

\- Sloppiness getting code into the icmp module (this is speculation, to be
fair).

\- Buffer overrun leading to RCE.

\- Solution:

    
    
      1 You rewrite in rust because you think the root cause is that C is unsafe.
    
      2 You don't write sloppy code, higher your standars, more audit/testing/verification.
    
    

To me, if you don't fix #2, you are going to have big problems anyway even if
you have safer tools.

~~~
pjmlp
That is the typical defense argument I keep getting from C crowd since the
mid-90's.

The thing is,

Σ logic errors < Σ logic errors + Σ memory corruption errors

So while errors don't go away, the exploit area is considerably dimished.

Naturally it gets hand waved as errors are errors.

Which is why I really do look forward for harder lawsuits when security
exploits happen.

When money starts speaking, more companies will take security more seriously.

~~~
int0x80
Fine. I agree. Less is better. Now, I don't want to have a c vs rust like
discussion, I think we will agree in fact mostly.

But, all I was saying in the beginning (and I later digressed) is that just
blaming 'C memory model' is not fair.

(Dramatization) "Hey, boss, yes... an RCE, what a pitty. Yeah, missing check.
But don't blame me. Is C it is at fault". That is just not
realistic/ridiculous. Is like saying is the parents of Denis Ritchie that are
at fault here.

~~~
pjmlp
It is fair blaming C memory model because safer systems programming languages
exist since 1961, and C only got where it is thanks for Bell Labs not being
able to sell UNIX for the first 10 years of its existence.

Even Multics had less exploits than earlier UNIX versions, as stated on a DoD
report about inexistence of memory corruption issues thanks to PL/I.

If you bother to read the early C history document written by Richie, they
were aware of such shortcomings and thus lint was born in 1979.

A tool that to this day many devs still ignore.

As for alternative languages I haven't named a single one on this thread.
There are plenty to chose from since 1961.

~~~
int0x80
Interesting, I will read the article, thanks for mentioning it.

As for alternatives, I was just giving examples, you didn't say anything yes.

------
walrus01
How long until somebody builds a device that is basically a pwnplug, which
joins wifi networks at major tech conferences, does an nmap for live IPs, and
sends this to every device?

~~~
kiallmacinnes
As an aside, well ran conference WiFi (and public WiFi in general) won't allow
attendees to contact each other over the WiFi network - they will only allow
traffic from end user devices towards the gateway, and won't allow hairpin
routing on that gateway.

I wish more public WiFi was well ran, as many of these same network attacks
wouldn't have an opportunity to work in the first place.

~~~
pjmlp
Many public WiFis are managed by people buying some routers at the local store
and plugging them in.

------
swang
Does this affect all version of iOS before 12? Seems like some old iphones may
fall out of use then if they're vulnerable.

~~~
Klover
Correct. iOS 11 devices can update to iOS 12, older devices are vulnerable.

------
unixpickle
Reproduced the bug in Golang. Pretty simple stuff.
[https://github.com/unixpickle/cve-2018-4407](https://github.com/unixpickle/cve-2018-4407)

------
petre
Is there a fix for older OSX or should I just install Linux on my 2011 iMac?
Yosemite is already quite slow. OpenSuSE 13.2 was really fast on a same
generation Mac Mini.

~~~
galad87
If you are behind a NAT, you won't receive ping from the Internet, so you are
safe. And you can enable the firewall and "stealth mode" to make it ignore
local pings.

Your 2011 iMac can be update to 10.13, so I would update, a iMac 2011 with
enough ram and a ssd works very well even on 10.13.

~~~
jsjohnst
Except it’s not a received ICMP packet that triggers the issue, it’s a TCP
packet with large IP and TCP options. The crash occurs because the XNU kernel
is sending an ICMP error in response to that received TCP packet.

------
wepple
Can someone explain to me, did I miss the description of the actual bug here?
I get there’s a copy, but why is there an under-allocation to start with? Or
is that alloc somehow attacker-controlled? Was part of the copy func args
controllable? Or was this just an ad?

~~~
geogriffin
Pretty sure it was introduced here: [https://github.com/apple/darwin-
xnu/commit/c10988c130af09087...](https://github.com/apple/darwin-
xnu/commit/c10988c130af090877998fa56ed842575b841ff8#diff-9e767463d3d961f80f454adb3cdd9da3R279)

In this commit a bunch of code was copy-pasted from BSD into ip_icmp.c in
icmp_error() to quote IP packet data in icmp error responses. Unfortunately
they forgot to copy a line from the BSD source which would prevent the
overflow:

    
    
      icmplen = min(icmplen, M_TRAILINGSPACE(m) - sizeof(struct ip) - ICMP_MINLEN);
    

m is allocated with a fixed-length buffer (mbuf), which means without that
line above we can overrun it:

    
    
      m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
    

Copy-paste programming in core networking code...

~~~
sigjuice
> Copy-paste programming in core networking code...

There is nothing special about _core networking code_.

~~~
pjmlp
Other than being highly security sensitive, written in a language without any
regard for security.

------
PeterLGummybear
The XNU networking stack is complete garbage in general. Have you ever seen
all the crazy hard-coded stuff they have for different types of network
mediums -- wifi vs cellular vs etc -- and in the kernel? It's bonkers. Plus a
weird evolution of firewalls and ugh.

------
sigjuice
This looks like a mundane bug and there are countless other undiscovered bugs
like this. It doesn’t deserve this huge essay IMHO.

~~~
TheDong
Remotely exploitable buffer overflows in kernels are fairly rare.

> there are countless other undiscovered bugs like this

How do you know that they exist if they're undiscovered?

At this point, there are probably very few in linux after the level of fuzzing
its received.

~~~
wahern
> At this point, there are probably very few in linux after the level of
> fuzzing its received.

Linux is _heavily_ developed, which means significant code churn. It's a
victim of its own success.

And there's much less fuzzing happening than you think. It's an on-again, off-
again activity; not something that any particular organization (AFAIK) is
rigorously and repeatedly performing on Linux for any serious length of time
(i.e. years). Fuzzing isn't an automatic thing; it requires human intervention
to help craft the tests so they reach and tickle the right corner cases. And
if the code is constantly changing, you need to constantly review your tests.

Also, syscall fuzzing must be done differently from network fuzzing, for
example. And fuzzing kernels in general is more difficult than, e.g., a self-
contained library.

If you look at the Linux kernel CVEs, they've been steadily _increasing_ over
time:
[https://www.cvedetails.com/product/47/](https://www.cvedetails.com/product/47/)
We can quibble over the causes and significance, but I don't think those data
points support your argument.

Yes, remote exploits in Linux are rare, just as they're rare in most operating
systems, including macOS and Windows. But not rare enough. And there's little
indication that they're becoming _more_ rare. Unfortunately, I'll bet that the
shift to eBPF to implement basic filtering and routing will cause a spike over
the next few years.

At this point the Linux kernel is a lost cause. Everybody serious about
security understands that the future is moving your most sensitive assets to
secure enclaves _not_ running general purpose OSs like Linux. Unfortunately
those enclaves are recapitulating the same mistakes--too many features, too
flexible, too much emphasis on adding more complexity to try to fix things.
But one thing is certain, Linux is definitely _not_ getting any simpler, and
people are moving assets to slower moving train wrecks.

~~~
TheDong
> If you look at the Linux kernel CVEs, they've been steadily increasing over
> time [...] I don't think those data points support your argument.

The number of CVEs don't support _any_ argument really. More CVEs are
assigned, yes. That doesn't mean more security issues. In the olden days of 8
years ago, a buffer overflow would be patched with no fanfare and no CVE
assigned. Nowadays, often only theoretically exploitable issues will still be
given a CVE.

