まだプログラマーですが何か?

プログラマーネタ中心。たまに作成したウェブサービス関連の話も https://twitter.com/dotnsf

タグ:popstate

NHK が最近また流行りだしたワンクリック詐欺サイトのニュースを流していました:
スマホに「消せないメッセージ」 注意を


(2015/02/06 追記)
NHK のニュースページが消えてしまい、リンク切れになっていたので、同様のニュースを紹介しているページのリンクを貼っておきます:
【注意!】スマホに消せない画面を表示し金を奪うサイトが続出!
(2015/02/06 追記終わり)


ニュースの内容によると、どうもこれは
 ・(アプリとかではなく)特定のウェブページを
 ・スマホを使って
 ・閲覧した瞬間に
起こる仕組みがある、というものでした。

試しに見てボタンをクリックしたら、ではなく、見た瞬間に発生するらしいです。なので詐欺とわかっていても何が起こるかわからないので試してみるのも怖い、、、、ですよね。

せっかくなので(笑)、勇気を出して比較的安全と思われる方法で何をやっているのかを調べてみました。

このニュースで報じられていたサイトは、どうやら http://XXXXX-avnavi.net/ というサイトです(XXXXX 部分は僕の判断で伏せ字にしてます)。 結論から言うと、このサイトは PC のブラウザでアクセスすれば、単に JavaScript の alert が繰り返し表示されるだけの迷惑ページで済むのですが、最初は何が起こるかわからないので PC ブラウザも使いません。Linux 環境から基本の wget でソースコードだけいただきます:
(トップページの HTML ソースコードだけいただいて X.html という名前で保存)
# wget http://XXXXX-avnavi.net/ -O X.html

取り出した内容を vi で表示します。何よりも驚いたのは丁寧でわかりやすいコメントが大量に書かれていました。おかげで何をやっているのか、とても理解しやすかったです(笑)。この姿勢に限っては真似してもいいと思う。

さてその内容ですが、まず最初にこんな JavaScript コードが実行されてました(コメントもそのまま):
<script>
// History API が使えるブラウザかどうかをチェック
if( window.history && window.history.pushState ){
  //. ブラウザ履歴に1つ追加
  history.pushState( "nohb", null, "" );
  $(window).on( "popstate", function(event){
    //. このページで「戻る」を実行
    if( !event.originalEvent.state ){
      //. もう一度履歴を操作して終了
      history.pushState( "nohb", null, "" );
      return;
    }
  });
}
</script>

非常に丁寧なコメントですよね~(苦笑)。実を言うとこの時点で「おや?」と気付くこともあったのですが、その内容は後述します。

肝心な内容は JavaScript で HTML5 の History API が利用できるブラウザかどうかをチェックした上で、popState/pushState を操作して「戻る」を実行しても戻れないように(要するに「戻る」の無効化)操作しています。このページを見て、怖くなって「戻る」を押しても戻れないように予め設定されてしまうのです。用意周到ですね。。

ちなみにここのテクニックに関しては以前に僕のブログエントリでも紹介しています。興味ある方はそちらを参照ください:
HTML5 の pushState/popState でヒストリバックを無効にする


