どの言語で書いてもおかしなコードを書く奴は書く

Computer, Security 1月 31, 2008
(Last Updated On: 2013年12月1日)

# 書きかけです。後で編集予定

「Web屋のネタ帳」のどの言語で書いてもおかしなコードを書く奴は書くに対するコメントです。その記事にはRubyのまつもと氏のブログの引用もあるのでそちらにも対するコメントでもあります。

言語が良いコードを書けるようサポートする事はできると思います。しかし、言語だけによって良いコード(安全なコード、メンテナンスし易いコードなど)が書けるようにはならないのではないでしょうか? 言語だけでは不十分だからです。

「どの言語で書いてもおかしなコードを書く奴は書く」とは昔から言われてきた事です。同じ人がおかしなコードを書きつづける場合もあるとは思いますが「どの言語のユーザでもおかしなコード(危険なコードであったり、メンテナンスが難しいコード、無駄が多いコード)を書く人はいるものだ」の意味で使われていると思います。

言語によってセキュアな物ができる、できない、の話になるとレベル合わせが必要だと思います。

PHPが作られた当初はともかく、現代では(セキュリティ的に弱いものができあがってしまいがちという意味で)害悪ではないだろうか。

これはPHPがtaintモードをサポートしていないからでしょうか? 少なくとも1年程は前だと思いますが、Railsはtaintモードでは動作していなかったことはまつもと氏もご存知だったと思います。今はtaintモードでも動作するのかも知れません。しかし、セキュリティ的にはtaintモードは有れば良い程度の機能だと考えています。アプリケーションはtaintモードより、完全な入力バリデーションに頼るべきだと考えているからです。

それとも、PHPは言語レベルでWebフレームワーク的な機能をサポートしすぎていて、コードをちょっと書くだけでWebアプリが作れる、つまりコードをちょっと書いただけでセキュリティ対策ゼロのWebアプリが作れてしまう、事が害悪と言われているのかも知れません。

もしかするとPHP本体やデフォルトモジュールには他の言語に比べてセキュリティホールが満載だ、と勘違いされているのかも知れません。PHP本体のセキュリティ情報が多い理由はこれを参照していただくその理由が分かります。

いずれにせよ短い文の意図を想像しているで間違っているかも知れません。

RubyでWebアプリケーションを書くなると私もRailsを使うと思います。RailsにはActiveRecordや認証プラグインなどもあり比較的安全なWebアプリを短期間に構築できます。しかし、言語として「Rubyで書いたから、比較的安全なWebアプリケーションが作られがちになる」のではなくWebアプリケーションフレームワークである「Railsで書いたから、比較的安全なWebアプリケーションが作られがちになる」のだと考えています。

私はフレームワークは万能ではない、とよくセミナー等で話しをします。同時に、フレームワークはより安全なアプリケーション構築に非常に有用であり積極的に利用すべき、とも話しています。安全なアプリケーション構築にはフレームワークが欠かせないのです。予想ですが、同じような資質を持ち同じような経験を持つプログラマが同時に初めてPHPとRubyを習い、フレームワーク無しでWebアプリケーションを作った場合、PHPで構築した方がよりセキュアなアプリケーションができるのではないかと思っています。これはPHPの方がよりWebアプリフレームワーク的な機能を持ち合わせているので、PHPの方がより安全なWebアプリケーションを構築する可能性が高いであろう、と考えるからです。

同じような資質を持ち同じような経験を持つプログラマがRailsと同等の機能を持ったPHPのWebアプリフレームワークを用いてWebアプリを構築した場合、ほぼ同じセキュリティレベルのアプリケーションが作れるのではないかと考えています。

ちょっと極端な例を書きますが、C言語でWebアプリケーションを作っるのは普通はナンセンスだと思います。C言語は非常に柔軟かつ強力である半面、厳格なメモリ管理が要求されうえWebアプリケーションで必要なデータ型に対する柔軟性に欠けます。CとPHP/RubyどちらがWebセキュリティ上良いコードがかけるのか比べなくても分かります。Cの場合はセキュリティ上のリスクが多すぎます。

