Endo Tech Blog

Techブログと言う名のただのブログです。

【翻訳】PHPアプリケーションの安全化in2016:ポケットガイド

f:id:kikuchi1201:20160712114109j:plain

Securing a PHP Application in 2016: The Pocket Guide

原文

この文章は機械翻訳を通した後になるべく文法が通るように筆者が意訳した為見ずらい文章が多々あります。また意味が曖昧な言葉はすべて()で括っています。もし間違い、指摘がございましたらコメント欄にてお伝え下さい

It was the year 2016. A business owner just had a great idea to expand their reach in the marketplace, and they needed to build a web application to pull it off. After a bit of market research, they decide the best course of action is to hire PHP programmers to build their vision.

2016年の事でした。事業主はちょうど市場を広げる素晴らしい考えがありましたし、同時にそれはwebアプリケーションでやる必要がありました。市場調査の後、目標を実現するための最良の行動計画はまずPHPプログラマを雇うことであると決めました。

pull it off:〔漠然と〕うまくやる
best course of action:最善の方策

Let's say you're a PHP programmer. A few days later, you find yourself employed at the company to make this vision happen. As you're sitting at the desk reviewing the wireframes that were agreed upon, the news on TV says something that catches your ear. You turn the volume up and learn that another company got hacked, all their customers' data was compromised, and it's just a mess all around.You look back at your wireframes and wonder, "If it were to happen to this project, how would it fare?" How would you even begin to answer this question?

1人のPHPプログラマが言いました。数日後にあなたは自分自身がこの会社の目標の為に雇われている事に気付くでしょう。あなたは机で座りながら規定済みのワイヤ・フレームを見直しをしている時、TVのニュースで何か耳に引っかかる事を聞きます。TVのボリュームを上げると、別の会社がハッキングされ顧客情報が危険に晒され、全てめちゃくちゃになってしまった事をあなたは理解します。 あなたは、ふり返ってワイヤー・フレームを見ながら、「万一、同じ事がこのプロジェクトに起こったらどうすればいいのか?」と思います。

さぁこんな場面に出くわしたら、なんて答え始めるでしょうか。

agreed upon :規定済みの,制定されている。
catches your ear :(曖昧)耳に引っかかる。
turn the volume up :ボリュームを上げる
just a mess all around :すべてがめちゃくちゃになる。

セキュリティの本質を理解しましょう。

Please set aside most of what you've heard over the years; chances are, most of it just muddies the water. Security is not a product.Security is not a checklist.Security is not an absolute.

この数年にわたって聞いたほとんどの情報を一旦別にしておいてください。ほとんどは逆に混乱させる可能性があります。
セキュリティーとは製品ではないです。
セキュリティーとはチェックリストでもありません。
セキュリティーとは絶対的なものではないのです。

chances are:可能性は
it just muddies the water:〔事態などを〕混乱させる,波紋を投じる

Security is a process. Security is an emergent property of a mature mindset in the face of risk.

セキュリティとはプロセスです。セキュリティーは危険に直面した際の熟慮した考えで生まれる創発特性なのです。

mature mindset: 成熟した考え

Perfect security is not possible, but attackers do have budgets.

完全なセキュリティは可能ではありません。しかし攻撃者は予算を持っています。

budgets:予算

If you raise the cost of attacking a system (your application or the networking infrastructure it depends on) so high that the entities that would be interested in defeating your security are incredibly unlikely to succeed, you'll be incredibly unlikely to be compromised.

もしシステム(アプリケーションまたはそれが依存するネットワークインフラストラクチャ)の攻撃にかかるコストを高く引き上げる事が出来ればセキュリティーを破る事に興味がある者達は破ろうとしませんし、その結果危険に晒されることも無いでしょう。

Even better, the most effective ways to raise the cost of attack against your system don't significantly increase the cost of using the system legitimately.

さらに良い事に、システムに対する攻撃のコストを最も上げる効果的な方法は、システムにかける運用コストを増やさない事です。

significantly:広げる、上回る
legitimately:正当な

This is no accident; as Avi Douglen says, "Security at the expense of usability, comes at the expense of security."

これは事故ではありません。Avi Douglenは言います。
ユーザビリティを犠牲にしたセキュリティはセキュリティを犠牲にする。」

Avi Douglen:https

With that in mind, let's look at some easy security wins you can implement in your PHP applications that significantly raise the cost of attack without making your software unusable.

この言葉を念頭において、ここでは簡単なソフトウェアが使用不能にすることなく攻撃のコストを上げる事が出来るPHPアプリケーションで実装できるセキュリティを見ていきましょう。

