珍しいJavaScript

珍しいものが出てくる。ワームが使っていたJavaScriptである。今回は実行されているのがconfirmで実害はなかったが、これからは要注意である

1
これはログの中にJavaScriptが入っているということである。
いわゆるクロスサイト・スクリプトである。



2
では、そこには何が書かれていたのか。生ログは次のようになっている。
クエリ・キーワードを query, search, q, s などに変化させているだけの違いである。いろいろなパターンをワームが挑戦して、「ヘタな鉄砲も数打ちゃ当たる」ということをしていることがわかる。
そして、こういうところに一般的な英語を使うのはその「ヘタな鉄砲」に「当たる」可能性が高くなるので避けたほうがよいこともわかる。
となると、「takoyakiyaketa」(タコヤキ焼けた)などの日本語をローマ字化したものなら多分この「鉄砲」には当たらないだろう(笑)。
LOG
62.224.189.78 - - [29/Jan/2019:06:34:35 +0900] "GET /query?search=%22%3E%3Csvg/onload=confirm(/keqc0/)%3E&s=%22%3E%3Csvg/onload=confirm(/keqc1/)%3E&query=%22%3E%3Csvg/onload=confirm(/keqc2/)%3E&q=%22%3E%3Csvg/onload=confirm(/keqc3/)%3E HTTP/1.1" 404 276 "-" "curl/7.37.0"
62.224.189.78 - - [29/Jan/2019:06:34:35 +0900] "GET /search?search=%22%3E%3Csvg/onload=confirm(/keqc0/)%3E&s=%22%3E%3Csvg/onload=confirm(/keqc1/)%3E&query=%22%3E%3Csvg/onload=confirm(/keqc2/)%3E&q=%22%3E%3Csvg/onload=confirm(/keqc3/)%3E HTTP/1.1" 404 277 "-" "curl/7.37.0"
62.224.189.78 - - [29/Jan/2019:06:34:35 +0900] "GET /q?search=%22%3E%3Csvg/onload=confirm(/keqc0/)%3E&s=%22%3E%3Csvg/onload=confirm(/keqc1/)%3E&query=%22%3E%3Csvg/onload=confirm(/keqc2/)%3E&q=%22%3E%3Csvg/onload=confirm(/keqc3/)%3E HTTP/1.1" 404 272 "-" "curl/7.37.0"
62.224.189.78 - - [29/Jan/2019:06:34:36 +0900] "GET /s?search=%22%3E%3Csvg/onload=confirm(/keqc0/)%3E&s=%22%3E%3Csvg/onload=confirm(/keqc1/)%3E&query=%22%3E%3Csvg/onload=confirm(/keqc2/)%3E&q=%22%3E%3Csvg/onload=confirm(/keqc3/)%3E HTTP/1.1" 404 272 "-" "curl/7.37.0"

3
これらはどれも同じだから、最初の一つだけをみておくと次のようになる。
LOG
62.224.189.78 - - [29/Jan/2019:06:34:35 +0900] "GET /query?search="><svg/onload=confirm(/keqc0/)>&s="><svg/onload=confirm(/keqc1/)>&query="><svg/onload=confirm(/keqc2/)>&q="><svg/onload=confirm(/keqc3/)> HTTP/1.1" 404 276 "-" "curl/7.37.0"
ログの処理はCGIを基本にしてきたが、次のようなタグの無効化(サニタイジング)はもう定式化してどのCGIの冒頭にも入っている。

SAMPLE
$line =~ s/</&lt;/g;
$line =~ s/>/&gt;/g;

したがってCGIではこういうことは起こらない。



4
しかしPHPでは見落としがあった。もともとログの処理はCGIがメインだから、PHPでは少し変わった形にしている。
CGIは単なる一括処理だが、PHPでは日付による抽出にした。この日付の自動設定(デフォルトでは実行した日になる)に手間取ってしまい、そのときにタグの無効化をコロッと忘れていたようである。とりあえず画面表示の直前にそのルーチンを入れておく。

SAMPLE
$line = str_replace("<", "&lt;" ,$line);
$line = str_replace(">", "&gt;" ,$line);
echo $line . "<br>\n";

こうすると不快現象は起こらなくなったようである。



検討

HTML5になってからJavaScriptが標準装備になった。これからはこういうスクリプトが普通に埋め込まれて出てくることが予想される。

SAMPLE
<svg/onload=alert(/篠崎愛/)>



要点
  1. 「<svg/onload=***>」が「<script>***</script>」と同等の動作をする。「***」はJavaScriptの関数などの動作を記述する。

  2. 「/***/」は「"***"」または「'***'」と同じ動作。
    Perlなどのクオートとよく似ている。しかし、alertなどでは「//」は文字と同じように表示されている。
    この部分を「"***"」としても動作は同じである。この場合、alertなどでは「""」は表示されない。

  3. 後に書いたものが先に実行される。
    「<svg/onload=alert(/本田美穂/)><svg/onload=alert(/篠崎愛/)>」の場合、「篠崎愛」→「本田美穂」の順に表示される。

  4. フォーカスを専有する。
    これは通常のJavaScriptのalertやconfirmと同じ。
    しかし、JavaScriptの場合は、その記述がある所で表示がストップするが、この場合は最後まで表示がなされる。

珍しい形のJavaScriptであっても、対策の基本はタグの無効化である。今回はこれを見落としていたので不快現象が起こってしまったことになる。

- 2019/01/29 -