Basic
Hackerがフェイク関数を作るために、Overrideする可能性があるのは、以下の3つであるように思われる。
(a1) document
(a2) document.write
(a3) document.write.toString
しかし、実際(a1) はありえない。なぜなら、
window.documentはread-onlyであり、新しい値を指定できないからである。
以下のコマンドを実行した場合、
"use strict";
window.document=999;
以下のようなエラーメッセージが出る。
Uncaught TypeError: Cannot set property document of #<Window> which has only a getter
at basic.php:95:16
You can see it in console...
さて、HackerがOverrideする可能性があるのは、以下の2つに絞られた。
(b1) document.write
(b2) document.write.toString
(b1) は base 関数も含めると、次の3つの可能性がある。
(b1.1) document.write
(b1.2) document.__proto__.write
(b1.3) document.__proto__.__proto__.write
'write' という property を持つかどうか、以下に列記する。
document.hasOwnProperty('write') => false
document.__proto__.hasOwnProperty('write') => false
document.__proto__.__proto__.hasOwnProperty('write') => true
※ 上記に3つに関する説明は hasOwnProperty.php を参照。
これら3つは、 hasOwnPropertyを用いて (false,false,true) を確認しなければいけない。もし確認できなければ、Hackされていると結論づけられる。
次に(b2)だが、これは base 関数も含めると、次の2つの可能性がある。
(b2.1) document.write.toString
(b2.2) document.write.__proto__.toString
'toString' という property を持つかどうか、以下に列記する。
document.write.hasOwnProperty('toString') => false
document.write.__proto__.hasOwnProperty('toString') => true
※ 上記に2つに関する説明は hasOwnProperty.php を参照。
これら2つは、 hasOwnPropertyを用いて (false,true) を確認しなければいけない。もし確認できなければ、Hackされていると結論づけられる。
さて、以下の関数では、hasOwnProperty が false を返すのを確認しなければいけないことを理解した。
(b1.1) document.write
(b1.2) document.__proto__.write
(b2.1) document.write.toString
以下の関数では、hasOwnProperty は true を返すわけだが、それを確認しただけでは不十分である。
(b1.3) document.__proto__.__proto__.write
(b2.2) document.write.__proto__.toString
これらの関数では、isNativeCode が true を返さなければいけない。
isNativeCode の詳細に関しては別のページに譲るが、isNativeCode は内部で、toString() を用いるので
以下の関数が重要になる。
(c1) document.__proto__.__proto__.write.toString
(c2) document.write.__proto__.toString.toString
Hackerは、isNativeCode を誤動作させるために、上記の2つの関数を以下のように Override しようとする。
document.__proto__.__proto__.write.toString=function(){
return "function write() { [native code] }";
};
document.write.__proto__.toString.toString=function(){
return "function toString() { [native code] }";
};
しかし、実際、この2つの関数を別々に Override することはできないのである。
※ その説明は toString.php を参照。
結局、Hacker は、ひとつの関数で上記の2つを Override しなければいけなくなる。
この Override を阻止するのに有効な手立ては、ダミーで document.write.toString() を
何回か呼び出すのである。
(1) document.write.toString() を n 回実行。
(2) document.write が native code であるかチェックするために、
document.write.toString() を isNativeCode 内で実行。
(3) document.write.toString が native code であるかチェックするために、
document.write.toString.toString() を isNativeCode 内で実行。
(4) document.write.toString() を m 回実行。
上記のように document.write.toString() を実行した場合、ハッカーは
(n+1)回まで、"function write() { [native code] }" を返して、
それ以降は、"function toString() { [native code] }" を返さなければいけない。
内部のコードを見ることなく、この切る変えを行うのは、かなり難しい。