C vs. PHP/Rubyの場合、土俵が違いすぎます。Cの場合、Webアプリケーションを安全に構築するため言語的なサポートは無いので、危険なアプリケーションを作ってしまう可能性が高くなります。フレームワークがあったとしてもCは言語仕様的に脆弱なアプリケーションを作ってしまう危険性があります。C言語でWebアプリを構築するのは、よほどの事が無い限り

現代では(セキュリティ的に弱いものができあがってしまいがちという意味で)害悪ではないだろうか。

と言えると思います。

PHPとRubyの場合はどうでしょうか。2つの言語の機能には大きな違いがあります。しかし、同じスクリプティング系の言語です。出来上がったアプリケーションのセキュリティレベルの比較は「土俵が全く違う」と言えるほどの違いはありません。どちらとも同じレベルのプログラマがコードを書いた場合、同じレベルのセキュリティを達成可能な言語だと思います。フレームワークが同じレベルなら、同じような物が作れると言うことです。

参考:Webアプリセキュリティの基本ルール

もう一つ重要なのは、ユーザ層の違いです。PHPは商用サービスで利用されている事例、オープンソースプロダクトに利用されている事例がRubyと比較すると比べ物ならないくらい多いです。このため、PHPユーザベースはRubyと比較にならないくらいユーザ数が多いです。つまり比較にならないくらい多くの初級者がいます。私はPHPを初めての言語として習得するのではなく、C/C++などのメモリ管理を自分で行う言語を取得した方が良い、と思っていますが、「PHPが初めて」の方も多くいるようです。「XSS?CSRF?セッションハイジャック?なんですかそれは?」とWebシステムのセキュリティ基礎中の基礎と言える知識さえ無い方も少なくありません。

Rubyの場合は玄人向けの言語(最近ではそうでもないがクロージャをサポートする言語は玄人向け、というのが私の認識です)であったため、ユーザ層はPHP比べ物にならいくらい「玄人」の割合が多いと思います。最低限のXSS,CSRF,セッションハイジャック等のWebセキュリティの基礎知識くらいは持っている方の割合が、PHPとは比べ物にならないくらい多いと思います。よりセキュアなコードが書けて当然です。

このような状況で「PHPで作ると脆弱なアプリケーションが作られやすいので害悪」とするのは無理があると思います。

RubyまたはPHPで作ったWebアプリケーションのどちらがよりセキュアになるかどうか、問題の本質は言語にあるのではなく「どのようなフレームワーク上で構築しているか」にあると思います。

柔軟であることは良いことばかりか

JavaScriptは比較的新しい言語ですが仕様が柔軟過ぎて、思わぬセキュリティホールを作ってしまったりします。

例:JSONデータのハイジャック

RubyもJavaScriptと同じように柔軟過ぎて(どんなオブジェクトをどこでも拡張できる)困った事になってしまう事も多いでしょう。

例:大規模プロジェクトで「だれだ、こんなところでオブジェクトを拡張(変更)したのは!」など

Ruby on RailsがRubyで実装されたのは、RubyとPHPではRubyの方がはるかにJavaScriptに似たコーディングが可能だからだと思っています。(RoR作者のブログにもそのような旨が記載されていたように思います)PHPでJavaScriptのメタファでコードを書こうとすると無理がありすぎです。RubyとJavaScriptなら同じような事(コーディング)がサーバとクライアントの両方で可能です。

# メタファ:我々の基本的な認知能力のうちのひとつ

PHPにはクロージャが無いのですから同じ事が同じようにかけるはずがありません。
RubyもJavaScriptも基底オブジェクトを持っていますが、PHPには基底オブジェクトと言えるようなオブジェクトはありません。

RailsとPrototypeのコードを読むと分かりますが、両方ともが必要としている機能であることが少し読むと解ると思います。RailsがPHPで実装されなかった理由はここにあるはずです。RoRをPHPで実装しようとして苦労して、Rubyだったら簡単だったのはコードを読めば一目瞭然だと思います。

