yukata

日々出会ったIT技術関連の所感やら紹介やら

HTMLの属性値はなんでダブルクォートで囲むことが推奨されているのか考えてみた

最近セキュリティの勉強をしています。

その中で一つ疑問に思って色々調べてみたけど、なかなか理由がわからないことがありました。

それは、HTMLの属性値を「"(ダブルクォート)」で囲むことを推奨していることです。

HTMLの属性値は、クライアントから受け取った値を使って動的に生成している場合、クロスサイトスクリプティングの脆弱性が発生してしまいます。そのため、HTMLエスケープする必要がありますが、「'(シングルクォート)」や「"(ダブルクォート)」の引用符で囲まなければ、たとえエスケープしていてもクロスサイトスクリプティングが可能です。

例えば以下のように、攻撃文字列の間にスペースを入れます。

<input type=text name=name value=<?php echo(htmlspecialchars($_GET())); ?>>
↓
<input type=text name=name value=hogehoge onmouseover=alert(1)>

このように、クロスサイトスクリプティングが成立してしまいます。ただ、なぜ「'(シングルクォート)」ではなく、「"(ダブルクォート)」で囲むことが推奨なのかがわかりませんでした。なぜ「'(シングルクォート)」じゃいけないのか・・・



「"(ダブルクォート)」の推奨に関しては、徳丸本とか、その他いろんなところで、そんな感じのことが書いてありました。


この件に関して、私の調査不足かもしれませんが、検索してもなかなかわからなかったので、以下のように推測してみました。


  1. 動的にHTMLの属性値を生成するとき、クロスサイトスクリプティング対策のため、属性値をHTMLエスケープし、且つ「'(シングルクォート)」か「"(ダブルクォート)」で囲む
  2. HTMLをデバッグするときにソースコードを見るが、不必要な文字列までエスケープされてしまうと、デバッグがしにくい
  3. 英語圏では、日常的に文章等に「'(シングルクォート)」が利用されるので、デフォルトでは「<」、「>」、「&」、「"」の必要最小限のみをエスケープするように関数を作成
  4. エスケープ用の関数を利用する際に、デフォルトでは「'(シングルクォート)」がエスケープされていないことを知らずそのまま使ってしまう。そして属性値を囲む引用符にポリシーがないまま開発してしまい、クロスサイトスクリプティングの脆弱性を作ってしまう
  5. そのため、HTMLの属性値は「"(ダブルクォート)」で囲むことを推奨している


と、こんな感じで考えてみました。

なので、「'(シングルクォート)」で囲ってはいけないわけではなく、デザイナーとか、低レベルのプログラマの人とかと連携して開発する場合は、とりあえずHTMLの属性値を「"(ダブルクォート)」で囲むことを徹底させておけば、脆弱性が作り込まれる可能性を少しでも低くできるんじゃないかということです。

XMMPボットサンプル

たいぶ古いけど、以下を参考にXMPPのボットのサンプルを試してみました。

http://d.hatena.ne.jp/Syo-Takasaki/20071121/1195644386

  • 環境
    • OpenFire version 3.8.1
    • ruby 1.9.3


OpenFireに対してTLSで接続しようとすると、なんかうまくいかないようです。

Jabber::Client.new した後に、インスタンスの中のスコープで
@allow_tlsをfalseにするとうまくいきました。

require 'xmpp4r'

user = "USER@DOMAIN"
pass = "PASS"

client = Jabber::Client.new(Jabber::JID.new("#{user}/bot"))
client.instance_eval do
  @allow_tls = false
end
client.connect('HOST', PORT)
client.auth(pass)
client.send(Jabber::Presence.new.set_show(:chat))
puts "Connected ! send messages to #{user}."

mainthread = Thread.current
  client.add_message_callback { |msg|
    if msg.body
      puts "from:#{msg.from} body:#{msg.body}"

      m2 = Jabber::Message.new(msg.from, "ECHO:#{msg.body}")
      m2.type = msg.type;
      client.send(m2)

      # Exit
      if msg.body == 'exit'
        m2 = Jabber::Message.new(msg.from, "Exiting ...")
        m2.type = msg.type;
        client.send(m2)
        mainthread.wakeup
      end
    end
  }
