MOBILE

Mobile Application Security : WebOS Security - Code Security

2/26/2011 4:17:11 PM
The JavaScript runtime manages memory, removing the need for third-party developers to worry about traditional coding errors such as buffer and integer overflows or other memory corruption errors. Not to say that these problems won’t exist—they will. But they will occur in platform applications such as WebKit, and memory corruption errors should not be a primary concern for third-party application developers.

Instead, application developers must focus on preventing application-level flaws, including script injection, SQL injection, and business logic flaws. These three attack classes are real risks on WebOS and take some effort to avoid. This section outlines the common coding errors, their impact, why they occur, and how to prevent them. An analysis of unique WebOS behaviors is also presented.

Script Injection

One of the most common web application vulnerabilities is cross-site scripting (XSS). This vulnerability occurs when a web application accepts user data and inserts that user data directly into a generated web page or AJAX response. If the user data is malicious and includes JavaScript, the script will execute in the context of the web application and allow the user to abuse the user session.

Note

For more information on web application vulnerabilities, refer to http://www.owasp.org/index.php/Top_10_2007.


XSS results when the web application fails to encode or reject the user-supplied data when generating web pages. When the web browser receives the page, it cannot differentiate between JavaScript the developer supplied and the JavaScript that the attacker has injected. Because it can’t tell the difference, the browser errors on the side of execution and runs any script it finds. To prevent these vulnerabilities, the web application must encode user data before inserting it into the web page. The browser will not treat encoded data as JavaScript and the attacker’s exploit won’t execute.

WebOS script injection is very similar to XSS. If attackers provide data to applications and that data is either treated as JavaScript or inserted into scene bodies without escaping, the Mojo framework will run the script as part of the application. WebOS JavaScript is much less constrained than the web browser sandboxe’s web JavaScript. Once the attacker’s JavaScript is executing, the attacker can send messages to the public bus, access per-application private data, and attack the rest of the device. Script injection in com.palm.* applications is even more worrisome because these applications can access the private bus and sensitive data, including text messages and e-mail.

At the time of this writing, Palm has already released patches for two script injection vulnerabilities, demonstrating that script injection vulnerabilities are a concern.

Three broad categories of script injection affect WebOS: direct evaluation, programmatic insertion, and template injection. Regardless of category, the severity is still critical. The categories only differ in the ways in which the vulnerability’s manifest.

Note that this research is extremely young, and new forms of script injection will likely appear in the future. Remember to handle all user data with suspicion, especially when combining it with executable JavaScript or HTML.

Direct Evaluation

Direct evaluation vulnerabilities occur when applications take user data and execute it, either by using the eval statement or by improperly handling the data when serializing or deserializing objects. JavaScript, and its associated frameworks, provides many methods to directly execute code. Because of the flexibility that dynamic execution enables, direct evaluation is a surprisingly common pattern in modern web applications. The following two methods are the most common source of direct evaluation script injection vulnerabilities in WebOS.

eval

The JavaScript eval() statement accepts a string parameter containing JavaScript, compiles the parameter into JavaScript bytecode, and then executes the newly compiled statement. Frameworks commonly use eval() when dynamically generating classes or creating framework objects. If attackers are able to insert unescaped data when the eval() statement is being assembled, the attacker’s JavaScript will be compiled and evaluated as legitimate user-supplied code. To prevent this vulnerability, do not generate eval() statements that include user data. Very few WebOS applications should require using eval(), and its common use may be an indication of poor design. Prefer designs that do not commonly use eval().

If eval() is the only option, ensure that the data comes from a trusted source and use the JavaScript “escape” function when processing untrusted data.

For example, this function is vulnerable to direct script injection via eval:

//user_data contains un-escaped and potentially malicious user-data
var j = eval('executeRequest(' + user_data + ')');

