PostgreSQLでのSQLインジェクションでシステムコマンド実行

https://www.postgresql.org/docs/9.3/static/sql-copy.html

今朝気づいたが、バージョン9.3以降では、COPYコマンド経由(PROGRAM)で外部コマンドを簡単に起動できる。xp_cmdshellの亡霊が再び…なんちゃって…


セッションIDをCSRFトークンに使うべきでない理由

malaさんも2年程前に書かれているのですが、未だに国内のCSRF対策の解説で「セッションIDをCSRFトークンとして使う」というアイデアが披露されていて辟易します。

喩え話は好きでないですが、「複数のサイトで同じパスワードを使っていたら一箇所から漏洩し、パスワードリスト攻撃を受けた」というのを彷彿します。セッションIDとCSRFトークンは単純に別の値にした方がいいです。

さてこのエントリの本題はここからで、CSRFトークンよりもむしろセッションIDの方です。最近は443番ポートへクロスサイトでリクエストを大量に送らせてそれをキャプチャし、すべてのリクエストに共通して含まれてくるCookie中のセッションIDを解読するBEAST/CRIME系の攻撃が知られるようになりました。

これらは基本的にはTLS/SSLの問題でありそれぞれ個別に対策が存在しているものの、基本的には「セッションIDがずっと同じ値である」という部分、HTTP特有の仕組みを攻撃対象としています。(攻撃対象がBasic認証などの場合はこの限りではないです)

これを受けて「何千もリクエストが勝手に送られている間、セッションIDがずっと同じなのって間抜けだよね?」と考えるのがまともな感覚だと思うのですが、いかがでしょうか。つまりセッションIDがずっと同じであるという実装の常識をそろそろ変えていくべきだと思います。あくまで保険的な対策となると思いますが、今後登場するかもしれないBEAST/CRIMEの発展形を防ぐ可能性が高いと考えます。

一部、セッション固定により「ログインしたタイミングでセッションIDを変える」ということは良く知られており実践されていますが、そもそもセッションIDはコロコロ変えるべきなのです。

さて話はCSRFトークンに戻りますが、セッションIDの値をそのままCSRFトークンとして使ってしまっていると、上記のように「セッションIDを頻繁に変更する」ということができなくなってしまいます。なのでセッションIDの値をCSRFトークンにするのはやめましょう。

「…やめましょう」とか書きましたが、別の件(CSRFトークン インタビューズ)でシェアの高いいくつかのフレームワークについて調べてみたところ、そもそもセッションIDの値をそのままCSRFトークンにしているものをひとつも見つけることができませんでした。もし見つけたら教えてください。

なんか、ガラパゴス的な議論をしていたようで脱力します。


非線形データに普通のKMeansを使う

1,2,2,2,3,3,4,10,10,11,11,11,12,12,12,12,13,13,25,25,26,26,26,27,28,28,29,29,29,29,30,30,30,31

例えば上記のような1次元のデータがある場合を考える。ある小学校のクラスで行われた簡易テストの点数のようなイメージだ。「1点の生徒が1人、2点の生徒が3人・・・31点を取った生徒が1人」という感じである。

nonlinear2

ヒストグラムは上記のようになる。ここで色分けは意図的に行っている。

  • 赤は落ちこぼれ
  • 緑は普通の生徒
  • 黒はよくできるグループ

のように、いわゆるラベル分けを行うことができる。繰り返しになってしつこいが、これは意図的なラベル分けだ。

ここでは3つに分類すると決めており、データは人間から見ると自然に3つに(ヒストグラム上で)別れている。各グループ間は線形分離が可能だ。

このような場合、KMeansクラスタリングでk=3とすると完璧にクラスタリングしてくれる(ことが多い)。「ラベルが3種類だから、k=3とする」というごくありがちなアプローチである。

a <-c(1,2,2,2,3,3,4,10,10,11,11,11,12,12,12,12,13,13,25,25,26,26,26,27,28,28,29,29,29,29,30,30,30,31) 
> kmeans(a,3)
K-means clustering with 3 clusters of sizes 16, 11, 7

Cluster means:
[,1]
1 28.000000
2 11.545455
3 2.428571

Clustering vector:
[1] 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

Within cluster sum of squares by cluster:
[1] 56.000000 10.727273 5.714286
(between_SS / total_SS = 98.1 %)

Available components:

[1] "cluster" "centers" "totss" "withinss" "tot.withinss"
[6] "betweenss" "size" "iter" "ifault"

仮に今回のケースが、ラベル有りで上記データが提供されていて、KMeansでモデルを作り、新たなデータを「落ちこぼれ」「普通」「よくできる」のいずれかに分類したいという状況だとする。この場合、データが上記kmeansの実行で得られたクラスタ中心(28, 11.5, 2.4)のどれに一番近いか?を判断するだけで良い。

しかし、ラベルが3種類ではなく、下記の2種類だったらどうなるだろうか。

nonlinear3

ここでラベルが以下の2つであるとする。

  • 緑は「普通でない生徒」
  • 赤は「普通の生徒」