Thread.stop;
client.close;
puts("Done.");

ubuntu12.04にmod_mrubyをインストールしたときの手順メモ

MacのVirtualBox上にubuntu12.04を入れて、そこにmod_mrubyをインストールしました。以下のURLを参考にさせて頂きました。

http://d.hatena.ne.jp/techmedia-think/20120618/1340021311


ubuntu上で以下のコマンドを実行していきます。最小構成でのインストール直後の状態です。

開発ツールインストール

# aptitude install build-essential
# aptitude install libreadline-dev libssl-dev zlib1g-dev
# aptitude install git-core curl

aprのインストール

# cd /var/tmp
# mkdir work
# cd work/
# wget http://ftp.jaist.ac.jp/pub/apache//apr/apr-1.4.6.tar.gz
# wget http://ftp.jaist.ac.jp/pub/apache//apr/apr-util-1.4.1.tar.gz
# tar zxf apr-1.4.6.tar.gz 
# cd apr-1.4.6/
# ./configure 
# make
# make install
# cd ..
# tar zxf apr-util-1.4.1.tar.gz 
# cd apr-util-1.4.1/
# ./configure --with-apr=/usr/local/apr
# make
# make install
# cd ..

pcreのインストール

# wget -O pcre-8.32.tar.gz "http://sourceforge.jp/frs/g_redir.php?m=jaist&f=%2Fpcre%2Fpcre%2F8.32%2Fpcre-8.32.tar.gz"
# tar zxf pcre-8.32.tar.gz
# cd pcre-8.32/
# ./configure
# make
# make install
# cd ..

apacheのインストール

# wget http://ftp.kddilabs.jp/infosystems/apache//httpd/httpd-2.4.3.tar.gz
# tar zxf httpd-2.4.3.tar.gz 
# cd httpd-2.4.3/
# ./configure --enable-mods-shared=all --with-apr=/usr/local/apr --with-apr-util=/usr/local/apr
# make
# make install
# cd ..
# /usr/local/apache2/bin/apachectl start
usr/local/apache2/bin/httpd: error while loading shared libraries: libpcre.so.1: cannot open shared object file: No such file or directory

# ln -s /usr/local/lib/libpcre.so.1 /lib/libpcre.so.1
# /usr/local/apache2/bin/apachectl start

Rubyインストール

# aptitude install ruby1.9.1
# gem install rake

mod_mrubyのインストール