The developer is intending to call executeRequest with user_data as a parameter. However, attackers could supply a string for user_data that includes script. Here’s an example:

);evil(

After this string is concatenated into the preceding eval() statement, the evil function will be called.

To mitigate this vulnerability, change the code to the following:

//The built-in escape function will render malicious data harmless
var user_data_escaped = escape(user_data);
var j = eval('executeRequest(' + user_data_escaped + ')');

The JavaScript escape() function encodes JavaScript meta-characters so that they will not be interpreted as JavaScript when the eval() statement executes.

JSON Injection

Another form of direct evaluation vulnerabilities occurs when parsing objects serialized using JavaScript Object Notation (JSON). This notation describes objects as a series of key/value pairs. An advantage of JSON is that the serialized blob is actually JavaScript. This makes using JSON extremely easy because string JSON can be deserialized with the eval() function. WebOS uses JSON extensively as the message interchange format for serialization requests.

An object with two properties (key1 and key2) serialized as a JSON string looks similar to the following:

"{
key1 : "value";
key2 : "value2";
}"

Prototype’s evalJSON() method is used to deserialize this string back to a native JSON object. The attacker can abuse the deserialization process by supplying objects containing JavaScript expressions as parameter values.

Here’s a malicious JSON object:

"{
key1 : Mojo.Log.error('Exploited');
key2 : 42;
}"

When the JavaScript runtime deserializes this object using eval() or Prototype’s evalJSON(), the attacker-supplied logging statement will execute. Of course, logging statements are fairly benign. Attackers can always supply more damaging exploit code.

To mitigate JSON injection, never use eval() to deserialize JSON objects. Always use Prototype’s evalJSON() string method and pass “true” for the “sanitize” parameter. This parameter forces Prototype to reject any property value that contains an executable statement. Always use Prototype rather than “rolling your own” because the Prototype library is widely used and has been well reviewed.

Here’s an example of using the evalJSON() method to correctly ignore JavaScript during JSON deserialization:

var fruits = user_data.evalJSON(true);

Programmatic Data Injection

Script injection can also occur when data is programmatically inserted into Views by either manipulating the DOM directly or by calling Mojo functions which update the DOM. Once the attacker can affect the DOM, they can inject JavaScript and execute their exploit code.

innerHTML Injection

A simple form of script injection occurs when unescaped user data is assigned to an HTML element’s innerHTML property. This property accepts raw HTML and actually replaces the HTML of the parent element. Attackers can easily abuse this behavior to inject script tags into the WebOS application’s DOM.

For example, consider the following example from a sports application. The “user_data” variable contains unvalidated and untrusted user data.

var updatedScores = "<b>" + user_data + "</b>";
this.sportsScoreElement.innerHTML = updatedScores;

In general, it is unsafe to use innerHTML for updating the WebOS DOM. Most of the time, developers follow this pattern because they are building HTML through string concatenation. This method of generating HTML is very dangerous and should be avoided if at all possible.

update() Injection

Many WebOS applications use the sceneController’s update() method to refresh screen elements and force a redraw. Unescaped user data must never be passed directly to the update() method because this can allow malicious JavaScript to be injected into the DOM.

Here are two vulnerable examples:

var updated_scores = "<b>" + user_data + "</b>";
this.controller.update($('SportsScores'), updated_scores);

Or more directly:

this.controller.update($('SportsScores'), user_data);

In both of these instances, the SportsScores element is being updated with user_data, which may be malicious and provide attackers with the opportunity to inject script.

Avoiding innerHTML and update() Injections

Avoid concatenating user data with HTML tags. Not only is this practice less efficient, but it makes finding and removing script injection very difficult. The best solution is to design out the string concatenation.

If that is not possible, and sometimes it won’t be, then make sure to escape HTML data before sending it into the DOM. To do so, use Prototype’s escapeHTML() function. This method replaces all of the potentially dangerous characters with their “safe” versions. For example, < becomes &lt;. After this transformation, the < will no longer be interpreted as part of the document’s structure and attackers will no longer be able to insert script. The preceding vulnerable snippets could be rewritten as follows:

var updatedScores = "<b>" + user_data.escapeHTML() + "</b>";
this.controller.update($('SportsScores'), updated_scores);

and

this.controller.update($('SportsScores'), user_data);

Unfortunately, this method is far from foolproof, and its success relies on never forgetting to apply the escapeHTML() function to potentially malicious data. Given the size of modern applications, errors will likely slip through. A still better option is to use WebOS templates for inserting user data into the DOM.


Template Injection

The final category of script injection flaws are template injection flaws. Generically, templates are snippets of HTML containing placeholders where user data can be inserted. They are used heavily within views and are helpful to developers looking to avoid writing large amounts of presentation-generation code.

