UIWebView/WKWebView存在控件跨域访问漏洞(CNNVD-201801-515)

UIWebView/WKWebView存在控件跨域访问漏洞(CNNVD-201801-515)

漏洞描述

​ 国家信息安全漏洞库(CNNVD)收录,iOS 平台WebView组件漏洞(UIWebView/ WKWebView)跨域访问漏洞(CNNVD-201801-515):成成功利用该漏洞的攻击者可以远程获取手机应用沙盒内所有本地文件系统内容,包括浏览器的Cookies、用户的配置文件、文档等敏感信息。iOS平台使用了WebView组件的应用可能均受影响。

漏洞介绍

​ WebView是iOS用于显示网页的控件,是一个基于Webkit引擎、展现web页面的控件。WebView控件功能除了具有一般View的属性和设置外,还可对URL请求、页面加载、渲染、页面交互进行处理。

​ iOS平台的WebView组件(UIWebView/WKWebView)存在控件跨域访问漏洞(CNNVD-201801-515),漏洞源于UIWebView 默认允许“file://” 域发起跨域请求,而WKWebView可通过手动设置允许“file://”域发起跨域请求。攻击者可利用App文件下载机制将恶意文件写入沙盒内并诱导用户打开,当用户打开恶意文件时,其中的恶意代码可通过AJAX向“file://”域发起请求,从而远程获取App沙盒内所有的本地敏感数据。

漏洞等级

根据CNNVD漏洞分级规范,该漏洞的危害评级为高危。

漏洞验证

UIWebView

做iOS开发经常用到UIWebView,大多时候是加载外部地址,但是有一些时候也会用来加载本地的html文件。

UIWebView加载外部地址的时候遵循了“同源”策略,而加载本地网页的时候却绕够了“同源”策略,导致可以访问系统任意路径。

这就是UIWebView中存在的UXSS漏洞。

恶意网页

以下是HTML 代码快。

 <!DOCTYPE html>
<html>
    <body>
        <script>
        // 这个可以是⼿手机任意⼀一个⽂文件地址,如/etc/hosts、/etc/passwd 
        var localfile = "file:///etc/passwd"
        var xhr = new XMLHttpRequest(); 
        xhr.onreadystatechange = function() {
            if (xhr.readyState == 4) { 
                var txt = xhr.responseText;
                alert(txt);
            } 
        }
        try {
            xhr.open("GET", localfile, true); 
            xhr.send();
        } catch (ex) { 
            alert(ex.message);
        
        }
        </script>
    </body>
</html>

iOS源码(部分)

本文通过APP中UIWebView去读取本地index.html文件方式。

NSString *filePath = [[NSBundle mainBundle] pathForResource:@"index" ofType:@"html"];
NSURL *url = [[NSURL alloc] initWithString:filePath];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[self.webView loadRequest:request];

运行结果

Simulator Screen Shot - iPhone SE (2nd generation) - 2020-05-27 at 15.18.11.png

测试结果

UIWebView 允许“file://” 域发起跨域请求,通过 JavaScript可以访问沙箱内的文件,甚⾄至可以静默上传文件到远端,默认存在此漏洞。

WKWebView

从 iOS 8.0 和 OS X 10.10 开始,在你的APP中使用 WKWebView 添加网页内容,不要使用 UIWebViewWebView

WKWebView可将网页处理限制在App的网页视图中,从而确保不安全的网站内容不会影响到App的其他部分。此外,iOS、macOS和Mac Catalyst均支持WKWebView。

WKWebView 可通过手动设置允许“file://”域发起跨域请求。

WKWebView 默认 allowFileAccessFromFileURLs 和 allowUniversalAccessFromFileURLs 选项为 false。

恶意网页

以下是HTML 代码快。

 <!DOCTYPE html>