突如、緑に属するデータは非線形な集まりとなってしまう。先ほどと同じようにKMeansでモデルを作り、新たなデータを分類する問題として考える場合、先ほどと同じアプローチで「ラベルが2種類だからk=2でクラスタリングしよう」と思っても当然うまくいかない。

ここで「くそっ、KMeansは非線形データに弱いんだぜ…」と考えてカーネル関数とかそっちに走るのもひとつの手だが、もっと超簡単な方法がある。というかこのブログエントリを先頭から読めば自然に気づくと思うが、「ラベルが2種類だからk=2」というのを「ラベルは2種類だけどk=3でやってみよう」とするだけである。

そして、実際の分類の際には

  • 1つめのクラスタ中心に近ければ「普通でない生徒」
  • 2つめのクラスタ中心に近ければ「普通の生徒」
  • 3つめのクラスタ中心に近ければ「普通でない生徒」

というロジックに従えばOKである。

クラスタリング結果をそのまま分類に使うのではなく、クラスタリング結果にもうひとつだけ処理を追加するだけでよい。クラスタリングはあくまでも数値処理で、人間がそれをうまく解釈してやるだけの話だ。

あまりにも簡単な話なのだが、意外と目にしない(私の探し方が悪いだけかもしれないが)ので、ブログに書いてみた。


自宅で働くJavaプログラマになって13年経過したのでメモ

当時は「SOHO」というキーワードで知られている、いわゆる在宅勤務。私は2002年頃からずっとやっていて…
まぁ誰かの参考になる可能性もあるかと思ってメモします。

まず、私の在宅勤務がどんなものかを簡単に。

私は2002年頃に「株式会社ビットフォレスト」というスタートアップを立ち上げた、いわゆるファウンダーです。そのため、世の中の人が「在宅勤務」で想像するであろう「雇われている」形態ではありません。ここは非常に大きなポイントになると思います(要するに自分がさぼると、きっちりツケが廻ってくるという意味で)。

場所は横浜市の南の方で、「下永谷」という名前の、駅前に何もない場所でやっています。最近、ついに駅前にコンビニが出来ました。どうでもいい。
在宅勤務を始めるよりも前に結婚しており、一人暮らしではありません。

会社のオフィスは、立ち上げた当時は存在せず、全メンバーが在宅勤務でしたが、数年後に四谷三丁目にオフィスを構えました。現在は在宅勤務しているメンバーは私を含め数名いますが、多くはオフィスで仕事をしています。

仕事の内容はソフトウェア(あるいはウェブサービス)の開発で、2002年頃からずっとJavaを使っています。なので、勤務時間中、殆どの時間はコードを書いていることになります。

なぜ在宅勤務にしたか?

大きく4つ理由があり、

  • オフィスでなくても仕事ができる(オフィスのコストの削減が可能)
  • 満員電車が苦痛
  • 通勤時間がもったいない
  • 集中できる

というものです。特に説明しなくてもよいですね。(1つめについては、その後結局オフィスを構えてしまいましたが・・・)

さて実際にやってみた感じは次の通りです。

むちゃくちゃ集中できる

仕事をしている時間は、同居している家族はそれぞれ仕事や学校で出払っていることが多いため、自宅にはひとりという状態になります。
場所が住宅地で、外も静かなため、数時間続けて集中してコードを書くことができます。

途中誰かから話しかけることがなく、また電話が鳴ることも殆どないため、プログラマにとっては理想的な作業環境です。非常に生産性が高く、また基本的に毎日そのような環境で仕事を継続的に行うことができます。

数年間でのトータルのアウトプット量で考えた場合、かつてサラリーマンとしてオフィスに通勤していた頃よりもはるかによい結果が出せていることは間違いないと思います。この点については今振り返ってみて、本当によい選択(時間を無駄にしなかったという意味で)だった思います。

ストレスが少ない

部屋に連続して数時間以上一人でいるという状態は、非常にストレスが少なく済みます。他の人の音やしゃべり声、ニオイなどがないので、心が乱されることがありません。また、例えばウ○コしたくなったらすぐトイレですればよいだけです。例えば下痢をしている日には、15分おきにトイレに入っても何も問題ありません。オフィスの場合、15分おきにトイレにいくのって結構周りの目が気になってつらいですよね。そういう生理的な欲求などを我慢する必要がない点についても、在宅勤務は優れていると思います。

自己管理が要求される

誰もいないので、誰も注意してくれません。私は太ってはいませんが、例えば異常な量のお菓子をバリバリ食べていても、誰も「食べ過ぎじゃない?」と言ってくれません。そのため食欲をはじめ、色々な面で自らの堕落を自ら節する必要があります。自己管理が苦手な人は在宅勤務は向いていません。

さみしいか?

在宅勤務のデメリットとして「寂しさ」が挙げられるケースがありますが、私は幸い家族がいることもあり、その点を感じたことはありません。在宅勤務の後は呑みに行く仲間はいないので、頻繁に仲間と呑みに行きたい人には辛いかもしれません。

どんな職業に向いているか