WebOS overloads the term template. There are actually two types of templates, and their behavior is similar but different in a scary and impactful way. The two types of templates are WebOS widget templates and Prototype templates. Most developers will only use WebOS templates because they are much more integrated into the overall Mojo framework.

WebOS Templates

When some widgets (such as the List widget) are used, a formatting template file may be specified. WebOS will invoke this template for each row that it inserts into the output list. The template contains HTML with simple placeholders that will be replaced by values from the template’s model. This system lets the developer avoid having to write complicated formatting code for configuring UI elements.

For example, the following HTML snippet formats will be applied to each list row and cause each element to have two divs—one for the team_name and one for the team_score. The contents of the #{team_name} and #{score} elements will be replaced with data from the row’s model object.

<div class="row textfield" >
<div class="score_tuple">
<div class="team_name">Team Name: #{team_name}</p>
<div class="team_score">Score: #{score}</div>
</div>
</div>

By default, the data substituted for the #{team_name} and #{score} tokens will be HTML-escaped. Therefore, script injection vulnerabilities, like the ones discussed in the “innerHTML Injection” section, will be prevented. This is obviously a clear advantage templates have over other formatting mechanisms.

However, the automatic escaping can be disabled by editing the application’s framework_config.json file and setting the value of the escapeHTMLInTemplates property to false. The framework_config.json file is stored in the application’s root directory and contains a list of properties that configure the Mojo framework itself. Try to avoid setting this property to false. Otherwise, the entire application must be reviewed for locations where unescaped and potentially malicious user data is formatted into templates. This is a time-consuming and expensive process, especially when compared to the cost of writing proper templates.

Instead of globally disabling HTML escaping, instruct the framework to disable it on a token-by-token basis. Do this by placing a hyphen (-) at the beginning of the replacement tokens. The framework will skip HTML-escaping these elements.

Here’s an updated version of the preceding team_name div. The #{team_name} replacement token will not be escaped.

<div class="team_name">Team Name: #{-team_name}</p>

Use this behavior sparingly. If an element is excluded from HTML escaping, ensure that models used for formatting do not contain any unescaped user data.

Prototype Templates

The Prototype JavaScript framework, included with WebOS, has its own template functionality that is very similar to standard WebOS view templates. However, these templates are not governed by the escapeHTMLInTemplates property. Therefore, any data formatted into Prototype templates must be manually escaped.

For example, the following template-formatting routine is vulnerable to script injection when user_data contains malicious data:

var score_template = new Template("<b> #{new_score} </b>");
sports_score = score_template.evaluate({"new_score" : user_data});
this.controller.update($('SportsScores'), sports_score);

To make this function safe, manually escape the data using Prototype’s escapeHTML() function.

Local Data Injection

Data from web pages, e-mails, and text messages is obviously malicious, but an additional, and often forgotten about, attack surface is the local one. With the rise of mobile malware, it is highly likely that users will install a malicious application at one point or another. WebOS makes some attempts to protect applications from each other: Sensitive data, such as e-mails and SMS messages, is directly accessible only through the private bus, and each application is able to store private data using either the cookie or depot storage API. Therefore, in order for mobile malware to compromise another application’s data, the malware must find a way to inject script into the target application.

Unfortunately, there are several ways this may happen, and they are not all well documented. This section outlines the various vectors available to malware attempting to inject script.

Application Launch Parameter Script Injection

One method attackers may use to inject script is by providing parameters containing script values. These parameters will be passed to the StageAssistant and/or AppAssistant when the application starts. The system provides no guarantees about the quality of this data, and parameter data certainly cannot be trusted.

To launch another application, applications dispatch a “launch” service request to the ApplicationManager service. Here’s an example:

this.controller.serviceRequest("palm://com.palm.applicationManager",
{
"method" : "launch",
"parameters" : {
"id" : "com.isecpartners.movietimes",
"params": {
movie_title : "Indiana Jones",
server_url: "http://www.isecpartners.com/movies"
}
}
});

All applications are permitted to launch any other installed application and supply any parameter values they wish. Applications need to handle potentially malicious launch parameters. If the launched application doesn’t handle the data appropriately—perhaps by improper use of templates or the update method—the malware could inject JavaScript that will execute in the context of the target application.

There are legitimate uses for launch parameters. For example, a movie application may take a “movie_title” parameter that it uses to search the Internet for movie show times. Because malware may have caused the application launch, the movie application must be careful about how it treats the “movie_title” data. Otherwise, formatting the search query into a template or evaluating it as JSON will likely result in script injection.

