XSS in Skype for iOS « Superevr
https://superevr.com/blog/2011/xss-in-skype-for-ios/
Skype XSS Explained « Superevr
https://superevr.com/blog/2011/skype-xss-explained/
Boxcarに学ぶプラットフォーム別セキュリティリスク - 金利0無利息キャッシング – キャッシングできます - subtech
http://subtech.g.hatena.ne.jp/mala/20110428/1304005287
これの話。
どういう実装をすると、このような現象が起きるのか。またどのような対策を施せば攻撃を防げるのか興味があったので自分がわかる範囲で調べた。
書こうと思ってからずいぶん時間がたってしまったし、全体的に知識不足・調査不足なのでツッコミ歓迎。
概要
file://, about://(applewebdata://) などの特権的なURLリクエストでロードされたUIWebView からjavascriptを利用してデバイスのアドレス帳、着信履歴などのデータファイルにアクセスできる為、
開発者が意図しないスクリプトを第三者に実行され、アプリユーザーのデータを盗まれてしまう可能性がある
Phil Purviance の報告によると ローカルのURL file:// を明示しないとこれは起きないという風に読めるけど、
俺がmalaさんに聞きながら確認してたケースではURLを無指定な状態 about:// (applewebdata://) でも起きることが確認できた(サンプルコードをあげておいたのでやってみて)。
サンドボックス外へアクセスできるケース
- Web APIなどから取得したデータを利用してHTMLを整形し、UIWebView でビューをつくっている
- ローカルのHTMLファイルをUIWebViewで読み込んだ状態から外部のデータを読み込んでjavascriptでDOMを生成している
UIWebView 以外にも PhoneGAP で作ったアプリで外部データを動的に読み込んでいるもの(file:// になってる)訂正
BoxacarとかSkypeとかがたぶんあてはまる。あと他のiTunes App Storeで公開中のアプリにも該当しそうなものが結構ある。
おそらくされない
- baseURLを適切に設定してある
- UIWebView にhttp[s]:// 〜 のスキームのリクエストを渡して単純な埋め込みウェブブラウザとして利用している
- Titanium Mobile の Titanium.UI.createWebView で作ったWebView (app://${Application Id}/hoge というデフォルトURLになった)
実行URLの簡単な確認方法
UIWebViewDelegate で現在のURLを表示してみる
- (void)webViewDidFinishLoad:(UIWebView *)webView { NSLog(@"Request URL: %@", [webView.request URL]); NSLog(@"DOM URL: %@", [webView stringByEvaluatingJavaScriptFromString:@"document.URL;"]); }
アプリに含まれたHTMLファイルを読みこんでUIWebView に読み込ませるケースはこんなかんじ
NSURL* URL = [[[NSBundle mainBundle] resourceURL] URLByAppendingPathComponent:@"index.html"]; [_webView loadRequest:[NSURLRequest requestWithURL:URL]]; Request URL: file:///var/mobile/Applications/9CC77062-D748-4E16-92B4-7A043494D739/UIWebView+XSSSample.app/index.html DOM URL: file:///var/mobile/Applications/9CC77062-D748-4E16-92B4-7A043494D739/UIWebView+XSSSample.app/index.html
あとabout://(applewebdata://) になる例というのは例えばよくある「HTML文字列をその場で整形してUIWebView に読み込ませる」というやり方で画面を実装していたとする
[_webView loadHTMLString:@"<h1>Hello World!</h1>" baseURL:nil];
こういうの。
その時の上記のログ表示はこうなる。
Request URL: about:blank DOM URL: applewebdata://6A65BE08-DD5B-477B-9C78-888803146C52
これはローカルファイルへのリクエストのかわりに、ローカルファイルを文字列として読み込んでUIWebView に渡すことも同等になる。
NSString* src = [[[NSString alloc] initWithContentsOfURL:[[[NSBundle mainBundle] resourceURL] URLByAppendingPathComponent:@"index.html"] encoding:NSUTF8StringEncoding error:nil] autorelease]; [_webView loadHTMLString:src baseURL:nil];
簡単な対処方
baseURL のパラメータをセットして file:// スキームへのアクセスを抑制できる。
[_webView loadHTMLString:src baseURL:[NSURL URLWithString:@"http://"]]; /** * file://, applewebdata:// だと抑制できない。 * hoge:// とか適当なのスキームにするとWebView自体のロードエラーがでるはず。なので http://〜 がよさそう */ Request URL: http:// DOM URL: http://
ただこの場合HTMLの中で <img src="imapge.png"> のようなURLでバンドルリソースのルートを読み込むのを期待していても http://imapge.png というURLに解釈されしまうので動的にフルパスに置き換えないといけなくめんどうくさい。
あと、本来のアプリの実装でXMLHttpRequest を発行している場合リスエクトが失敗してしまう。その時はbaseURL を http://api.example.com まで指定すれば api.example.com にはアクセスできるようになる。
サンプルコードでたいていそうなので baseURL:nil になっているコードは結構ありそう、
loadHTMLString baseURL:nil lang:objectivec - Code Search
http://www.google.co.jp/codesearch#search/&q=loadHTMLString%20baseURL:nil%20lang:objectivec&type=cs
HTMLのエスケープ処理
あとはGoogle Toolbox for Mac やらウェブにHTMLエスケープするスニペットやらがあるので入力を描写する際に逐一チェックするというウェブ開発と同じような作法が……
今回使用したサンプルコード+いろいろ
まとめ
前提: 外部からの入力のあるアプリでは
- loadRequest でfile:// を読まない
- loadHTMLString はbaseURL を設定する
- 入力値をチェックする
知りたいこと
更新: Fri Oct 7 17:43:37 JST 2011
リソースの安全な読み込みについて、
カスタムリソースにはNSURLProtocolを使えば良いのじゃないか? — sklave
のNSURLProtocol でカスタムスキーマの挙動を定義する方法が理想っぽい。参考になる。
更新:Fri Oct 14 20:11:50 JST 2011
iOS5 SDK のリリース版に更新してみたけどかわらずなので、
Bug Reporting Best Practices - Apple Developer
http://developer.apple.com/jp/bugreporter/bugbestpractices.html
に送った
→ "Closed" で処理された。次のバージョンでは直ってるのかな。
更新:Mon Oct 24 23:45:23 JST 2011
PhoneGap について 1.1.0 のバージョンを再確認したところ、
file:// スキームで動作していたものの、リモートのJavascript ファイルを読み込ませる部分は動作しなかった。
どういう実装なのか確認しているけど、上記NSURLProtocol で中間処理をしている為っぽい。
更新
NSURLProtocol を定義してUIWebView で安全にローカルのリソースを読み込む - laiso - iPhoneアプリ開発グループ
http://iphone-dev.g.hatena.ne.jp/laiso/20111130/1322649990