IOS中UIWebView的UXSS漏洞及修复方法

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

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

这就是UIWebView中存在的UXSS漏洞。已知尚未修复该漏洞的App有:微盘、文件全能王、QQ阅读。

漏洞复现方式大体相似,现在微盘为例:

在PC上编辑一个网页,命名为test.html. 内容如下:

<script>
alert(document.location);
var aim='file:///private/etc/passwd';
var d=document;
function doAttack()
{
    var xhr1= new XMLHttpRequest();
    xhr1.overrideMimeType('text/plain; charset=iso-8859-1');
    xhr1.open('GET',aim);    
    xhr1.onreadystatechange = function() 
    {
       if(xhr1.readyState ==4)   
       {      
       	  var txt=xhr1.responseText;
       	  alert(txt);
       }    
    };
    xhr1.send();
}
doAttack();
</script>

通过文件发送到微信手机端,在微信手机端点击刚才发过来的文件,选择用其他应用打开,在弹出来的应用列表里选择“微盘”,这个时候会进入微盘界面,点击上传按钮,上传完毕后,在我的微盘文件列表中点击刚才上传的文件,这个时候会弹出一个alert框显示当前文件所在路径,点击“好”,接着就会显示系统账户和密码信息(也就是passwd文件的内容)。

效果图如下:

修复方案

<1>禁用从外部打开HTML文件;(切断攻击入口)

<2>针对本地HTML文件中脚本做一些权限限制;(初步防范措施)

<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

在AppDelegate的application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions回调中调用

[NSURLProtocol registerClass:[SeMobSandBoxFileProtocol class]];  //注册我们的协议

SeMobSandBoxFileProtocol.h、SeMobSandBoxFileProtocol.m内容分别如下:

#import <Foundation/Foundation.h>

@interface SeMobSandBoxFileProtocol : NSURLProtocol

@end

#import "SeMobSandBoxFileProtocol.h"

@implementation SeMobSandBoxFileProtocol

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

+ (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
{
    [[self client] URLProtocol:self didFailWithError:[NSError errorWithDomain:@"CFNetwork" code:kCFURLErrorUnknown userInfo:@{@"NSErrorFailingURLKey":self.request.URL}]];
}

+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request {
    return request;
}
@end
代码分析

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



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在JavaScript调用iOS方法需要使用JavaScript与原生iOS之间的交互技术。以下是一些方法: 1. 使用UIWebView执行JavaScript代码 可以使用UIWebViewiOS应用程序执行JavaScript代码。UIWebView对象提供了一个方法,可以通过该方法将JavaScript代码传递给UIWebView并执行它。在JavaScript代码,可以使用window.location来调用iOS方法。例如: ``` window.location = "ios://methodName?param1=value1&param2=value2"; ``` 在iOS应用程序,可以在UIWebView的委托方法截取这个请求,解析参数,并调用相应的方法。例如: ``` - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { NSURL *url = request.URL; if ([[url scheme] isEqualToString:@"ios"]) { NSString *methodName = [url host]; NSDictionary *params = [self parseParams:[url query]]; // call the iOS method with the given name and parameters [self callMethod:methodName withParams:params]; return NO; } return YES; } ``` 2. 使用JavaScriptCore框架 JavaScriptCore框架是一个内置于iOS的JavaScript引擎。可以使用它来执行JavaScript代码并与原生iOS进行交互。可以使用JSContext对象来将JavaScript代码传递给JavaScript引擎并执行它。在JavaScript代码,可以使用JSContext对象的evaluateScript方法来调用iOS方法。例如: ``` var methodName = "methodName"; var param1 = "value1"; var param2 = "value2"; var result = MyObjCClass.callNativeMethod(methodName, param1, param2); ``` 在iOS应用程序,可以创建一个MyObjCClass类来处理JavaScript传递的调用请求,并返回结果。例如: ``` JSContext *context = [[JSContext alloc] init]; context[@"MyObjCClass"] = [MyObjCClass class]; [context evaluateScript:@"var methodName = 'methodName'; var param1 = 'value1'; var param2 = 'value2'; var result = MyObjCClass.callNativeMethod(methodName, param1, param2);"]; ``` 以上是两种在JavaScript调用iOS方法方法。当然,具体的实现方案需要根据具体的需求和场景进行调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值