<html>
    <body>
        <script>
        // 这个可以是⼿手机任意⼀一个⽂文件地址,如/etc/hosts、/etc/passwd 
        var localfile = "file:///etc/passwd"
        var xhr = new XMLHttpRequest(); 
        xhr.onreadystatechange = function() {
            if (xhr.readyState == 4) { 
                var txt = xhr.responseText;
                alert(txt);
            } 
        }
        try {
            xhr.open("GET", localfile, true); 
            xhr.send();
        } catch (ex) { 
            alert(ex.message);
        
        }
        </script>
    </body>
</html>

iOS源码

     WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
     configuration.preferences.javaScriptEnabled = YES;
     configuration.preferences.javaScriptCanOpenWindowsAutomatically = YES;
     configuration.suppressesIncrementalRendering = YES; // 是否支持记忆读取
    [configuration.preferences setValue:@YES forKey:@"allowFileAccessFromFileURLs"];
     if (@available(iOS 10.0, *)) {
          [configuration setValue:@YES forKey:@"allowUniversalAccessFromFileURLs"];
     }
    WKWebView *wkweb = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:configuration];
    wkweb.center = self.view.center;
    wkweb.UIDelegate = self;//代理,需要实现alert
    [self.view addSubview:wkweb];
    wkweb.backgroundColor = UIColor.redColor;

    NSString *resourcePath = [[NSBundle mainBundle] resourcePath];
    NSString *filePath =[resourcePath stringByAppendingPathComponent:@"index.html"];
    NSMutableString *htmlstring=[[NSMutableString alloc] initWithContentsOfFile:filePath  encoding:NSUTF8StringEncoding error:nil];
    NSURL *baseUrl=[NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]];
    [wkweb loadHTMLString:htmlstring baseURL:baseUrl];

运行结果

无信息展示。

测试结果

无法复现漏洞。

漏洞总结

​ 市面上大多数使用HTML5技术开发的应用均使用WebView进行HTML5页面的展示。除了从远程服务器加载Web页面,WebView还可以通过修改特定配置,从文件中进行HTML5页面的加载。在未正确配置WebView的情况下,导致WebView同源策略失效,导致HTTP协议、file协议跨源攻击。该漏洞导致WebView能够访问当前应用内部数据,如果WebView加载了来源不明的HTML文件,可能导致当前应用内部数据被攻击者窃取,如身份认证信息、加密密钥、用户隐私信息等。

​ 成功利用该漏洞的攻击者,可以远程获取手机应用沙盒内所有本地文件系统内容,包括浏览器的Cookies、用户的配置文件、文档等敏感信息。iOS平台的应用如果在使用WebView组件时,未考虑上述情况,则会受到漏洞影响。

附件

建议

  1. 避免开启文件域的全局访问;
  2. 避免在WebView中加载来自外部传入的“file://”域页面;
  3. 对于敏感信息数据,建议进行加密处理后存储,或使用iOS平台推荐的KeyChain服务进行存储,可缓解漏洞可能造成的破坏;
  4. WKWebView 检查 allowingReadAccessToURL 路径是否安全,WKWebView 默认不允许“file://”域发起跨域请求。
  5. WKWebView 默认 allowFileAccessFromFileURLs 和 allowUniversalAccessFromFileURLs 选项为 false。

官方警告

b3b7d0a20cf431adaa6f84345cd9a4a92fdd9877.jpg

苹果表示,App仍在使用已弃用的UIWebView API嵌入网络内容的开发者,应尽快更新为WKWebView以提升安全性和稳定性。

WKWebView可将网页处理限制在App的网页视图中,从而确保不安全的网站内容不会影响到App的其他部分。此外,iOS、macOS和Mac Catalyst均支持WKWebView。

苹果提醒称,2020年4月起App Store将不再接受使用UIWebView的新App,2020年12月起将不再接受使用UIWebView的App更新。

修复方案

  1. 禁用从外部打开HTML文件;(切断攻击入口)
  2. 针对本地HTML文件中脚本做一些权限限制;(初步防范措施)
  3. 新增一个NSURLProtocol, 专门用来处理本地网页的加载,根据同源策略来安全地加载本地文件。(彻底的解决方案)

方案3:新增一个NSURLProtocol, 专门用来处理本地网页的加载,根据同源策略来安全地加载本地文件。