Script injection is not the only concern; malicious values may be supplied to exploit the application’s business logic. For example, our movie application could take a “server_url” parameter that tells the application which server to run the search query against. Assume that along with this search request, the application sends an authentication token. Obviously, an attacker would like to gain access to this token. By supplying their own value for the “server_url” parameter, the attacker may be able to force the application to post the attacker’s malicious server. This technique could be used to harvest a large number of authentication tokens.

Do not trust launch parameter values and, if possible, limit the set of allowed values to a predefined whitelist. Avoid sending data, especially sensitive data, to launch parameter-specified server addresses. If a request will leak sensitive data, consider asking the user before issuing the request.

To test an application’s resistance to malicious launch parameters, start the application using the luna-send command-line tool. This tool must be run from a WebOS command prompt and enables sending serviceRequests directly to services.

To use luna-send to launch an application, do the following:

  1. Open a novaterm shell to the device.

  2. Run the following command. The terminal requires the additional backslashes be used for escaping quotes.

    luna-send -n 1 "palm://com.palm.applicationManager/launch"
    "{\"id\":\"com.isecpartners.helloworld\",
    \"params\":\"{foo:\\\"bar\\\"}\"}"
Directly Launching Scenes

A slightly less well understood boundary is the scene boundary. Quite simply, any application can push a scene from any other application onto its scene stack. When this happens, the application that owns the scene is started and the execution context switches to the newly pushed scene.

This behavior is legitimately used throughout WebOS to elevate privileges and to provide a consistent user experience. For example, applications are prohibited from using the Camera plug in directly, but they can push the capture scene from the Camera application onto their stack. When they do so, the Camera scene runs and provides the user interface and permissions for taking the camera shot.

The Camera capture scene is an example of a scene that was designed to be included by other applications. However, not all scenes are designed this way, and attackers may be able to abuse scenes by invoking them out of order or supplying malicious parameters. Vulnerabilities resulting from the direct instantiation of scenes are similar to application launch vulnerabilities. Applications can invoke a scene directly using the Mojo.Controller.StageController.pushScene(scene, args) method, as shown here:

this.controller.stageController.pushScene(
{ appId: 'com.isecpartners.movie_app', name: 'PurchaseScene' },
{ tickets: "2"});

The second (args) parameter to the pushScene() method is an object that will be passed to the PurchaseScene’s scene assistant. Just like parameters passed on application launch, scene parameters must not be trusted. Also be aware that your scene may be called out of order. Imagine the following scenario:

  1. A movie application allows you to look up nearby movie times and purchase tickets. To ease the purchase process, the movie application stores your account information.

  2. When you make the purchase, the application takes you through a three-step process: Search Movies, Select Theater and Time, and Purchase.

  3. The Purchase scene takes a movie ticket ID and the e-mail address to send the tickets to as scene parameters.

  4. When the Purchase scene starts, it performs the purchase automatically and then shows the results to the user.

Malware can abuse this process by skipping the first two scenes and directly invoking the Purchase scene. Because the application didn’t verify the e-mail address parameter, the tickets are sent to the attacker’s e-mail address instead of to the legitimate user.

The process may sound contrived, but vulnerabilities extremely similar to this have been found in several WebOS applications. Unfortunately, being vigilant is the only solution. Always design scenes so that they are resistant to malicious parameters and do not execute sensitive actions without first asking the user for confirmation.

Opening Documents and Service Requests

Two additional methods for launching applications and communicating between applications involve using the Application Manager’s “open” method and directly making a serviceRequest. In the current version of the SDK, third-party applications are unable to register to be launched using either of these methods. If third-party services or document handling are ever allowed, though, risks similar to those outlined in the previous two sections will likely apply.

Application Packaging

Applications are packaged using the Itsy Package Manager System (ipkg). This is a commonly used application distribution format for embedded devices, and it bundles the entire application into a single easy-to-distribute file. The package files have the extension .ipk and are actually tar’d and gzip’d files (.tar.gz). To uncompress IPKs on Windows, simply use an extractor, such as 7-Zip, to extract the package’s contents.