しかし、柔軟であることは良いばかりではありません。柔軟過ぎると「どの言語で書いてもおかしなコードを書く奴は書く」が発生しやすくなります。柔軟であるが故にわけの分からないコードが生成されます。

BASICをご存知の方は耳に蛸が出来るくらい聞いていると思います。「GOTO文があるのでスパゲティコードになる」と言われていました。GOTO文を正しい状況で使うとコードを非常に簡潔かつ解りやすく書くことができます。しかし、GOTO文の柔軟性は乱用されがち(というより乱用の方が多かった)なのでBASICで書いたコードは使えないコードが多いと言われていた事を覚えている方も多いと思います。

「どの言語で書いてもおかしなコードを書く奴は書く」方は柔軟な言語や開発環境であればあるほど、おかしなコードを書いてしまいます。クロージャはあまり関係無いとしても、オブジェクトを柔軟に拡張出来すぎる仕様はBASICのGOTO問題と同じような問題の原因となる可能性が高いです。柔軟であることは良いことばかりではないのです。

制限が多いことは悪いことばかりか

良いコーディングができるように初心者をサポートする言語はスタティック言語な方が良いのではないか、と思っています。また、コードの書き方にも縛り(制限)があった方が良いのではないでしょうか?

PHPよりJavaの方が大規模プロジェクトに向いている

とよく言われました。Javaの方がより静的な言語(コンパイル型なので当たり前ですが)だから「大規模プロジェクトに向いている」と言われている(いた)のだと思います。PHP5は他の動的言語に比べかなり静的になっていますが、PHP4までは$thisに何でも代入できたり、既成のオブジェクトを自由に拡張することもできました。(とは言ってもRubyやJavaScriptの足元にも及びませんが)Javaに比べPHPの方がはるかに縛りが少なく、同時に訳の分からないコードを書くこともできました。しかし、おかしなコードが書けることよりも大規模プロジェクトに向かないとされた一番の理由はライブラリ/フレームワークなどでの縛りが効かなかったことにあると思います。

大規模システムは作るだけ、では終わりません。運用・メンテナンスを如何に容易に行うかが重要になります。概ね(良い)制限が多いシステムは見通しが良くなる傾向にあります。

制限が多いと「どの言語で書いてもおかしなコードを書く奴は書く」ような人でも、それなりに理解ができるようなコードを書く可能性が高くなります。

今後どのようになるのか

PHPとRubyを比べるとRubyの方がはるかに動的で柔軟です。PHPは他のスクリプト系言語とは反対にここ数年、静的な言語へと仕様が変更されてきています。

ここに興味深いプロセスが見えています。

スタティックな言語からダイナミックな言語への流れ(JavaScript, Rubyの人気上昇)

Javaは元々静的な言語であるのでJRubyが実装されたのも、Javaには無い物(クロージャ、自由なオブジェクトの拡張など)がRubyにあったからでしょう。

Rialsのおもしろい所は言語は制限が少なくても、フレームワークの制限は多い所です。制限を儲ける事により設定ファイル等が必要なくなる半面、柔軟性を減らしています。この辺りのバランスが非情に良いのでRailsは玄人受けが良いのだと思います。

PHPは反対の方向性

動的な言語からJavaに近い静的な言語へ

で拡張してきています。制約が多い言語へと進んでいるPHPですが、フレームワークを見るとZend Frameworkの様に明確な制限がないライブラリのようなフレームワークが新たに作られたりしています。

ここ数年、間違いなく関数型言語や関数型言語に影響を受けた言語の人気が高まってきていると思います。まだ、当たり前になった、とまでは行かないですが今後どうなるか?興味深い所です。玄人向けの機能として終わるのか、それともオブジェクト指向の様に当たり前になるのか?

関数型言語の人気は未来のRubyとPHPの勢力図に大きな影響があると思います。

Wikipedia: 関数型言語


関連URL:
http://slashdot.jp/askslashdot/08/02/03/0022251.shtml

 

この件は、他にもかなりいろいろな所で話題になっているようですね。

投稿者: yohgaki