In the previous chapter you learned about the underpinnings of BlackBerry applications and how to analyze them primarily in a static fashion. To be able to put these analysis techniques into practice, you also need to know about the attack surface of an app. Knowing about the app enables you to choose the correct technique to employ. Although each app is different in terms of attack surface, several elements are more common than not.
In this chapter we look at each of these attack surface elements and how they might be attacked. In the previous chapter you looked at some of the BlackBerry 10 app security fundamentals, architectural elements, and base security analysis techniques for apps, but in this chapter you dig a little deeper by looking at a number of fundamental concepts for BlackBerry 10 apps and how they can be attacked.
As with apps on any other operating system, whether it’s a full-fledged, general-purpose OS or a proprietary, hardware-abstracting, real-time OS, the principles of analyzing and attacking apps are the same. Namely, you want to be able to perform the following tasks:
The trust boundary of a BlackBerry 10 app is in the first instance of the operating system user that the app runs as. It is a trust because each app is run as a separate user to implement the sandboxing concepts discussed in the previous chapter. A second trust boundary may then exist in devices that are configured as balance enabled. Balance devices are configured with a personal half and an organization-controlled half that are separated from each other via a variety of access control lists at the file and network level coupled with process separation. This looks like Figure 15.1.
In the diagram in Figure 15.1 each app has its own private data sandbox within which to operate, but is also free from runtime modification of the executable image. The inter-container communication includes another degree of separation. That is, the interprocess communication mechanisms that would be available between App 1, App 2, and App 3 within their own container are typically disabled or limited in intercontainer situations. A couple examples of mechanisms that are limited in such a configuration include shared files and the clipboard.
Within QNX and thus BlackBerry 10, the following interprocess communication mechanisms exist, which allow for trust boundary traversal:
http://developer .blackberry.com/native/reference/core/com.qnx.doc.neutrino .utilities/topic/s/setfacl.html and http://developer.blackberry .com/native/reference/core/com.qnx.doc.neutrino.utilities/topic/ g/getfacl.html
)The native SDK documentation discusses a number of these in detail (http://developer.blackberry.com/native/documentation/core/com.qnx.doc .neutrino.sys_arch/topic/ipc.html
). Reviewing the utilities that ship with BlackBerry 10 is also a good idea because a number of them come in handy when you’re investigating apps. You can find a detailed reference on the BlackBerry developer website (http://developer.blackberry.com/native/reference/core/com.qnx.doc.neutrino.utilities/topic/about.html
). Reviewing the numerous sample apps for which BlackBerry published the source code is also worthwhile (http://blackberry.github.io/Catalogs/All_Samples.html
) because they provide a few examples with functionality one might consider dubious from a security perspective.
In BlackBerry 10 under the application’s working directory (homePath()
) are the following read/write locations:
./data
—This is a private data directory for the app that no other app can access. You obtain access to the contents of this directory by backing up the device and decrypting the backup../shared
and subdirectories—These are shared files that are accessible to apps with the access_shared
capability../tmp
—As the name implies, this is a temporary directory that the app and OS may clean up. This is private to the app itself../sharedwith
—This is data that is used by the app to share files with other apps via the Invocation Framework.With regard to /sharedwith
BlackBerry has this to say about the Invocation Framework and file transfer:
When the framework receives an invocation request with a
file://
URI, it inspects the URI to determine if the request refers to a shared area. If the file is already shared, the invocation request passes the URI to the file in the shared area, as specified by the sender. However, if the invocation framework detects that the file is not shared, then it creates a read/write copy of the file in a private inbox for the target app.
Three vectors for attacking apps via files satisfy our requirement of traversing trust boundaries. Attacking apps via shared
and Sharedwith
is trivial. Using the app’s private data directory to attack an app has only been partially implemented publicly due to the inability to re-encrypt in the commercial tools.
For shared files you should review the files both created and consumed by the target app. However, remember this attack assumes that the malicious app would have the access_shared
capability. When reviewing files that are created, you are primarily concerned with those that contain sensitive information and shared locations because this information is useful to a malicious app on the device or to the app’s author.
When assessing the files that are consumed by the target app, you are instead concerned with their contents and how malformed or otherwise malicious files might influence the program. For example, you might be able to inject content or script in the case of a WebWorks or a Cascades application, or trigger a denial-of-service or memory corruption vulnerability in an app that is written in C/C++. For sharedwith
files, the attack surface is similar to when an app consumes files from the shared
directory. However, instead of relying on passive consumption you can invoke an app. (See the “Invocation Framework” section later in this chapter.)
Numerous file browsers are available within BlackBerry World (http://appworld.blackberry.com/webstore/content/43871/?lang=en&countrycode=GB
). They provide the ability to review what files are in the shared
directory, as shown Figure 15.2. Alternatively, you can use SSH (Secure Shell) access to review the files and their contents.
For files that are held in an app’s private directory, you can recover anything sensitive stored by an attack. For details on how to do this see the section, “Accessing App Data from a Device” in Chapter 14. Files with contents that would modify the app’s behavior (whether execution or configuration) are modifiable. However, the ability to re-encrypt the backups so they can be restored to the device has not publicly been released.
On BlackBerry 10 it is conceivable that an app might implement a server of some kind via the socket API (http://developer.blackberry.com/native/documentation/core/com.qnx.doc.neutrino.sys_arch/topic/tcpip_sock .html
). Indeed, BlackBerry provides example code that does this to get around some security restrictions in WebWorks apps.
This BlackBerry 10 WebWorks extension provides additional APIs supplying an embedded Web Server.
The API gives you the ability to serve files outside the protected application directory.
The reason for writing this API is that you can’t download media from an external server and display it within a WebWorks application. This API overcomes this limitation allowing access of the Apps data or tmp directories using a URI like
http://localhost:8080/
.
https://github.com/blackberry/WebWorks- Community-APIs/tree/master/BB10/mongoose
Identifying sockets that may be of interest is as simple as doing a netstat before and after the application is invoked to see the new attack surface. You connect to the relevant socket via the socket API already discussed. In the case of the WebWorks example, which embedded the Mongoose web server, you can actually use the web browser to demonstrate the vulnerability.
UNIX domain sockets are supported on BlackBerry 10 (http://developer .blackberry.com/native/reference/core/com.qnx.doc.neutrino.lib_ref/topic/u/unix_proto.html
) and are arguably more secure than network sockets to IPC (Inter-Process Communication) developers. With regards to security:
Normal filesystem access-control mechanisms are also applied when referencing pathnames (e.g., the destination of a
connect()
orsendto()
must be writable).
To list the UNIX domain sockets on the device you can use netstat -f AF_LOCAL. To attack an app that is using UNIX domain sockets you must create it in a location that the attacking app has read/write access to. As with network sockets, you connect the relevant socket via the socket API as previously discussed.
Shared memory objects are supported on BlackBerry 10. You can find a Cascades example (http://blackberry.github.io/Qt2Cascades-Samples/docs/ sharedmemory.html
) that shows how to use them in an arguably insecure fashion. This app is split over two BAR files:
https://github.com/blackberry/Qt2Cascades-Samples/tree/master/sharedmemory
https://github.com/blackberry/Qt2Cascades-Samples/tree/master/sharedmemory_loader
In this example you set the key as follows:
// The key that is used for the shared memory segment
static const char *s_sharedKey = "fileloader_shm_key";
This allows the client to access the server by using this name. The underlying API is shm_open:
The permission bits for the memory object are set to the value of mode, except those bits set in the process’s file creation mask.
Using the shared memory sample app previously referenced provides a good basis upon which to build an app to read out the shared memory of other processes.
Identifying those apps that use shared memory primarily occurs via static analysis of either the code or binary. That is, you look for programs that import the shm_open
API or have a QSharedMemory
(http://developer.blackberry .com/native/reference/cascades/qsharedmemory.html
) object. In the case of Cascades, applications will allow you to identify such apps. It will then be a case of finding the name (if it is indeed named) to attempt to connect to it.
Persistent Publish/Subscribe (PPS) objects on BlackBerry are stored under the /pps path and can be created by apps either via the Cascades class PpsObject
(http://developer.blackberry.com/native/reference/cascades/bb__ppsobject .html
) or via a standard POSIX file API such as open
; for example, open ("/pps/an-object", O_RDWR | O_CREAT);.
Enumerating an app’s attack surface is as simple as enumerating the /pps namespace before and after installation and execution of the app, or if persistent PPS objects are used by backing up the app, you’ll also get a copy of the PPS objects.
Note that PPS objects are encoded. The example provided here is borrowed from http://www.qnx.com/developers/docs/660/index.jsp?topic=%2Fcom .qnx.doc.pps.developer%2Ftopic%2Fpps_encode.html
:
pps_encoder_t encoder;
pps_encoder_initialize(&encoder, false);
pps_encoder_start_object(&encoder, "@gps");
pps_encoder_add_double(&encoder, "speed", speed);
pps_encoder_add_string(&encoder, "city", city);
pps_encoder_start_object(&encoder, "position");
pps_encoder_add_double(&encoder, "longitude", lon);
pps_encoder_add_double(&encoder, "latitude", lat);
pps_encoder_end_object(&encoder);
pps_encoder_end_object(&encoder);
if ( pps_encoder_buffer(&encoder) != NULL ) {
write(fd, pps_encoder_buffer(&encoder), pps_encoder_length(&encoder));
}
pps_encoder_cleanup(&encoder);
Using this code results in a PPS object that would look like this (http://www.qnx.com/developers/docs/660/index.jsp?topic=%2Fcom.qnx.doc.pps .developer%2Ftopic%2Fpps_encode.html
):
@gps
speed:n:65.412
city::Ottawa
position:json:{"latitude":45.6512,"longitude":-75.9041}
The native C functions for encoding and decoding are not documented in the BlackBerry 10 API. Instead, you can reference the QNX documentation (http://www.qnx.com/developers/docs/660/index.jsp?topic=%2Fcom.qnx.doc.pps .developer%2Ftopic%2Fpps_api_reference.html
). For Cascade applications, the PpsObject
exposes versions of the encode and decode functionality, which is documented at http://developer.blackberry.com/native/reference/cascades/bb__ppsobject.html
.
To attack PPS objects, you apply three types of attack:
Room exists for some mischief in the context of PPS objects.
Channels is a slightly confusing term in BlackBerry 10. BlackBerry has repurposed a QNX core concept into a term it uses specifically in the context of BlackBerry Platform Services (BPS) (http://developer.blackberry.com/playbook/native/reference/com.qnx.doc.bps.lib_ref/com.qnx.doc.bps.lib_ref/topic/overview.html
).
Specifically, in the context of BPS there is an API called bps_channel_create which is used to implement this repurposed meaning (http://developer .blackberry.com/playbook/native/reference/com.qnx.doc.bps.lib_ref/com.qnx.doc.bps.lib_ref/topic/bps_channel_create.html
).
However, within the context of QNX a lower-level concept of channels is implemented via a number of kernel level APIs:
The lowest level of these APIs is
ChannelCreate
—To create the listening half of a channel http://developer .blackberry.com/native/reference/core/com.qnx.doc.neutrino .lib_ref/topic/c/channelcreate.html
ConnectAttach
—To connect as a client to the listening half of a channel http://developer.blackberry.com/native/reference/core/com.qnx .doc.neutrino.lib_ref/topic/c/connectattach.html
To use ConnectAttach
you need to know a Node Descriptor (ND), a process ID (PID), and a channel ID (CHID) to be able to attach to a server. Blackberry provides several ways for you to obtain this information (that is, advertised to other apps) in its documentation (http://developer.blackberry.com/native/documentation/core/com.qnx.doc.neutrino.getting_started/topic/s1_msg_find77.html
). However, at times you may need to try to brute-force these items.
A slightly higher-level version of the channels APIs exists for cross-process communication:
name_attach
—Use this to register a name in the namespace and create a channel (http://developer.blackberry.com/native/reference/core/com.qnx.doc.neutrino.lib_ref/topic/n/name_attach.html
).name_open
—Use this to open a name for a server connection (http://developer.blackberry.com/native/reference/core/com.qnx.doc .neutrino.lib_ref/topic/n/name_open.html
).You can find a couple of examples that show how channels are used in various apps for IPC. For example, to create and connect to a channel across threads and use pulses for events, check out this site: https://github.com/blackberry/Presentations/blob/master/2012-BlackBerryJam-Americas/JAM15/FaceFilter/src/main.cpp
The likelihood you will see the use of channels outside of events in apps and their being vulnerable in some way is low.
In addition to the specific attack surface elements discussed already in this chapter, several other higher-level concepts are worth considering when attacking BlackBerry applications.
As with apps on other OSs, the analysis of network traffic for the lack of encryption or network analysis when protocols, such as SSL/TLS, are used are common tasks that we perform to validate the implementation if the verification of certificates is performed as well. The techniques employed to attack BlackBerry apps are no different than those used on other mobile OSs that don’t easily allow instrumentation or where proxy settings may not be honored. For suggested approaches and relevant caveats, read Chapter 14’s section called “Network Traffic Analysis and Interception.”
The Invocation Framework addresses the concept of bounded and unbounded invocation.
First and foremost, there are two kinds of invocations—unbound and bound. An unbound invocation is performed when an app does not specify a specific target app that should get invoked, and hence relies on the invocation framework to select the best target. For example, if there are three apps that can open .DOC files, the framework chooses the best one based on its own target selection logic. So, for unbound invocations, the framework provides automatic brokering to find the best-fit targets and also performs target selection to choose the best among the best.
http://devblog.blackberry.com/2012/08/blackberry-10-invocation-framework/
You primarily want to focus on bounded invocations because you want to target a specific application. To understand what an app’s Invocation Framework attack surface is, you need to look in its bar-descriptor.xml. Within this file there will be <invoke-target>
tags; for example:
<invoke-target id="com.nccgroup.mahh.foo">
<invoke-target-name>Foo Monster</invoke-target-name>
<icon><image>icon.png</image></icon>
<type>foo.monster</type>
<filter>
<action>bb.action.OPEN</action>
<mime-type>*</mime-type>
<property var="uris" value="file://"/>
<property var="exts" value="monster"/>
</filter>
</invoke-target>
This code snippet says that it handles file URIs that end in .monster
for OPEN requests. When attacking Invocation Framework clients you will use these definitions to attack with URIs or files that are either malformed to cause undesirable behavior in the target app or to cause files or URLs to be accessed that lead to a second-stage attack.
To retrieve information from the clipboard that might be sensitive you need to use the Clipboard
class in the Cascades API (http://developer.blackberry .com/native/reference/cascades/bb__system__clipboard.html
). The challenge is you need to explicitly specify the MIME type; that is, text/plain
, text/html,
or text/url
. These types were identified by looking at the source code from the WebKit BlackBerry Port (https://github.com/adobe/webkit/blob/master/Source/WebCore/platform/blackberry/ClipboardBlackBerry.cpp
). The SDK documentation says:
Data in the clipboard is referenced by type. Multiple types of data can exist in the clipboard at the same time. Each type typically refers to a different encoding of the same data. For example, an application copying data from an HTML source might insert both HTML markup and plain text into the clipboard.
. . .
A type can be any non-empty string. For compatibility with other applications, using Internet media types (i.e., MIME types) is recommended. For example,
text/plain
,text/html
, andtext/rtf
are three commonly used encodings for textual data.
http://developer.blackberry.com/native/reference/cascades/bb__system__clipboard.htm
Due to this limitation, doing a number of requests with a variety of MIME types makes sense if you are looking to monitor the clipboard for changes. If you are writing an app to monitor the clipboard then make sure you request the run_when_backgrounded
capability; otherwise, your app won’t execute when it’s not in the foreground.
This chapter covers a number of ways that you can attack apps, from low-level operating system interprocess communication mechanisms through to higher-level, BlackBerry-specific concepts such as the Innovation Framework.
The attack you apply will depend on the type of app, attack surface, and the app’s specific functionality. For example, you may want to assess a WebWorks app for susceptibility to script injection vulnerabilities by looking at the sources and syncs for data retrieved and processed by app. In the WebWorks extension example where the authors embedded their own webserver (https://github .com/blackberry/WebWorks-Community-APIs/tree/master/BB10/mongoose
), you might look at the index.html
and associated JavaScript to see whether it pulls in a file from /shared
(it doesn’t) that was under your control.
Attacking BlackBerry 10 apps is not dissimilar to attacking any other POSIX compatible–based mobile device apps. Yes, attacking BlackBerry 10 apps has a few unique aspects due to QNX being the underlying operating system, plus the way BlackBerry 10 is architected from a security perspective and the presence of some higher-level functionality. However, on the whole, the attack methodologies you would employ for native (that is, C/C++) or web (HTML5/JavaScript) apps apply when you’re assessing BlackBerry 10 apps.