そして、ページを戻れなくした上で行っているのがこちらのコードです。赤字部分は僕が加えた説明コメントです:
<script type="text/javascript">
client_id1 = getCookie('id'); //. クッキーから(別途設定した) ID を取得
console.log("in template"); //. この2行要らないと思う
console.log(client_id1);
var HogeTimer = setInterval("hogemoge()",1000); //. 1秒毎に以下を実行
function hogemoge(){
(この一行があまりにも長くて見にくかったので改行しています。
 問い合わせ先電話番号 NNNNNNNNNNNNN はこちらで伏せ字にしました)

alert('【御登録完了】\nお申込み承諾致しました。\n 動画再生準備完了中。\n\n 【18禁アダルト動画サイト】\n 【365日間の視聴期間】\n\n ★只今お客様還元祭★\n ★キャンペーン期間中で割引適用中★\n 99800円\n 会員ID:' +client_id1 +'\n問い合わせ先\nNNNNNNNNNNNNN\n ※キャンペーン期間内にご精算下さい※\n\n ※誤作動登録の場合※\n →24時間以内に登録削除(自動処理)へご連絡ください。\n\n ※24時間経過後※\n→誤作動登録の場合でもご精算頂きます。');
//. ↑怖いメッセージを表示した後に、、 location.href = "tel:NNNNNNNNNNNNN"; //. スマホの場合、ここで電話をかけようとする

//. 終了しても1秒後にメッセージ表示から繰り返される } </script>

まず別途設定したクッキーを使って、お客様番号っぽい情報を作り、それを取り出します(お客様番号でも何でもありません)。 その直後の console.log 2行は気持ちは分かるけど消しておいた方がいいと思う(苦笑)。

そして JavaScript の setInterval を使って、1000ミリ秒(1秒)毎に実行する処理を指定しています。ここでいう「1秒毎」は、この処理が実行されて、最後まで実行して、そこから1秒たったらまた初めから実行、です。要は1秒の間をとりながら延々と繰り返される処理、ということになります。ここまではよくあるブラクラと同じ原理です。

気になる肝心の処理内容ですが、(1)怖いメッセージを表示して(「OK」ボタンだけ表示されるので押すしかない)、(2)「OK」を押すと(スマホでは)特定の番号に国際電話をかけようとする です。実際には「電話をかけますか?」という確認メッセージが表示されて、かけるかどうかを選択できるのですが、書けずに終了しても、1秒後にまた (1) へ戻るだけです。ちなみに電話をかけても (1)へ戻ります。

「怖い」と感じて、前のページに戻ろうとしても前述のように「戻る」は無効化されています。普通にホームボタンを押してブラウザを閉じてしまうことはできますが、(別の目的で)ブラウザを使おうとすると、履歴が残っているのでまたこの画面に戻ってしまいます。パニックにさせて、「電話をかけるしかないのか?」と思わせようとしてるんですかね。ちなみに電話をかける実験まではしてないので、どういう内容かはわかりません。 (^^;


もしも、間違ってこのページを PC ブラウザで開いてしまった場合は、CTRL+ALT+DEL キーを押してタスクマネージャーを出すなどして、ブラウザごと終了してしまいましょう。

スマホでこのページを見ちゃった場合はこちらのページを参考に履歴ごと消してしまってください:
http://did2memo.net/2013/11/15/iphone-endless-pop-up-message-page/



サイトの仕組みの説明は以上です。この下は気付いた雑感を2つほど。

まず、このページの HTML / JavaScript は非常に読みやすいです、メンテナンスしやすそう(苦笑)。ある意味で優秀なエンジニアが関わってるんだろうなあ、と思いました。デバッグ用と思われる console.log が残っているのはご愛嬌ですが、JavaScript 以外の HTML でも例えばこんな感じの記述がされています:
2015013101


いやあ、わかりやすい(笑)。 <div> でちゃんとパーツ化されている上に HTML コメントが非常に適切で、実際の画面を見なくてもどういうページを作ろうとしているのか想像できます。感心してる場合じゃないけど、これ作った人とは話が合いそう。。 (^^;

そしてもう1つ気になったこと。それは上記で紹介した僕のブログエントリ
HTML5 の pushState/popState でヒストリバックを無効にする

で紹介している JavaScript の内容と、このサイトで実際に使われている JavaScript の内容が変数やコメントの使い方のレベルで非常に似ている、というか似すぎている!? あれ?もしかして参照してくれた!? ということに気付いてしまいました。 良い子はこういう使い方に応用しないでね。 d(o^ )

#念のため補足しておくと、僕が紹介した無効化は問い合わせフォームなどで 入力→確認→送信 みたいなページ遷移をする時に 送信後のページから確認ページに戻られると色々不都合があるので、そういった挙動をさせなくするための手段として紹介したつもりでした。


というわけで、メンテナンス性も含めた色んな意味で意外と完成度の高い詐欺サイトでした。




 

HTML5 で追加された JavaScript の History API を使うと、ブラウザのヒストリ履歴(戻る/進む)の中身を操作できます。これを使って「戻る」を無効にしたページを作ってみます。jQuery を使うので、必要に応じてロードしておきます。

History API では pushState メソッドで履歴を1つ追加、popState メソッドで履歴を1つ(新しいものから)取り出します。この2つを組み合わせて、以下の様なロジックを実装しています:
- ページロード時に強制的にニセの1つ履歴を追加
- そのページ内で「戻る」イベントが発生したら(追加したニセの履歴が取り出されるので)、再度ニセの履歴を1つ追加して処理を終了(return)する

<script>
// History API が使えるブラウザかどうかをチェック
if( window.history && window.history.pushState ){
  //. ブラウザ履歴に1つ追加
  history.pushState( "nohb", null, "" );
  $(window).on( "popstate", function(event){
    //. このページで「戻る」を実行
    if( !event.originalEvent.state ){
      //. もう一度履歴を操作して終了
      history.pushState( "nohb", null, "" );
      return;
    }
  });
}
</script>

これでブラウザの「戻る」ボタンをクリックしても、本来の1つ前の URL ではなく、偽装した履歴が取り出されます。このままですとその偽装した履歴の URL に移動してしまう(今回は "" を指定しているので飛びようもありませんが)のですが、その前に return で強制的に処理を止めているので何も起こりません。また履歴を取り出した直後に再度ニセの履歴を追加しているので、更にもう一度「戻る」をクリックしても同じ処理が繰り返されて、結局戻れない、ということになります。

ちなみにこのブログのエントリの中にもこの JavaScript を埋め込んであります。なので、History API が使えるブラウザでこのページを見ている状態からは「戻る」を押してもどこにも戻れないはずです。


これ、うまく使うと「戻る」ボタンを押した時に本来とは異なるページに強制移動させることもできちゃったりするんじゃないかな。。



このページのトップヘ