4ステップでPHPセキュリティを改善します

Step1 すべての新しい開発でPHP7を使用する。

PHP 7 does three important things that significantly improve the security of software written in it:

PHP 7はソフトウェアのセキュリティを著しく改善する3つの重要な事が書かれています。

1.PHP 7 dropped support for the old mysql_* functions, which a lot of outdated and insecure PHP tutorials used.
2.PHP 7 allows you to add scalar type declarations to your code.
3.PHP 7 ships with a secure random number generator.

1.多くの時代遅れで不安定なPHP教本が使用してきた、古いmysql関数の支援をやめました。
2.スカラ型宣言をコードに加えられています。
3.安全な乱数生成器がPHP7では備えられています。

Let's look at an example of the first two items in that list.

それでは最初の例として、2つのリスト項目を見てましょう。

<?php

/** PHP 5 snippet */
class Foo {
    public function get_products($name, $start = 0, $end = 30)
    {
        $name = mysql_real_escape_string($name);
        $query = mysql_query("SELECT * FROM products WHERE name LIKE '%{$name}%' LIMIT {$start}, {$end}");
        $products = [];
        while ($row = mysql_fetch_assoc($query)) {
            $products []= $row;
        }
        return $products;
    }
}

$foo = new Foo;
$products = $foo->get_products($_GET['search']);