プログラマーのように、コンピュータだけあれば完結するような仕事が向いていることは言わずもがなです。他には、その人が雇われているのか、自営なのかが大きなポイントだと思います。自営の場合にはピーク時には頑張って稼ぎ、それを過ぎたら休みを増やしてのんびりすることもやりやすいですし、さぼると自分の収入が少なくなるため自制もやりやすい面があるでしょう。

また、在宅勤務には「面白い」と思える仕事が向いていると思います。

働きすぎる

37signalsの本にありましたが、在宅勤務で注意が必要なのは「さぼること」ではなく「働きすぎること」ですw。

朝食を済ませたらコーヒーを淹れて即仕事が開始できますし、また夜も仕事を終えたら10分で眠れてしまうため、どうしても仕事をしすぎになります。私の場合、コードを書くことは仕事でもあり趣味でもあるため、この点については我ながらダメだなと思います。

以上、誰かの参考になれば。


コモディティサーバ戦略のパラドックス

servers

今さら確認するまでもないが、サービスの成長に合わせてこまめにサーバリソースを追加し、負荷をうまく分散して処理していく戦略がスケールアウトで、図の上がこれを示す。
主に安価なコモディティサーバを使うイメージである。

一方、図の下は、最初から高価で高性能のサーバを買ってしまい、それをぎりぎりまで使い切って、あるタイミングでまた高性能のサーバを追加するイメージである。まぁ、一昔前まで当たり前だと考えられていたアプローチである。

上だと最終的に6台のサーバが、下だと最終的に2台のサーバがある感じである。

図中の青い部分が「買ってしまったけど使っていない」リソースであって、無駄なコストである。

上の方が、青い部分の面積は小さく、無駄なコストを省くことに成功している。スケールアウト戦略を選択する理由にはいくつかあるが、そのうちでポピュラーなものがこの「無駄なコストの削減」である。

しかしこのときサーバ台数は増えてしまっているので、DatadogやMackerelのような「サーバ毎に課金される」サービスを利用する場合には、料金もきれいにスケールしてしまう。

貧者の戦略としてコモディティサーバを選んだのに、価格が高くなってしまうのだ。

でもまぁ、台数が増えたらサーバ管理の手間は増えるから、「サーバ管理を助けるサービス」の使用料が高くなるのは当たり前だよ、って言われると納得するかも…


Deep Learningで人工知能が実現するとかいってる人たち、あるいはそういう見出しの記事を書きたい記者が正座して読むべき記事

Facebookでケンタロさんに教えてもらった記事。
http://spectrum.ieee.org/automaton/robotics/artificial-intelligence/facebook-ai-director-yann-lecun-on-deep-learning

僕も一時期(2014年の12月から2015年の1月)にDeep Learningについてかなり時間をかけて調べてみたけど、結局明らかに達成されていることは「精度の高い教師あり学習ができる」ということであって、人のように抽象化思考を行う何かがそこから発現するとは思えないと考えていた。(フリーソフトではじめる機械学習の、WEKAでのニューラルネットの章で、オートエンコーダーによってコンピュータが自動的に二進数の概念を獲得するところは興奮したけど。)

We had quite a bit of success with this, but in the end, what ended up actually working in practice was good old supervised learning

また、下記の部分などは僕が好きな苫米地氏がずっと前から表明しているのと同一の見解だと思う。

The bottom line is that the brain is much better than our model at doing unsupervised learning. That means that our artificial learning systems are missing some very basic principles of biological learning.

個人的には、人工知能(強いAI)を作るには、「痛み」「快楽」「生」「死」のような生命の根源に直結する概念、欲求を教えないとダメだと思う。痛みや死から逃げるための判定を最優先させる。このときは低い抽象度で。死から遠いところでの活動には、より抽象度の高い学習や判定を行わせていく。


Windows XPは使い続けてはダメだけどStruts1は使い続けてもいい理由

1行まとめ: OSSだからヽ(´ー`)ノ

ソフトウェアのライフサイクルの問題は、僕自身が10年以上続いているウェブサイトやウェブアプリをいくつかメンテナンスしていることもあり、非常に興味がある。
WindowsXPのように商用のソフトウェア場合、マイクロソフト以外がパッチを発行するわけにいかないので、「サポート終わりです」と言われたらもう使い続けることができない、という結論になるだろうと思う。

でもStruts1のケースは、WindowsXPとはまったく違う。「Struts1はEOLです」としているのはあくまでもStruts1の事実上の開発主体であったApache Software Foundationであり、ソースコードの改変の自由については、もちろん保たれたままだ。だから、Forkして自由に機能追加やバグ(脆弱性)修正を行うことができる。

今回話題になったClassLoaderにアクセスできる脆弱性などは、修正すること自体はそれほど難しいものではない。そのため、別に慌てることなく、淡々とパッチを開発して、それを適用すればよいという話になる。

go.jpやco.jpで拡張子が.doだからといって、叩かれる必要はない(もちろん今回の脆弱性に対する対策は何かしらするべき)。

僕自身では、ついこの間までPHP4.3という古いバージョンのウェブアプリケーションを運用していた。PHPのソース(C言語で書かれている部分)を読んでパッチを開発するというのはちょっと厳しかったので、基本的に脆弱性等の対策はWAFでやるというスタンス。