我们知道IOS中对于各种协议(http,https, ftp, file)的处理都是通过NSURLProtocol来实现的,

每一种对应了一个NSURLProtocol,有以下几个重要的方法:
+ (BOOL)registerClass:(Class)protocolClass

注册NSURLProtocol,

+ (void)unregisterClass:(Class)protocolClass

反注册NSURLProtocol

+ (BOOL)canInitWithRequest:(NSURLRequest *)request

表示是否走该NSURLProtocol的处理逻辑,返回YES,表示走,NO 表示不走,

- (void)startLoading

表示开始加载请求,由系统调用该方法,我们只需在该方法内部做网络数据请求就可以

- (void)stopLoading

表示停止加载请求,由系统调用该方法,我们只需在该方法内部做一些取消请求操作

我们新建一个类派生自NSURLProtocol, 暂且命名为SeMobSandBoxFileProtocol

全局使用
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    // 注册我们的协议
    [NSURLProtocol registerClass:[SeMobSandBoxFileProtocol class]];
    return YES;
}
局部使用
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    // 注册我们的协议
    [NSURLProtocol registerClass:[SeMobSandBoxFileProtocol class]];
}
SeMobSandBoxFileProtocol.h
#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface SeMobSandBoxFileProtocol : NSURLProtocol


@end

NS_ASSUME_NONNULL_END
SeMobSandBoxFileProtocol.m
#import "SeMobSandBoxFileProtocol.h"

@implementation SeMobSandBoxFileProtocol

+ (NSArray *)supportedScheme {
    return [NSArray arrayWithObjects:@"file", nil];
}

/// 表示是否走该NSURLProtocol的处理逻辑
/// 返回:YES 表示走。
/// 返回:NO  表示不走。
/// @param request 请求
+ (BOOL)canInitWithRequest:(NSURLRequest *)request {
    NSURL* url=[request URL];
    NSUInteger index = [[self supportedScheme] indexOfObject:[url scheme]];
    if (index != NSNotFound) {
        NSURL* baseURL = [[request mainDocumentURL] URLByDeletingLastPathComponent];
        //得到主资源的路径
        NSString* baseString = [[baseURL absoluteString] lowercaseString];
        NSRange sharpRange = [baseString rangeOfString:@"#"];
        if (sharpRange.length) {
            // 路径过滤处理,去掉#号以及#号后面的内容
            baseString = [baseString substringToIndex:sharpRange.location];
        }
        if([baseURL isFileURL]) {
            // 判断子资源路径是否包含主资源路径前缀
            BOOL ok = ![[[url absoluteString] lowercaseString] hasPrefix:baseString];
            return ok;
        }
        else {
            return baseString.length>0;
        }
    }
    return NO;
}

// 表示停止加载请求,由系统调用该方法,我们只需在该方法内部做一些取消请求操作
- (void)stopLoading {
    
}

// 表示开始加载请求,由系统调用该方法,我们只需在该方法内部做网络数据请求就可以
-(void)startLoading {
    NSError * _Nonnull error = [NSError errorWithDomain:@"CFNetwork"
                                                   code:kCFURLErrorUnknown
                                               userInfo:@{@"NSErrorFailingURLKey":self.request.URL}];
    
    [[self client] URLProtocol:self didFailWithError:error];
}
 
+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request {
    return request;
}

@end
代码分析

总体思路是根据主资源与子资源的文件路径判断它们是不是父子目录关系,如果是的话,就允许访问子资源,否则就不允许,这样就阻止了子资源访问主资源对应目录以外的目录,因为判断是否为父子目录关系,是根据是否包含目录前缀来判断的,所以需要对路径进行过滤处理,把路径中#号后面的内容连同#一起过滤掉。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,165评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,720评论 1 298
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,849评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,245评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,596评论 3 288
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,747评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,977评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,708评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,448评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,657评论 2 249
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,141评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,493评论 3 258
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,153评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,108评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,890评论 0 198
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,799评论 2 277
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,685评论 2 272

推荐阅读更多精彩内容