This appears secure (we're escaping strings), but what if you accidentally passed a GET parameter as the second and third arguments to$foo->get_products()? Chances are, SQL injection would be the result.

これはセキュア(文字列をエスケープしている)として表せられますが、$foo->get_products()の二番目と三番目の引き数としてGETパラメータで渡された場合どうなるでしょう?恐らく、SQLインジェクションが結果としておきるでしょう。

what if:~だったらどうする?
Chances are:多分,おそらく

Now let's look at the PHP 7 approach:

ではPHP7での振る舞いを見てみましょう。

<?php
declare(strict_types=1);

/** PHP 7 snippet */
class Foo {
    protected $pdo;
    public function __construct(PDO $pdo)
    {
        $this->pdo = $pdo;
        $this->pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
        $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    }

    public function get_products(string $name, int $start = 0, int $end = 30): array
    {
        $stmt = $this->pdo->prepare(
            "SELECT * FROM products WHERE name LIKE :name LIMIT {$start}, {$end}"
        );
        $stmt->execute([
            'name' =>
                '%' . $name . '%'
        ]);
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }
}

$foo = new Foo(new PDO(/* ... */));
$products = $foo->get_products($_GET['search'] ?? '');

Is this more secure than the PHP 5 snippet? Certainly. If a developer accidentally passes a GET parameter to the second or third arguments, this will throw a TypeError unless they cast the user's input to an integer first. If the script doesn't catch the TypeError, then the script aborts execution. Type safety is useful for stopping unintended consequences.

このコードはPHP5より安全でしょうか?もちろんです。もし開発者が誤って第一引数,第二引数へのGETパラメータを渡す場合でも最初の整数にユーザ入力をキャストしない限り、例外処理としてType Errorを投げます。スクリプトTypeError例外をキャッチしない場合、実行が中止されます。従って型の安全性は意図しない結果を停止するのに便利なのです。

There are no known integer inputs that can result in SQL injection, given the code above. However, it's still highly recommended to avoid string concatenation in SQL queries at all.

上記のコードで既知のSQLインジェクションをもたらすことができる整数入力はないです。しかし今まで通りにSQLクエリでの文字列連結を回避することを強くお勧めします。

Furthermore, both the MySQLi and PDO extensions support a feature called prepared statements.The old MySQL extension did not.

さらに、MySQLiとPDO拡張機能両方が準備された機能をサポートします。古いMySQLはもう拡張はしません。

PHP 7 marked an inflection point in the PHP language (and the ecosystem surrounding it) to make it easier to do the secure thing than the insecure thing

PHP 7は不安定な言語から、より簡単に安全なことをするPHP言語(またそれを囲む生態系)としての変曲点を迎えました。

marked an inflection point :(曖昧)変曲点にマークする

Step2 どこでもHTTPSを使おう。

A website that uses HTTPS properly almost never has to worry about session hijacking attacks (for example, Firesheep); and thanks to Let's Encrypt and open source projects like Caddy - a webserver that offers automatic free HTTPS, it's never been easier to adopt HTTPS.

HTTPSを適切に使用しないほとんどのウェブサイトはセッションハイジャック攻撃(例:Firesheep)を心配する必要があります。 暗号技術やCaddy -オープンソースHTTPSを提供するWebサーバ-のおかげで、HTTPSの導入は簡単になりました。

セッションハイジャック攻撃:cookieでセッション管理を行うPHPの場合はcookieにセッションIDを保存します。このセッションIDを他のユーザーのものに書き換えてなりすましてしまうのがセッションハイジャック攻撃です。

Compare, for instance, this Caddyfile for our project, CMS Airship with its congruent Apache or nginx configurations.

例えば我々のプロジェクトであるCaddyfile,CMS AirshpsにおいてApacheもしくはnginxの構成で比較してみましょう。

Even though modern HTTPS (the TLS 1.2 variety) adds a layer of authenticated encryption to your network traffic, its CPU and memory usage overhead has been proven negligible. With HTTP/2, it's often faster for your users to connect over HTTPS than it is over HTTP.

現代のHTTPS(TLS1.2)はネットワークトラフィックに認証された暗号化の層を追加していても、そのCPUとメモリ使用量のオーバーヘッドが無視できることが証明されています。HTTP/2を使用する事でユーザがHTTPを介しするよりもりも、HTTPS経由で接続する方が速いことが多いのです。

For marketing incentive, HTTPS is also a boon for search engine optimization.

マーケティングの要点からもHTTPSは検索エンジ最適化のために役立つでしょう。

incentive:要因,動機 boon:恩恵,ありがたい

Step3 セキュリティ・ヘッダーを使用する。

Security expert Scott Helme has put together a website that allows you to assess your usage of HTTP response headers that enable and/or configure security features, at SecurityHeaders.io. (You can see our scan results here.)

セキュリティの専門家であるスコット・ヘルメ氏はSecurityHeaders.ioでセキュリティ機能を有効にするか、または構成するHTTP応答ヘッダーの使用状況を評価することを可能にするウェブサイトを一緒に入れています。 (ここに私達のスキャン結果を見ることができます。

Some security headers are trivial to implement (header("X-Frame-Options: SAMEORIGIN"); makes clickjacking nigh-impossible while allowing the use of HTML frames if your website was designed to use them).

一部のセキュリティヘッダを実装するのは簡単です。例えば(header("X-Frame-Options: SAMEORIGIN");を実装するようにデザインされているHTMLフレームであれば、使用しながらもクリックジャッキングを不可能にする事ができます。

※クリックジャッキングとはCSRFと同じように「Webアプリケーションのサーバー側機能」を利用者(被害者)に実行させる手法です。詳細はここのリンクにあります。

For the more complicated security headers, Paragon Initiative Enterprises has developed open source software to make their implementation easier.Consider, for example, CSP Builder (which assembles Content-Security-Policy headers for you).

より複雑なセキュリティ・ヘッダーの場合、 Paragon Initiative企業(著者の企業)はこれらの実装を容易にするために、オープンソースソフトウェアを開発しました。例えば、CSP Builder(Content-Security-Policyの組み立て)で考えてみましょう。

<?php
use ParagonIE\CSPBuilder\CSPBuilder;

(new CSPBuilder())
    ->addSource('image', 'https://ytimg.com')
    ->addSource('frame', 'https://youtube.com')
    ->addSource('script', 'https://www.google.com')
    ->addDirective('upgrade-insecure-requests', true)
    ->sendCSPHeader();


At bare minimum, you should send these headers:

最低でも、以下のヘッダを送信する必要があります。

  • Strict-Transport-Security
  • X-Frame-Options
  • X-XSS-Protection

Step4 信頼できる参考資料を使いましょう。

Although adopting PHP 7 means you'll miss out on most of the ways PHP developers shoot themselves in the foot while building software, there are still tutorials being written in 2016 that contain ill-advised (or outright vulnerable) practices. A great way to avoid accidentally trusting an unreliable tutorial is to proactively learn the best practices.

PHP7を採用する機会から逃げている事は、PHP開発者がソトウェアを構築しなが自ら墓穴を掘っている事を意味しますし、また(あからさまな脆弱)が含まれている2016年に書かれたチュートリアルが未だ残っています。信頼できないチュートリアルを回避するのに最適な方法は、積極的にベストプラクティスを学ぶことです。

miss out on most of the ways:方法のほとんどを逃します。
shoot themselves in the foot:自ら墓穴を掘る。

Start with our Gentle Introduction to Application Security, then check out our application security reading list. Most of the concepts we emphasize in our blog posts are also widely applicable outside PHP security.

PHPセキュリティの次のレベルへ

If you follow the four easy steps above, you'll be in much better shape when it comes to defending against computer criminals.

上記の4つの簡単な手順を実践する事でコンピュータ犯罪者に対する防御を考える際にもはるかに良い形になるでしょう。

Earlier we had said, "If you raise the cost of attacking a system (your application or the networking infrastructure it depends on) so high that the entities that would be interested in defeating your security are incredibly unlikely to succeed, you'll be incredibly unlikely to be compromised." There's a corollary that must be stated here.

先に我々が述べた"もし貴方がシステム(アプリケーションまたはそれが依存するネットワークインフラストラクチャ)の攻撃にかかるコストを高く引き上げる事が出来れば、セキュリティーを破る事に興味が攻撃者達は破ろうとしませんし、その結果危険に晒されることも無いでしょう"という事をここに、もう一度記載しなければなりません。

You cannot know everyone that is interested in attacking your system. You similarly cannot know why every possible attacker in the universe may want to attack your system.

システムを攻撃する事に興味を持ってる人を誰も知り得る事はできません。また同様に、全ての(in the universe)攻撃者がセキュリティーを破れるシステムの中であなたのシステムを攻撃するかもしれない事を、知る事もできないのです。

There are a lot of companies that try to fill in this gap. They emphasize attribution, threat intelligence, and real-time attack monitoring. You can, for the most part, safely ignore all of these things they are selling.

このギャップを埋めるために挑戦する多くの企業があります。彼らは攻撃の特性、脅威インテリジェンス、およびリアルタイムの攻撃の監視を強調しています。ほとんどの部分は、彼らが販売している物で安全に無視することができます。

attribution :帰属,著者,属性特性

Consider this: Even if you were to succeed in knowing who is attacking your network and what they hope to gain, the most you can glean from this is psychological comfort in knowing your enemy and maybe retributive prosecution (if they're in another country, the odds become much slimmer).

ここで考えてみましょう:貴方がネットワークを攻撃した人物を特定し、攻撃者が望んでいる情報を引き出す事に成功したとしても、ほとんどは攻撃者を特定する事による心理的快感と恐らく報復起訴を苦労して得る事ができます。(もし、攻撃者が別の国にいる場合、オッズはかなり小さいですが。)

glean:探り出す,〈落ち穂などを〉拾う,(苦労して少しずつ)収集する
retributive prosecution:(曖昧)報復起訴

If your goal is to write secure PHP applications:
・You generally don't need to know who the attacker is.
・You generally don't need to know why they want to break in.
Conversely:
・You should know what attacks are possible.
・You should know where attacks should come from.
・If an incident does occur, you should know when and how it happened, so you can prevent it (and similar attacks) from happening again.

セキュアなPHPアプリケーションの目標を記述する場合:

・「誰」が攻撃者があるかを知る必要はありません。
・「なぜ」彼らは壊したいのかを知る必要はありません。

では逆に

・「なに」で攻撃が可能であるかを知っている必要があります。
・「どこ」から攻撃がくるのかを知っている必要があります。
・もし事故が発生した場合は、「いつ」、どのようにそれが起こったあなたが知っている必要がありますので、再び起きてからそれ(と同様の攻撃)を防ぐことができます。

If you find yourself asking, "Who would want to attack us? It's not worth it for them to target such small fry," consider the current trend of computer crime: ransomware and watering-hole attacks on ad networks are quickly becoming the biggest threats to the security of most peoples' computers.

あなたはこんな感じに自問自答するかもしれません。"だれが我々を攻撃したがるんだ?彼らにとって我々なんて小さな稚魚を捕まえるような事じゃないか",と考えながら現在のコンピュータ犯罪の傾向を考えます。広告ネットワークへのランサムウェアおよびWatering Hole型攻撃はすぐに人々のコンピュータセキュリティ最大の脅威となってくるでしょう。

ランサムウェア:感染したPCをロックしたり、ファイルを暗号化したりすることによって使用不能にしたのち、元に戻すことと引き換えに「身代金」を要求する不正プログラムです。 身代金要求型不正プログラムとも呼ばれます。詳細はここで見れます

※Watering Hole型攻撃:企業や組織を狙った攻撃手法の1つを表す言葉として使用されています。この場合、攻撃者は、慎重に考慮した上で特定のWebサイトを選定し、そのWebサイトに脆弱性利用のマルウェア(エクスプロイト)を組み込むことで改ざんを行い、最終的にマルウェアの感染被害が発生することになります。詳細はここで見れます

Your system might not be the end-game, especially if the attacker is sophisticated. Always look to improve. Security is a process. It's not a destination.

攻撃者が高度な技術を持っている場合は特に、システムにエンドゲームはないかもしれません。常に改善する所があります。繰り返し言いますが、セキュリティはプロセスです。目的地ではないのです。

sophisticated:(都会的・知的に)洗練された、(高度の)教養のある、インテリ向きの、世慣れた、純真でない、如才ない,精巧な、高性能の

If you run out of ideas to improve, consider hiring a security company to perform a comprehensive penetration test and/or audit your source code. Specialists will generally have deeper insight into the more advanced attacks that are possible as well as the best defense against them.

もしも改善するアイデアが不足した場合は総合的な侵入テストを実行するために警備会社を雇うことを検討するか/またはあなたのソースコードを監査をつけましょう。専門家は、一般的に可能なだけでなくそれらにに対する最善の防御策であり、より高度な攻撃に深く洞察力を持っています。

(Full disclosure: Our company specializes in developing secure PHP software; penetration testing and source code auditing are both services we provide our clients.)

(情報開示:私たちの会社は安全なPHPのソフトウェアの開発に特化しており、侵入テストとソースコード監査の両方のサービスをクライアントに提供しております)

July 10, 2016 4:55 pm by P.I.E. Staff

原文

後日談

数日前に友人に誘われてベンチャー投資家とスタートアップのミーティング会議に参加させてもらったことがあったんですよ。といってもデッカイ会場とかではなく横浜にあるタワーマンションのワンルーム(?)みたいな所で10~12人ぐらいが入る規模ぐらいかな?。このミーティングに参加している一人が僕の友人にこのミーティングに誘ってくれて、その友人から僕に連絡がきて「美味しい食べ物とお酒、ノメルヨ」と来てノココと付いて行った訳です。でまぁ、このミーティングが結構熱くて、中には黒人の学生の子もいて、母国(アフリカ諸国)に戻ってICT教育を普及させたいだ!つって全部英語で喋って(勿論投資家側も英語で返す)、僕みたいミーハな奴でも熱が伝わる素晴らしいプレゼンだったんだけど、プレゼンが終わった飲み会でその黒人の人とは違う、外国人の人から「PHPwebサービスを作るのは危険なんだよね」みたいな事を聞かれれ、ボクなんか英語で返そうにも最近Rapにはまってるせいで「Hy!Yo!Year! wackなMC~!」しか言えないんだけど、頑張って「いやPHP7にすれば大丈夫だよ」とかなんかそれっぽい事を言ったら「hmmmmmm」ってすごい怪訝な顔をされた訳ですよ。 「hmmmmm」って、それ日本人でしう「う~~~ん」みたいな?なんか違うぜ、みたいな?そしたら彼がやっぱりセキュリティの事でPHPは危険さぁ~って、手にもった赤ワインを飲みながら陽気に受け流していたんだけど。まぁ確かに7に上げた所でそこまで売り上げ変わるかってわかんないし、そもそも情報がまだまだ少ないし、しかもカツカツなベンチャーなら、顧客情報流失なんて謝罪で済む話じゃない訳で、一歩間違えりゃ倒産じゃないですか。さっき頑張ってプレゼンしてた黒人のナイスガイナな彼も困り顔で「hmmmmm」とか言いそうだなって!って、意識が朦朧としながらトイレで引きこもりがら考えてたんですよ。

でこの文章に書いてある通りに確かにセキュリティを考えなきゃならん、しかし運用も考えなきゃならんと。結局はバランスとか言っていい感じに〆たい所なんですけ少なくとも今後新しいサービスは7に切り替えるべきだなって考えています。まぁそんなわけでここに書いてある通り良いコードを身につけるべく、今は独習PHPにいじめられています。

時間あったら型付関数とタイプビンディングの違いの記事をあげます。

教祖本

散々いじめられた。お世話になりました。

パーフェクトPHP (PERFECT SERIES 3)

パーフェクトPHP (PERFECT SERIES 3)

今読んでます。

独習PHP 第3版

独習PHP 第3版

教祖本を買いた同じ人が書いてますが、やっぱり難しいが良本。
MVCフレームワークを使った最近のwebアプリケーション開発の事例を知りたかったら
この本でも十分通用します。

効率的なWebアプリケーションの作り方 ~PHPによるモダン開発入門

効率的なWebアプリケーションの作り方 ~PHPによるモダン開発入門