Webview白名单绕过
Url绕过
RFC中URL格式定义:
|
|
其中
以下是一些常见的Url检测和绕过的方式,内容来自参考链接。
indexOf(url)>0
绕过:1 2 3 4 5 6 7 8 9 10
private static boolean checkDomain(String inputUrl) { String[] whiteList=new String[]{"site1.com","site2.com"}; for (String whiteDomain:whiteList) { if (inputUrl.indexOf(whiteDomain)>0) return true; } return false; }
indexOf
提取域名校验1 2 3 4 5 6 7 8 9 10 11 12
private static boolean checkDomain(String inputUrl) { String[] whiteList=new String[]{"site1.com","site2.com"}; String tempStr=inputUrl.replace("http://",""); String inputDomain=tempStr.substring(0,tempStr.indexOf("/")); //提取host for (String whiteDomain:whiteList) { if (inputDomain.indexOf(whiteDomain)>0) return true; } return false; }
提取
://
和/
之间的字符串当作host进行校验 payload: http://site1.com@evil.com/poc.htmURL类中的
getHost
+indexOf
1 2 3 4 5 6 7 8 9 10 11
private static boolean checkDomain(String inputUrl) throws MalformedURLException { String[] whiteList=new String[]{"site1.com","site2.com"}; java.net.URL url=new java.net.URL(inputUrl); String inputDomain=url.getHost(); //提取host for (String whiteDomain:whiteList) { if (inputDomain.indexOf(whiteDomain)) return true; } return false; }
payload: http://www.site1.com.evil.com/poc.html 上述URL包含site1.com但是其中 www.site1.com 只是evil.com这个域名的子域名,还是指向攻击者控制的服务器。
getHost
+endsWith
payload: http://evilsite1.com/getHost
+endsWith
+ ‘.’1 2 3 4 5 6
String inputDomain=url.getHost(); //提取host for (String whiteDomain:whiteList) { if (inputDomain.endsWith("."+whiteDomain)) //www.site1.com return true; }
getHost
方法并不一定能得到正确的域名信息 payload: http://evil.com\@www.site1.com/poc.html 这里getHost
得到的是www.site1.com 但是实际访问的是evil.com服务器,不过攻击页面不能叫poc.html,根据访问日志需要叫/@.site.com/poc.html
(没具体验证这条,不懂为何www没了…) 另一种绕过方法: http://evil.com\.site1.com 这里getHost
方法得到的是evil.com.site1.com但是实际访问的是evil.com服务器URI代替URL
1 2 3 4 5 6 7 8 9 10 11
private static boolean checkDomain(String inputUrl) throws URISyntaxException { String[] whiteList=new String[]{"site1.com","site2.com"}; java.net.URI url=new java.net.URI(inputUrl); String inputDomain=url.getHost(); //提取host for (String whiteDomain:whiteList) { if (inputDomain.endsWith("."+whiteDomain)) //www.site1.com return true; } return false; }
payload:
1
JavaScript://www.site1.com/%0d%0awindow.location.href='http://evil.com/poc.html'
但是webview实际执行的是如下两行JavaScript代码:
1 2
//www.site1.com/ window.location.href='http://evil.com/poc.html'
第一行通过//符号来骗过java.net.URI获取到值为www.site1.com的host,恰好//符号在Javascript的世界里是行注释符号,所以第一行实际并没有执行;然后通过%0d%0a换行,继续执行window.location.href=‘http://evil.com/poc.html'请求poc页面.
URI + 协议校验
payload:
1
http://www.site1.com/redirect.php?url=http://evil.com/poc.html
Webview在请求http://www.site1.com/redirect.php?url=http://evil.com/poc.html 的时候,实际是发出了两次请求,第一次是在loadUrl中请求http://www.site1.com/redirect.php?url=http://evil.com/poc.html, 第二次是请求http://evil.com/poc.html ,但是第二次请求发生在loadUrl之后,而我们的白名单校验逻辑在loadUrl之前,才导致了绕过。
所以需要重写webview的
shouldOverrideUrlLoading
方法,该方法会在webview后续加载其他url的时候回调。
参考链接: