2015.02.02

UDIDやCookieを使わずFingerprintでiOS端末を識別する

はじめに

こんにちは。次世代システム研究室のT.Tです。
前回に引き続きiOSアプリ関連の記事です。

開発を担当したWebビューを使ったiOSアプリで、同じ端末からの不正なリクエストを識別する必要があり、その機能を実現するためにFingerprintを識別方法の一部として検証しました。
今回は、Fingerprintの概要と利用したライブラリの実装の主要箇所、実際にどの程度識別できるかを検証した結果についてご紹介したいと思います。

Fingerprintの概要

FingerprintはスマホやPC等の様々なデバイスを、その中に搭載されているブラウザから取得できる情報に基づき、各デバイスを識別するための技術です。
ブラウザから取得できる情報としては以下のようなものがあり、各要素によりどの程度端末を識別できるかがEntropyにより示されていて、Entropyが高い程端末を識別するのに役立ちます(各端末で異なる値になりやすい)。
(詳しくはHow Unique Is Your Web Browser?参照)
Variable Entropy (bits)
user agent 10.0
plugins 15.4
fonts 13.9
video 4.83
supercookies 2.12
http accept 6.09
timezone 3.04
cookies enabled 0.353
Table 2. Mean surprisal for each variable in isolation
Variable Value
User Agent Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20100106 Ubuntu/9.10 (karmic) Firefox/3.5.7
HTTP ACCEPT headers text/html, */* ISO-8859-1,utf-8;q=0.7,*;q=0.7 gzip,deflate enus,en;q=0.5
Cookies enabled? Yes
Screen resolution 1280x800x24
Timezone 300
Browser plugins Plugin 0: DivX Web Player; DivX Web Player version 1.4.0.233; libtotem-mully-plugin.so; (AVI video; video/divx; divx). Plugin 1: QuickTime Plug-in 7.2.0; The <a href=”http://www.gnome.org/projects/totem/”>Totem</a> 2.28.2 plugin handles video and audio streams.; libtotem-narrowspace-plugin.so; (QuickTime video; video/quicktime; mov) (MPEG-4 video; video/mp4; mp4) (MacPaint Bitmap image; image/x-macpaint; pntg) (Macintosh Quickdraw/PICT drawing; image/x-quicktime; pict, pict1, pict2) (MPEG-4 video; video/x-m4v; m4v). Plugin 2: Shockwave Flash; Shockwave Flash 10.0 r42; libflashplayer.so; (Shockwave Flash; application/x-shockwave-flash; swf) (FutureSplash Player; application/futuresplash; spl). Plugin 3: VLC Multimedia Plugin (compatible Totem 2.28.2); The <a href=”http://www.gnome.org/projects/totem/”>Totem</a> 2.28.2 plugin handles video and audio streams.; libtotem-coneplugin.so; (VLC Multimedia Plugin; application/x-vlc-plugin; ) (VLC Multimedia Plugin; application/vlc; ) (VLC Multimedia Plugin; video/x-google-vlc-plugin; ) (Ogg multimedia file; application/x-ogg; ogg) (Ogg multimedia file; application/ogg; ogg) (Ogg Audio; audio/ogg; oga) (Ogg Audio; audio/x-ogg; ogg) (Ogg Video; video/ogg; ogv) (Ogg Video; video/xogg; ogg) (Annodex exchange format; application/annodex; anx) (Annodex Audio; audio/annodex; axa) (Annodex Video; video/annodex; axv) (MPEG video; video/mpeg; mpg, mpeg, mpe) (WAV audio; audio/wav; wav) (WAV audio; audio/x-wav; wav) (MP3 audio; audio/mpeg; mp3) (NullSoft video; application/x-nsv-vp3-mp3; nsv) (Flash video; video/flv; flv) (Totem Multimedia plugin; application/x-totem-plugin; ). Plugin 4: Windows Media Player Plug-in 10 (compatible; Totem); The <a href=”http://www.gnome.org/projects/totem/”>Totem</a> 2.28.2 plugin handles video and audio streams.; libtotem-gmpplugin.so; (AVI video; application/x-mplayer2; avi, wma, wmv) (ASF video; video/x-ms-asf-plugin; asf, wmv) (AVI video; video/x-msvideo; asf, wmv) (ASF video; video/x-ms-asf; asf) (Windows Media video; video/x-ms-wmv; wmv) (Windows Media video; video/x-wmv; wmv) (Windows Media video; video/x-ms-wvx; wmv) (Windows Media video; video/x-ms-wm; wmv) (Windows Media video; video/x-ms-wmp; wmv) (Windows Media video; application/x-ms-wms; wms) (Windows Media video; application/x-ms-wmp; wmp) (Microsoft ASX playlist; application/asx; asx) (Windows Media audio; audio/x-mswma; wma).
System fonts wasy10, UnDotum, Century Schoolbook L, OpenSymbol, msam10, Mukti Narrow, Vemana2000, KacstQurn, Umpush, DejaVu Sans Mono, Purisa, msbm10, KacstBook, KacstLetter, cmr10, Norasi, Loma, KacstDigital, KacstTitleL, mry KacstQurn, URW Palladio L, Phetsarath OT, Sawasdee, Tlwg Typist, URW Gothic L, Dingbats, URW Chancery L, FreeSerif, ori1Uni, KacstOffice, DejaVu Sans, VL Gothic, Kinnari, KacstArt, TlwgMono, Lohit Punjabi, Symbol, Bitstream Charter, KacstOne, Courier 10 Pitch, cmmi10, WenQuanYi Zen Hei Mono, Nimbus Sans L, TlwgTypewriter, VL PGothic, Rachana, Standard Symbols L, Lohit Gujarati, kacstPen, KacstDecorative, Nimbus Mono L, Mallige, Nimbus Roman No9 L, KacstPoster, Mukti Narrow, WenQuanYi Zen Hei, FreeSans, cmex10, KacstNaskh, Lohit Tamil, Tlwg Typo, UnBatang, KacstFarsi, Waree, KacstTitle, Lohit Hindi, DejaVu Serif, Garuda, KacstScreen, FreeMono, URW Bookman L, cmsy10 (via Flash)
(Partial) supercookie tests DOM localStorage: Yes, DOM sessionStorage: Yes, IE userData: No
Table 3. A typical Panopticlick fingerprint
(表は同記事から抜粋)

用途としてはリワード広告等があるようです(詳しくは三宿さんの記事)。

Fingerprintの実装

Fingerprintを取得するためにfingerprintjsを利用しました。
Fingerprintを取得する箇所の実装は以下のようになっています。
  Fingerprint.prototype = {
    get: function(){
      var keys = [];
      keys.push(navigator.userAgent);
      keys.push(navigator.language);
      keys.push(screen.colorDepth);
      if (this.screen_resolution) {
        var resolution = this.getScreenResolution();
        if (typeof resolution !== 'undefined'){ // headless browsers, such as phantomjs
          keys.push(this.getScreenResolution().join('x'));
        }
      }
      keys.push(new Date().getTimezoneOffset());
      keys.push(this.hasSessionStorage());
      keys.push(this.hasLocalStorage());
      keys.push(!!window.indexedDB);
      //body might not be defined at this point or removed programmatically
      if(document.body){
        keys.push(typeof(document.body.addBehavior));
      } else {
        keys.push(typeof undefined);
      }
      keys.push(typeof(window.openDatabase));
      keys.push(navigator.cpuClass);
      keys.push(navigator.platform);
      keys.push(navigator.doNotTrack);
      keys.push(this.getPluginsString());
      if(this.canvas && this.isCanvasSupported()){
        keys.push(this.getCanvasFingerprint());
      }
      if(this.hasher){
        return this.hasher(keys.join('###'), 31);
      } else {
        return this.murmurhash3_32_gc(keys.join('###'), 31);
      }
    },

    ...
navigator、screen、window、canvasオブジェクトに格納されている値を参照して、必要に応じてFingerprintの書式に変換しているというくらいで特別なことはやっていないようです。

識別結果

検証はiPhone 4S、iPhone 5、iPhone 6、iPhone 6 Plusの端末で行い、全部で10台の端末でFingerprintの値を完全に一致するかどうかで比較しました。
iOSアプリ内のWebViewで先述のfingerprintjsを実行する以下のスクリプトを仕込んだhtmlを返すURLにアクセスして、端末のFingerprintを取得しました。
データをサーバー側で集めるために取得したデータをポストしています。
<script>
    var plain_hasher = function(value, seed){ return value; };
    var fingerprint = new Fingerprint({hasher: plain_hasher}).get();
    $.post('/server/postdata', {FingerprintID: fingerprint});
</script>
結果としては10台から6種類の異なるFingerprintを取得できました。

まとめ

iOSの端末ではPCのブラウザと比較してプラグインの値が利用できないためFingerprintによる識別はあまり有効ではなく、Fingerprintのみで端末を識別するのは難しいようです。
この検証結果を受けて、開発したiOSアプリでは他のいくつかの情報と組み合わせて端末を識別することになりました。

参考リンク

次世代システム研究室では、スマートフォンアプリエンジニアを募集しています。スマホアプリ開発経験者の方、スマホアプリ開発に興味がある方、また次世代システム研究室にご興味を持って頂ける方がいらっしゃいましたら、ぜひ 募集職種一覧 からご応募をお願いいたします。

  • Twitter
  • Facebook
  • はてなブックマークに追加

グループ研究開発本部の最新情報をTwitterで配信中です。ぜひフォローください。

 
  • AI研究開発室
  • 大阪研究開発グループ