# git clone https://github.com/matsumoto-r/mod_mruby.git
# cd mod_mruby/
# git submodule init
# git submodule update
# cd mruby/
# rake CFLAGS="-O3 -fPIC"
・・・
rake aborted!
Command failed with status (127): ["bison" -o "build/host/src/y.tab.c" "src/p...]
tasks/mruby_build_commands.rake:29:in `_run'
tasks/mruby_build_commands.rake:169:in `run'
src/mruby_core.rake:14:in `block (2 levels) in <top (required)>'
Tasks: TOP => default => all => bin/mruby => build/host/bin/mruby => build/host/lib/libmruby.a => build/host/src/y.tab.o => build/host/src/y.tab.c
・・・
# aptitude install bison
# rake CFLAGS="-O3 -fPIC"
# cd ..
# vi Makefile.in   //以下2行を修正
  APXS=/usr/local/apache2/bin/apxs
  APACHECTL=/usr/local/apache2/bin/apachectl
# ./configure
# make
# make install

  ※Warningは無視していいとのこと。
  https://twitter.com/kyonfuee/statuses/282029734152507392

# /usr/local/apache2/bin/apachectl restart

mod_mrubyのサンプル作成

# cd /usr/local/apache2
# vi htdocs/test.mrb
  r = Apache::Request.new()
  r.content_type = "text/html"
  Apache.rputs("<h1>test</h1>")
  r.filename = "/usr/local/apache2/htdocs/index.html"
  Apache.return(Apache::OK)

# vi conf/httpd.conf
・・・
AddHandler mruby-script .mrb     //追記
・・・
<IfModule mruby_module>           //追記
  mrubyTranslateNameFirst /usr/local/apache2/htdocs/test.mrb
</IfModule>

# bin/apachectl restart


適当なURLにアクセスして、
うまくでっかい文字でtestとIt works!が表示されればOKです。

Gehirn(ゲヒルン)のRS2登録と、baserCMSのインストール

Gehirn(ゲヒルン)のRS2がどんなものか試してみたくて登録してみました。デフォルトでPHPが使えますので、とりあえずbaserCMSをインストールしました。

特に難しい手順はなく、と言うかびっくりするぐらいにあっさりと完了し、しかも標準でWAF(Webアプリケーション・ファイアウォール)がついているので、アプリケーションのセキュリティも高く保てます。

以下、簡単ですが手順を書いておきます。


Gehirn(ゲヒルン)のRS2を登録


1. まずはGehirn(ゲヒルン)でアカウントを取得
https://cp.gehirn.jp/#!/register

2. コントロールパネルから請求先情報を登録する
https://cp.gehirn.jp/#!/ID/account

3. RS2を新規契約
https://cp.gehirn.jp/#!/RS2/signup

※詳細な手順は以下に記載されています。
http://support.gehirn.jp/manual/rs2/idcreate/


SSHでログイン

コントロールパネルのRS2の、契約一覧から、対象プランの「設定」ボタンをクリックします。

次に、SSHタブから、「公開鍵の管理」ボタンをクリックし、

そこから、「キーペアを生成する」ボタンをクリックしてPKCSの2048bitでキーペアを生成すると、ローカルPCに秘密鍵がダウンロードされます。

そしてダウンロードした秘密鍵の権限を変更し、その鍵を指定してGehirn RS2のサーバへSSHログインします。

$ chmod 600 xxxxx.key  // ダウンロードされるファイル名は毎回異なります
$ ssh -i xxxxx.key [SSHユーザ名]@[IPアドレス]


baserCMSインストール

ドキュメントルート以下に(コントロールパネルで設定可能)、baserCSMをダウンロードし、展開します。

$ cd /home/{ホスト名}/public_html
$ wget http://basercms.net/packages/download/basercms/2.0.5.1
$ unzip 2.0.5.1


mysqlのデータベースを作成します。
コントロールパネルのRS2タブから、データベースタブをクリックし、「データベースを追加する」ボタンをクリックしてデータベースを作成します。
今回は手動で登録はありませんが、以下のようにデータベースへアクセスできます。

$ mysql -u {ユーザ名} -p  // ※ユーザ名は、登録したデータベース名と同じ


そしていつも通り下記のURLへアクセスし、インストールを開始します。

http://{ホスト名}/basercms

rubyでdowncase VS 正規表現

ついでにupcaseも。

大文字と小文字を区別せずに大量のデータを比較する場合、downcaseが速いのか正規表現の方が速いのか、確認してみました。コードは以下です。(こんなんでいいかな・・・?)

require 'benchmark'

a = "BaNaNa RiNgo BuDo IchiGO"
b = "banana RINGO budo ICHIGO"
n = ARGV[0].to_i

puts Benchmark::CAPTION
puts Benchmark.measure{ n.times { a.downcase == b.downcase } }
puts Benchmark.measure{ n.times { a.upcase == b.upcase } }
puts Benchmark.measure{ n.times { a =~ /^#{b}$/i } }


実行結果は以下です。1000回、10000回、100000回で実行しました。

$ ruby test.rb 1000
      user     system      total        real
  0.000000   0.000000   0.000000 (  0.000889)
  0.000000   0.000000   0.000000 (  0.000854)
  0.000000   0.000000   0.000000 (  0.004305)

$ ruby test.rb 10000
      user     system      total        real
  0.010000   0.000000   0.010000 (  0.011290)
  0.010000   0.000000   0.010000 (  0.010139)
  0.040000   0.000000   0.040000 (  0.040895)

$ ruby test.rb 100000
      user     system      total        real
  0.100000   0.000000   0.100000 (  0.095221)
  0.090000   0.000000   0.090000 (  0.094485)
  0.370000   0.010000   0.380000 (  0.382025)

断然downcase(upcase)の方が速かったです。
世の中の常識ですかね?
今まで調子に乗って正規表現でやってました。
反省します!

dotcloudでデプロイしようとしたらコマンドをアップロードしろって言われた

dotcloudでデプロイしようとしたらいきなりこんなこと言われたのでメモ。

$ dotcloud push --all [アプリ名]
Warning: A new version of the DotCloud cli is available: 0.9.1
This new version is an important update and several changes have been made to improve developer workflow and usability.
You can learn more about migrating here: http://docs.dotcloud.com/0.9/guides/migration/
When you're ready, you can run the following commands to upgrade to the latest version:
$ sudo pip uninstall dotcloud dotcloud.cli
$ sudo pip install --upgrade dotcloud


とりあえず以下でデプロイできました。
なんかコマンドのオプションが変わっていますね。また必要に応じて調べることにします。

$ sudo pip install --upgrade dotcloud
$ dotcloud push -A [アプリ名]

PHP Matsuri 2012 参加してきました!

PHP Matsuri公式サイト

まず、参加してよかったこと。

それは、自分がどんだけしょぼいかってことを再確認できたことです・・・みなさんすごかった。レベルが高い。。まだまだ自分も頑張らなくては・・・(涙)

やってることのレベルも高いですし、なによりプレゼンがうまい人が多かった印象があります。みんな慣れてるって感じで、話もすごく面白くて爆笑の嵐でした。とは言っても、初心者やレベルの低い人たちにも優しくウェルカムな感じで、色々とサポートしてくれますし、誰でも安心して参加できるんじゃないかなーと思います。PHP知らなくてもきっと大丈夫です!!でもノートPCは必ず持って行きましょう。一応ハッカソンなので(笑)


それから、闇で行われた「アンリーダブルコード選手権」もめちゃくちゃ面白かったです(この時点で深夜0時)。異様な音楽とともにへんなグラサンをかけた関西弁の2人組があらわれ、続いて発表者が5人、顔がばれないように覆面で登場してきました。でも知ってる人には余裕でばればれ。全員の話が、もれなく面白かったです。ちょっと耳が痛いところもいくつかありましたが、さすがにこれはないわー(笑)っていうコードばかりでした。以下、セッションの一つ。スライドを上げてくれたようです。
https://speakerdeck.com/komagata/i-dont-like-such-a-php-project

f:id:maehira:20121103232516j:plain


そして深夜に行われたファミコン大会(このとき、1時か2時くらい)。一生懸命コード書いてる後ろでピコピコやってました。音が懐かしすぎて、気になって気になって仕方ありませんでした・・・

f:id:maehira:20121104005124j:plain


そして、あっというまに夜も明け、LT大会が始まりました。これも非常にレベルが高かった。やってる内容も、プレゼンも。ジャンルも幅広くて色々勉強になりました。

内容はこの辺にまとめられています。
http://togetter.com/li/400807


自分が今回やったことは、複数人でのWebアプリケーション開発です。PHPMatsuriなので、一応CakePHPを使いましたが、ほぼJavaScript(Pusher(Websocket)、JQuery含む)でした。セッションの合間と、一晩丸々使ってかなり進みましたが、思ったところまで進まず、LTは断念。。無念。。。次回は必ず・・・

それにしてもあの大トリをつとめた13歳のガ・・・子どもはなんだったんだろう・・・やけに場慣れしてる感じで、見た目は子ども、振る舞いは大人、コナン君かと・・・


まあなにはともあれ、楽しくてあっという間の2日間でした。とりあえず、ほとんど寝てないので寝ます!