Mac OS X 10.10.2: Information leak from discoveryd ('s address space) caused by valid DNS server responses

Originator:weissismail
Number:rdar://20171408 Date Originated:16-Mar-2015 11:49 AM
Status:Open Resolved:
Product:OS X Product Version:Mac OS X 10.10.2 (14C1510)
Classification:Security Reproducible:Always
 
Summary:
========

There seems to be an information leak from the system wide daemon (LaunchDaemon) /usr/libexec/discoveryd to arbitrary user processes. The information seems to be leaked through the CNAME (((struct addrinfo *)info)->ai_canonname field) returned from eg. getattrinfo(3). The program using getaddrinfo can receive data which looks very much like arbitrary (specially escaped) address space content from discoveryd.

The problem in discoveryd seems to be that doesn't handle DNS message compression correctly (see section "4.1.4. Message compression" in RFC 1035 [1]). It does handle message compression pointers to ordinary DNS labels correctly however it seems to fail if DNS message compression pointers point to other DNS message compression pointers.

Example:

Assuming a DNS query to mail.aYa.com, a DNS server might respond with

000  7e 6d 81 80 00 01 00 02  00 00 00 00 04 6d 61 69  |~m...........mai|
010  6c 03 61 59 61 03 63 6f  6d 00 00 01 00 01 c0 0c  |l.aYa.com.......|
020  00 05 00 01 00 00 0e 0e  00 02 c0 11 c0 2a 00 01
030  00 01 00 00 0e 0e 00 04  7f 00 00 01

This response contains a CNAME record (bytes 0x1e to 0x2b in the whole packet above):

c0 0c 00 05 00 01 00 00 0e 0e 00 02 c0 11

It's not that interesting, the only interesting thing is that the byte sequence "c0 11" references byte 0x11 in the packet to refer to the CNAME. The bytes starting at 0x11 are "03 61 59 61 03 63 6f 6d 00 00" which corresponds to "aYa.com". So name compression worked well and saved a couple of bytes.

The response does also contain an A record (bytes 0x2c to 0x3d in the packet above):

c0 2a 00 01 00 01 00 00 0e 0e 00 04 7f 00 00 01

The A record is a bit more interesting because it's name (again "aYa.com") doesn't reference the initial reference of "aYa.com" directly but references the CNAME we saw earlier at bytes 0x2a. Again, the CNAME field is "c0 11" which is a reference to "aYa.com".

So the A record's name references the CNAME which references the actual labels.

It turns out, discoveryd doesn't not seem to cope well with recursive DNS name compression pointers.

The problem is also illustrated in the attached image packet-picture.png (also available [4]).

This ticket contains an example DNS server that reproduces this problem for every domain on every request. Most DNS servers we have tested do not exhibit this problem (as they don't seem to use recursive DNS name compression pointers). We have however seen one real DNS server that triggered this problem repeatedly in OS X Yosemite. The DNS server triggering that problem is a Microsoft Windows 2008 R2 DNS Server (Active Directory).


Steps to Reproduce:
===================

1. Download the attached program `pydns.py` (also available at [2]) which is a DNS server which replies with packets as described above, always pointing to 127.0.0.1
2. Run it as root (`sudo python pydns.py`)
3. Configure the only DNS server in the system to be "127.0.0.1"
4. Run `ping -c1 mail.aYa.com`

Comments

PART 2 (because Apple's Radar is limited to 3000 characters)

Expected Results:

Something similar to the output below should be written to the terminal --- SNIP --- $ ping -c1 mail.aYa.com PING aYa.com (127.0.0.1): 56 data bytes 64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.038 ms

--- aYa.com ping statistics --- 1 packets transmitted, 1 packets received, 0.0% packet loss round-trip min/avg/max/stddev = 0.038/0.038/0.038/0.000 ms --- SNAP ---

Actual Results:

The precise result varies but I just got

--- SNIP --- $ ping -c1 mail.aYa.com PING 017?*000nnes-macbook-pro005local000000000000000p028?ʕ000000????????@000000000`032000000h028?ʕ000000p028?ʕ000000?k?ʕ0000000k?ʕ000000032??ʕ000000hk?ʕ000000p0110018001000000000?mϐ?000000?004???00000 (127.0.0.1): 56 data bytes 64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.038 ms

--- 017?*000nnes-macbook-pro005local000000000000000p028?ʕ000000????????@000000000`032000000h028?ʕ000000p028?ʕ000000?k?ʕ0000000k?ʕ000000032??ʕ000000hk?ʕ000000p0110018001000000000?mϐ?000000?004???00000 ping statistics --- 1 packets transmitted, 1 packets received, 0.0% packet loss round-trip min/avg/max/stddev = 0.038/0.038/0.038/0.000 ms --- SNAP ---

ping will print the CNAME after the "PING" string, it should be "aYa.com" but it is the garbage up there.

Please also note that my computer's name is "johannes-macbook-pro" and you can for example see the "nnes-macbook-pro" part appearing in the leaked memory bits.

Regression:

Yes, not noticed on 10.9.x and below.

Notes:

1.

Please also find attached a program getaddrinfo-test.c (also available at [3]) that can be compiled using clang -o getaddrinfo-test getaddrinfo-test.c that can be used to print the CNAME and other information.

In a working environment getaddrinfo-test mail.aYa.com would return something like

--- SNIP --- $ ./getaddrinfo-test mail.aYa.com mail.aYa.com: ptr: 0x7fcd8ac05740, aya.com flags: 0x00000000 CANON NAME len 7 'aya.com' A 202.181.97.43 --- SNAP ---

with the specially crafted pydns.py server results like this happen:

--- SNIP --- $ ./getaddrinfo-test mail.aYa.com mail.aYa.com: ptr: 0x7f99707006f0, 017?*000000?*.000008016001000000000000000000000000000000000002s3009amazonaws003com000ߕ?000000008000000000000000000000p013??\000\000\000\000\000\000\000\000\000\000??\007\016\001\000\000\000\016\000\000\0000\000\000\000pv?\018\001\000\000\000u?018001000000000?003???000000??z?a?000"4c001000000000000000?v?018001000000000;??015001000000000000p009016001000000000?0110080160010000000000040000000004c001000ӓ?0150010000000004c001000002000000000googl000000000024 flags: 0x00000000 CANON NAME len 556 '017?*000000?*.000008016001000000000000000000000000000000000002s3009amazonaws003com000ߕ?000000008000000000000000000000p013??\000\000\000\000\000\000\000\000\000\000??\007\016\001\000\000\000\016\000\000\0000\000\000\000pv?\018\001\000\000\000u?018001000000000?003???000000??z?a?000"4c001000000000000000?v?018001000000000;??015001000000000000p009016001000000000?0110080160010000000000040000000004c001000ӓ?0150010000000004c001000002000000000googl000000000024' BROKEN!!! GREP-MARKER-XXX: 5c303137c02a5c3030305c303030c02a5c2e5c3030305c3030385c3031365c3030315c3030305c3030305c3030305c3030305c3030305c3030305c3030305c3030305c3030305c3030305c3030305c30303273335c303039616d617a6f6e6177735c303033636f6d5c303030df95ff7f5c3030305c3030305c3030385c3030305c3030305c3030305c3030305c3030305c3030305c303030705c3031336089ff7f5c3030305c3030305c3030305c3030305c3030305c3030305c3030305c3030305c3030305c303030c0ef5c3030375c3031365c3030315c3030305c3030305c3030305c3031365c3030305c3030305c303030305c3030305c3030305c30303070769a5c3031385c3030315c3030305c3030305c30303060759a5c3031385c3030315c3030305c3030305c303030e55c303033f992ff7f5c3030305c303030f5f17ab761ce5c3030302234635c3030315c3030305c3030305c3030305c3030305c303030d0769a5c3031385c3030315c3030305c3030305c3030303b92f75c3031355c3030315c3030305c3030305c3030305c303030705c3030395c3031365c3030315c3030305c3030305c303030805c3031315c3030385c3031365c3030315c3030305c3030305c3030305c3030345c3030305c3030305c30303034635c3030315c303030d393f75c3031355c3030315c3030305c3030305c30303034635c3030315c3030305c3030325c3030305c3030305c303030676f6f676c5c3030305c3030305c3030305c303234 A 127.0.0.1 --- SNAP ---

2.

Illegal DNS packets like forward pointers and pointer cycles aren't handled correctly either.

.. [1]: https://www.ietf.org/rfc/rfc1035.txt

.. [2]: https://gist.github.com/weissi/def5dc0fa89f9256e461

.. [3]: https://gist.github.com/weissi/bf4cc09931ba91fdaa5e

.. [4]: http://i.imgur.com/fgtuiF1.png

By weissismail at March 16, 2015, 11:54 a.m. (reply...)

Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!