IPKs may have an embedded signature, although Palm has not yet released the details on their signing process. Very few, if any details are currently available about the signatures that will be required for WebOS applications. The best guidance comes from the Terms of Service (http://developer.palm.com/termsofservice.html), which states that “applications which access or make use of Palm’s APIs may not be installed or used on Palm Devices, except in a test environment, without first being signed by a certificate issued by or for Palm.” In the future, developers will likely have to register with Palm and receive a developer certificate. Applications currently being distributed through the App Store are signed with a certificate owned by Palm. Details about this process will soon be added to the Palm Developer Portal, so check there for the most current information (http://developer.palm.com).

The package embeds the signature as three disjointed files: a certificate in PEM format, a public key, and a detached signature. It is unclear which content this signature covers, but it likely includes all files and directories within the IPK.

Other  
  •  Windows Phone 7 Development : Working with Isolated Directory Storage (part 2)
  •  Windows Phone 7 Development : Working with Isolated Directory Storage (part 1)
  •  iPhone Application Development : Making Multivalue Choices with Pickers - Using Date Pickers (part 3)
  •  iPhone Application Development : Making Multivalue Choices with Pickers - Using Date Pickers (part 2) - Adding a Date Picker
  •  iPhone Application Development : Making Multivalue Choices with Pickers - Using Date Pickers (part 1)
  •  iPhone Application Development : Making Multivalue Choices with Pickers - Understanding Pickers
  •  Sync Your iPad with iTunes : Troubleshooting iTunes and the Sync
  •  Sync Your iPad with iTunes : Manually Transferring Music, Movies, Podcasts, and More on Your iPad (Drag-and-Drop Method)
  •  Windows Phone 7 Development : Internationalization - Using Resource Files to Localize Content
  •  Windows Phone 7 Development : Internationalization - Storing and Retrieving Current Culture Settings
  •  Mobile Application Security : WebOS Security - Development and Security Testing
  •  Mobile Application Security : WebOS Security - Introduction to the Platform
  •  iPhone Application Development : Getting the User’s Attention - Using Alert Sounds and Vibrations
  •  iPhone Application Development : Getting the User’s Attention - Using Action Sheets
  •  jQuery 1.3 : Modifying table appearance (part 4) - Filtering
  •  jQuery 1.3 : Modifying table appearance (part 3) - Collapsing and expanding sections
  •  jQuery 1.3 : Modifying table appearance (part 2) - Tooltips
  •  jQuery 1.3 : Modifying table appearance (part 1) - Row highlighting
  •  Windows Phone 7 Development : Using Culture Settings with ToString to Display Dates, Times, and Text
  •  Mobile Application Security : SymbianOS Security - Persistent Data Storage
  •  
    Most View
    SyncMaster S24B750V - Stylish Monitor To Mirror Smartphone's Display
    Yamaha PDX-11 - Well-Rounded Quality With Excellent Bass
    Programming .NET Components : Building a Distributed Application (part 6) - Remote Callbacks
    Plantronics Backbeat Go, Inno3d Geforce Gt 640, Sony Internet Player With Google Tv, Azio Mech4 Levetron
    How to set up your own virtual private network (Part 1)
    Windows 8: End Game? (Part 3)
    Without A Wire
    Sony RX1 - The World’s Smallest Full-Frame Camera (Part 1)
    Mobile Application Security : SymbianOS Security - Code Security
    How fast is Windows 8? (Part 1)
    Top 10
    Thermaltake Cases Are Suitable For Everyone’s Budget (Part 7)
    Thermaltake Cases Are Suitable For Everyone’s Budget (Part 6)
    Thermaltake Cases Are Suitable For Everyone’s Budget (Part 5) : Thermaltake Armor Revo
    Thermaltake Cases Are Suitable For Everyone’s Budget (Part 4) : Thermaltake Level 10 GTS
    Thermaltake Cases Are Suitable For Everyone’s Budget (Part 3) : Thermaltake Commander MS-III
    Thermaltake Cases Are Suitable For Everyone’s Budget (Part 2)
    Thermaltake Cases Are Suitable For Everyone’s Budget (Part 1) : Thermaltake Commander MS-I
    LG Optimus L9 - A Cheap Middle Class Android Phone (Part 3)
    LG Optimus L9 - A Cheap Middle Class Android Phone (Part 2)
    LG Optimus L9 - A Cheap Middle Class Android Phone (Part 1)