AppleTV & nmap -sV

208134-appletv2_x1_originalSo I’m working the other day, and my wife asks me why the TV is on. I don’t know. I didn’t turn it on. But it’s near my desk, and I know nobody else turned it on, either. I had been running nmap on my local network to test something out, though. You may have heard that you want to be careful using nmap against printers, because some of them will studiously print out the packets they receive and you may not want to use up all that paper. Was my Apple TV doing something like that?

Turns out it was. Join me for a little investigation-as-excuse-for-practicing-tools. I find chasing my own questions teaches me more about how things work than reading a book or in some other way chasing other people’s questions.

If you have an AppleTV, do this: Find out its IP address (Settings > General > About > IP Address. Mine was at 192.168.10.110. While you’re here, see if you have model A1625, running tvOS 9.2.2, like I do – maybe it matters?), then shut it off. Then, using a computer on the same network, run an nmap version scan.

nmap -sV 192.168.10.110

Watch the little light on the AppleTV. Mine comes about 30 seconds into the scan. The full scan completes about two or three minutes after that, and declares the following six ports to be open:

Version Scan Results

I shut it off and ran the scan again, and got the same results, so I’m certain it was the scan that turned it on. Now I want to know what’s making it happen. Maybe there’s something in here I can use to control the AppleTV? Can I turn it off? Start some music? Annoy my neighbor’s AppleTV?

Let’s see what’s happening on the network during this time.

In one terminal window, I ran tcpdump. In another, I ran the version scan again. Using tcpdump to show traffic as you run a scanner or other automated tool is a good habit. It helps you see that the thing is still running if it’s not producing output. It lets you see if you configured the scanner wrongly and now you’re about to get yourself into trouble scanning the Wrong Things.

If you run it with no arguments, you get packet headers dumped to stdout. You can add a bpf filter to cut down on uninteresting traffic (e.g. ‘not arp’) and the -n switch turns off name resolution and the use of well-known port names, so you get shorter lines. If you know the IP addresses you’re looking for, this can be a big help. For things like this, I find the less you let your tools interpret things, the better. I want to see “port 22” not “ssh” because what’s there may not actually be ssh all the time.

Tcpdump up top, nmap down below

I’m capturing the packets to a file (-w appletv.pcap) for later.

I’m thinking there’s going to be one or two packets that’s causing the thing to turn on, here, but let’s see how many we have to sort through, worst case, before we start looking.

2,869 packets is more than I want to look at.

How can we narrow this down? That was the whole version scan, and I know the thing I’m interested in is near the start of it.

Also, I’m going to guess that the packet I want is going to be one sent to an open port, and clearly the nmap scan will be trying to talk to closed ports, too. So, let’s try tcpdump again, but only listening for the ports that we found to be open earlier. That’s 3689, 5000, 7000, 7100, 49152, 62078. And I’m going to stop collecting traffic by hitting Ctrl-c as soon as I see the TV come on.

Down from 2869 to 122 packets.

That’s a whole lot better. I open the packet capture in Wireshark, and start at the bottom (most recent). I’m looking for anything that looks like a conversation. I notice this one:

Conversation of Interest

Right-clicking on that packet, and choosing “Follow…. TCP Stream” shows me this HTTP-ish conversation:

HTTP-ish Conversation

Now, RTSP is not HTTP, but it’s awfully similar in syntax here: I can do this on the command line, if I know what IP and port to send it to. Looking back up at Wireshark, it’s port 5000.

I shut off the AppleTV and try it, piping the OPTIONS request to netcat. The “-e” flag that I set for ‘echo’ tells it to interpret backslash escape sequences so I get actual newlines instead of a literal backslash-n which would do nobody any good.

Same Response as Captured

I get the same response, but the AppleTV is still off – so this is not the one I want. But it’s interesting that I get such a complete response from a system that is “off.”

Here’s another candidate:

Odd-Looking HTTP Request

This looks like something nmap is doing to get a specific response out of some specific system. The request is: GET /nice%20ports%2C/Tri%6Eity.txt%2ebak (“nice ports,/Trinity.txt.bak”? – yes, this is nmap creativity at work. Why do they send a request like this? Answer: http://seclists.org/nmap-dev/2006/q2/207)

Anyhow, I sent this one and got no response at all. And no TV wakeup. This is also not the one I want. Going further towards the beginning, I see two bare GET requests, to different ports.

GET / HTTP/1.0 to Port 3689

I can send that:

$ echo -en "GET / HTTP/1.0\n\n"| nc 192.168.10.110 3689

..and the TV comes on!

This turned out to be it. Just a “GET /” is all it takes to turn the AppleTV on from the network.

So, there’s my answer. It was a generic test that’s part of the nmap version scanning logic. Just like the thing where scanning a printer makes it print stuff, this is a side-effect of the scanner, not its intended functionality. And it’s not a bug or a tricky way some obscure packet is handled. It’s the most basic possible HTTP request. Interesting. That seems to suggest some functionality of the AppleTV is probably exposed through this port, and at least some of it doesn’t require authentication.

Looking around the web for information about this port, I came across this “Unofficial AirPlay Protocol Specification” that explains some of what I’m seeing here, and gives ideas for further research:https://nto.github.io/AirPlay.html. If you’re interested in how far this goes, that would be my next step.