Code Day's Night

ichikawayのブログ

Webアプリケーションにおけるタイミング攻撃の実現性 リモートから簡単にパスワードクラックできるのか?

これはPHPアドベントカレンダー2017 8日目の記事です。

今年もBrewDog ホッピークリスマスIPAの季節になりましたね。美味しいクラフトビールに恵まれて幸せです。 市川@cakephperです。 丹精込めてVAddyを作ってます。

経緯

2017年9月にLaravel5.5にタイミング攻撃が存在するという脆弱性が CVE-2017-14775 として公開されました。 修正のPull Requestはこちらです。
[5.5] [Security] Close remember_me Timing Attack Vector

日本語の記事として、Innovator Japan Engineers’ Blogのlocakdiskさんの記事があります。
Laravel の脆弱性 CVE-2017-14775 の対処法

この修正を見て、そもそも最近の高速なCPUや複雑なネットワーク、サーバ環境においてリモートからのタイミング攻撃は可能なのか?という疑問が浮かびました。 今回はPHPを例に説明しますが、結論の箇所はPHPに関係なく他の言語でも同様の結論です。

タイミング攻撃とは

タイミング攻撃とは、処理速度や消費電力の違いを利用して機密情報を取得するサイドチャネル攻撃の一種です。 例として、処理が遅いデバイスで入力値の時間の変化によってパスワードを1文字ずつ解析するものがあります。

PHPのタイミング攻撃

PHPの比較演算子 ===== では、文字列がマッチする長さによって処理時間が異なります。

例えば、'abcde' == 'aaaaa' と、'abcde' == 'abcde' では微妙に処理時間が異なります。 PHPはC言語で実装され、==, ===では下記のような動作になります。

  • 比較する文字列の長さが異なると即falseを返す
  • 同じ長さの文字列は、前方から1文字ずつ比較し、異なった時点でfalseを返す

これにより、パスワード文字列などが効率的に取得できます。

PHPでの対応策

PHPでは、安全な文字列比較関数として hash_equals()がPHP5.6から用意されています。

タイミング攻撃の利点

パスワードを破る場合、総当たりのブルートフォース攻撃がありますが、これは多くのパターンを試行しなくてはならず、時間がかかります。 例えば数字のみのパスワード6桁の場合、最大で100万回の試行が必要です。

タイミング攻撃がうまくいくと仮定すると、最小で60回程度の試行、1回では判別できないことが多いので、何度か試行してその100倍、1000倍程度の回数になります。1000倍でも6万回。 ネットワークの遅延など、ランダムな遅延が発生するので、1文字に対してある程度の回数を試行し、統計処理をすると解析できるというものです。 ただ、揺れが大きく多くの試行が発生する場合は、結局ブルートフォースと同じぐらいの試行回数となる可能性もあるため、どれぐらいの精度で判別できるかが焦点になります。

疑問点の整理

文字列比較のようなμsec程度の処理の差を、ネットワーク越しのWebサーバから検出できるのかというのが今回の疑問点です。 文字列比較の処理時間に比べて、下記のような他の要素が圧倒的に時間がかかるものがある環境で統計的に解析できるのが信じられません。

  • 同じネットワークの経路を通るとは限らず、混雑などの影響の遅延がばらつく
  • Webサーバのアクセス数や、同時に起こっている別の人の処理内容は異なっている
  • Webサーバの手前のキャッシュサーバや多段構成の要素の影響

また解析できたとしても試行回数が多くなって、それはブルートフォースと比べてパフォーマンスが良いのかという点も気になります。

結論

同じような疑問をもっている人がいて、検証した論文が2015年に公開されています。
Web Timing Attacks Made Practical

ここでの結論としては、

  • インターネット経由の場合はμsecレベルの差は検出できない
  • LAN内であっても1μsec程度の処理差だと検出できない(一般的なサーバCPUの文字比較程度だと無理)

となっています。1μsecを超えるようなもう少し重い処理であれば、LAN内なら検出できる可能性はあるようです。

インターネットで広く提供しているサイトであればタイミング攻撃を恐れる必要はないと言えますが、今回hash_equals()を覚えた人は今後は使えるところは使っていきましょう!

修正箇所

今回の修正箇所を見ると、 f:id:ichikaway:20171208090127p:plain

Pull Requestの修正コードは一応問題ないのですが、修正された内容は、まず $userを評価してfalseならhash_equals()は処理されない点が興味深いですね。 今回のコードでは問題になりませんが、$userの結果がtrue/falseによって時間差が生じますので、下手をすると別の問題を引き起こしてたかもしれません。

そもそも元のコードPHPは比較演算子を使ってるわけではなく、SQLのWHERE句でトークンの条件を指定していただけです。それをPHPのタイミング攻撃が!と言ってわざわざSQLから取得した結果をもとにトークンの一致をhash_equals()を使ってやっています。 たぶんこのPull Requestを送ってる人もタイミング攻撃の詳細はあまりよくわかってなく、とりあえずそれっぽいところにはhash_equals()を使うという表面的な考えしかないように見えます。

感想

今回はLaravelの脆弱性修正箇所を見て、これは本当に必要な修正だったのだろうかという疑問が残ります。 フレームワーク作者はフレームワークの機能を作るのに注力しているため、セキュリティの問題があるという指摘とPull Requestがきた場合、SQLインジェクションのようなわかりやすいものは別として、 今回のような影響小さそうだけど良くわらからないから面倒だからという場合は、あまり考えずに取り込んでしまうのではないでしょうか。

そもそも現在の環境でほぼ起こらない問題を指摘して、PHPのお作法的にはこうなってるからしたほうがいいよ(詳細は知らんけど)ぐらいの理解の人が声をあげていくのは良いのだろうか、コア開発者をうんざりさせるだけなのではないか、そう感じました。

この話とはちょっとそれますが、面白い記事があったのでリンクを貼っておきます。
「セキュリティを「必要悪」にした犯人は業界自身ではないか?」

それでは良い金曜日を!

Route53のDNSレコード操作のみ許可するIAMロール

Route53を操作するIAMで、下記の要件を満たすロール設定

  • コンソール画面での操作を想定
  • 特定ゾーンのみのレコードの作成、更新、削除を許可
  • ゾーン一覧の表示
  • ゾーンの削除は不可
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "route53:GetHostedZone",
                "route53:ListHostedZonesByName",
                "route53:ListResourceRecordSets",
                "route53:ChangeResourceRecordSets",
                "route53:ListTagsForResource",
                "route53:ListTagsForResources"
            ],
            "Resource": [
                "arn:aws:route53:::hostedzone/Z3PYYYYYY",
                "arn:aws:route53:::hostedzone/Z3PXXXXXX"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "route53:ListHostedZones"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}

Resourceの arn:aws:route53:::hostedzone/Z3PYYYYYY は、アクセスを許可したいドメインのホストゾーンIDを記載する。今回は2つのゾーンを許可している。

Route53の管理ページで、ゾーンの一覧が表示できないとコンソールでの操作が面倒(ゾーンIDを含むURLに直接遷移が必要)なため、 route53:ListHostedZonesを全てのリソース*で許可する。
全てのリソースで許可する理由は、route53:ListHostedZonesは、リソースの範囲を特定ゾーンに絞れないため。

参考URL docs.aws.amazon.com

口座振替の依頼書で銀行印が必要なのは1ページ目だけ(捨印は任意)

支払い方法が口座振替(引き落とし)に限られている場合、自分の銀行印を押して提出する必要がある。

一般的には、1枚目は銀行用、2枚目が委託業者用、3枚目がお客様控えになっていると思う。2、3枚目は写しになっているが、なぜかそこにも銀行印を押すようなフォーマットの用紙がある。(写しだから1枚目と同じ記述になっている)

 

しかし、2枚目、3枚目は銀行以外のところで保管されるため、銀行印は押したくない。そこで口座振替依頼書に記載された電話番号(今回はSMBC系列)にかけて聞いてみた。

結論は下記。

  • 銀行用と書かれた1枚目のみ銀行印を押せば良い
  • 2枚目以降は銀行印は不要。何も押印しないか、認印を押せばよい
  • 捨印は、1枚目も含めて任意であり必須ではない

 

まぁ、普通に考えればそうだよねという結論だが、振替依頼書のフォーマットによっては2枚目、3枚目にも銀行印が必要という記述があって(写しだから)、何も考えないとそのまま銀行印を押してしまうケースは多いと思う。

 

2枚目は基本的に支払先が管理する用紙のため、申し込み先のお店やスクールなどが管理する。ここに銀行印を押したものを管理されたくないので今回調査した。

 

pandasでデータを間引く(リサンプリング)

大量の時系列データをプロットする場合、プロット数が多くなりすぎてグラフが綺麗にでないことがある。 その場合は、データを間引くわけだが、単純にfor文で回して一定期間を処理するのも良いが、pandasを使えば1発でできる。

この間引くという機能はresampleというメソッドを使えば可能。

pandas.DataFrame.resample — pandas 0.19.2 documentation

df_orig = pd.read_csv(file, names=['date','val'],parse_dates=['date'],infer_datetime_format=True,index_col='date')  #CSVからデータをロード

df = df_orig.resample("D").max()   #1日単位の最大値を取得
df = df_orig.resample("H").sum()   #1時間単位の合計値を取得
df = df_orig.resample("10T").mean()   #10分単位の平均値を取得

pyenvで入れたpython3をcronなどから利用する方法

pyenvを使ってインストールしたpython3をcronなどから利用する場合、他のユーザからも実行できるように、まずは.pyenvを/usr/local/pyenvなどに置く。

git clone https://github.com/yyuu/pyenv.git /usr/local/pyenv

vi ~/.bashrc
export PYENV_ROOT="/usr/local/pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"

source ~/.bashrc

pyenv install 3.6.0
pyenv global 3.6.0

pyenv global 3.6.0としておけば、/usr/local/pyenv/shims/pythonが3.6のバージョンになる。 あとは他のユーザがこの /usr/local/pyenv/shims/python を使えばok。 pipでインストールされたmatplotlibやpandasもpython3.6のものとなる。

MacやLinuxにpyenvを入れてお手軽にpython3環境を構築

MacやLinuxにpyenv入れて、python3とmatplotlibなどをインストールする場合
.pyenvの場所は自由に指定できるので、/usr/local/pyenvなどでもok。

git clone https://github.com/yyuu/pyenv.git ~/.pyenv

vi ~/.bashrc
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"

source ~/.bashrc

pyenv install -l でインストール可能なバージョンがリストアップされるので、必要なバージョンをインストール。
このユーザで使うpythonのバージョンを指定。

pyenv install 3.6.0
pyenv global 3.6.0

pipはインストール済みのため、matplotlibなどをインストール

pip -V
pip install matplotlib numpy pandas
pip list

Macだとpython3でそのままmatplotlibを動かすとframeworkエラーが出るので下記で対応

qiita.com

vi ~/.matplotlib/matplotlibrc
backend : TkAgg

AWS Linuxでpython2.7に切り替えてmatplotlibをインストール

メモ

AWS Linuxでは、python2.6が利用されているため、それを2.7に切り替える。 python2.6のpipでは古すぎてmatplotlibがインストールできないため。

alternatives --display python
alternatives --set python /usr/bin/python2.7
python -V

pipをインストールし、matplotlibをインストールする

yum install python27-devel python27-pip
easy_install pip
pip install --upgrade pip

pip install matplotlib numpy

最後に、グラフを描画してhoge.pngに保存するスクリプトを動かして、実際にmatplotlibが動くか確認。

import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(1,1,1)

x = [0,1,2,3,4,5]
y = [10,20,30,40,50,60]

ax.plot(x,y)
plt.savefig('./hoge.png')

サイトの日英翻訳は?自分が評価できない納品物の悩み

VAddy Adventカレンダー6日目の記事です。 

VAddyの海外展開

VAddyは海外にも売れるサービスだと思ってます。海外のブログ記事では、「DevOpsにセキュリティテストを!」という記事をよく見かけるため、需要は国内の何倍もあると思います。

セキュリティテストの需要は国内外関係ないですし、現地語じゃないと普及しないような特殊なサービスでもないため、私たちも最初から海外も含めて売るつもりで作っています。

英語の壁

VAddyの製品紹介ページ、マニュアル、サービスの管理画面は全て英語/日本語の両対応です。国内ユーザも多いため日本語のサポートはしっかりやりますし、画面を設計していく上でもまず日本語で考えて後から英語の文言を差し込んでいます。

英語の壁は高いというのも感じていて、意味が通じる英語の文章であれば自分たちでも書けるのですが、製品ページやブログ記事などはより自然な英語にしないと読んでもらえないため、英語に関しては基本的に外部に委託しています。

いくつか翻訳サービスを使って分かった自分の無力さ

良い翻訳者を探すために、まずは複数の翻訳サービスの会社を使って、私が書いた下記のブログ記事をそれぞれの会社に翻訳してもらいました。

VAddyが目指す世界と使命 - VAddyブログ - 継続的セキュリティテストへの道 -

それなりに費用がかかりましたが、翻訳者によって品質は結構違うことがわかりました。その中でも自分たちが良いと思った翻訳記事があったので、ここに決めようかと考えていました。

念のため、翻訳された英語記事を知り合いのオーストラリア人エンジニアの人に見てもらいました。結果として、"意味は通じるけれども、大人が書いている文章には見えない"という評価を受けました。

ショックでした・・・

それなりに英語を勉強してきて、これなら大丈夫そうと選んだ記事が、英語ネイティブユーザには不自然だというのです。自分たちがこれから発注していくものを、自分たちが正しく評価できないという現実を突きつけられました。

辿りついた信頼できる人

翻訳のクラウドソーシングはたくさんありますが、毎回違う人が翻訳するのは怖いので信頼のおける人を探すことにしました。結果的に海外の翻訳者マッチングサービスで良さそうな人を見つけてその人にアプローチしました。アメリカ出身で現在は名古屋在住の方です。

先ほどと同じブログ記事を翻訳してもらい、同じオーストラリア人エンジニアにもう一度チェックしてもらいました。結果はOK。その記事がこれです。

Vaddy's vision and mission statement - The Automated Vulnerability Scanner for DevOps

そこからずっとこの方に翻訳をお願いしています。同じ方にずっと翻訳をお願いしているため、VAddyについての考え方や操作は深く知ってもらえて、結果的にVAddyに関する機能の質問は最近はなくなりました。

最近では、私が書いた日本語の文章にはない情報や表現を入れてもらうこともあり、原文よりも120%ぐらい良い英語文章になっていますw

さいごに

自分たちが評価の軸を持っていないもの、正しい評価ができないものは注意が必要ですね。英語以外のケースでもこのようなことが起こらないかチェックしておきたいものです。

 

今日は私が好きなクラフトビール銘柄の紹介を。4年前ぐらいに初めて飲んだオランダのデモーレンという会社が作っている、Vuur&Vlam(ブアー&ブラム)というIPAが最高に美味しかったです。私の中で1位ですね。ボトルビールは日本で買えるのでお試しください。

ラベルもすごくオシャレで、他の銘柄もデモーレンの風味があって特徴が強く、おっとこれ以上は長くなりそうなのでこれぐらいにしておきますね。いつかオランダにある醸造所を訪ねてみたいです。

 

 

VAddyの歴史を振り返る

VAddy Adventカレンダー5日目の記事です。

最近ではコンビニでクラフトビールが買えるようになってきて良いですね。福岡だとまだ少ないですが、東京ではナチュラルローソンのビールの品揃えがすごくて、BrewDogのPunk IPAが普通に置いてあってビックリしました。

今日は、VAddyが今まで何をしてきたのか簡単に振り返ってみたいと思います。

VAddyの歴史

2014年

2013年の年末ぐらいからVAddyのアイディアを議論し始め、2014年の2月頃にVAddyという名前が天から舞い降りてきてきましたw

何をするのか、何をしないのか、どう動いたらユーザに嬉しいのか、など4月ぐらいまでずっと議論し、6月には動くものができました。今考えると、裏の検査エンジンも含めて開発しているので2ヶ月でできたのは非常にスピーディーですね。

6月末に開催されたPHPカンファレンス関西のLTで初めてVAddyの構想を発表し、8月にはベータ版をリリースして利用者を募りました。

2015年

2015年4月に英語版をリリースしました。日本語で作っていたものを全て翻訳して、ドキュメントも用意してスタートしました。

ここから正式版(有料プラン)を議論し、10月にリリースしました。課金やプランの自動ダウングレードなどのバッチ処理が時差によって日付が変わるため、実行時間などを気にするようになりました。

VAddyミートアップを東京と福岡で開催しました。VAddyのセミナーに近い形でVAddyを知ってもらい、デモをみて使えそうか感じてもらうことが目的でした。

2016年

海外カンファレンスや国内カンファレンスでスポンサーブースを出しました。ブースでの反応は上々なのですが、実際のサインアップ数は・・・という感じで難しいですね。

今年はVAddyユーザミートアップと名前を変えて、実際のVAddy利用ユーザの方に講演して頂きました。

VAddyユーザーミートアップ Vol.1を開催しました 

VAddyユーザーミートアップ Vol.2を開催しました 

VAddyユーザーミートアップ Vol.3を開催しました 

VAddyユーザーミートアップ Vol.4を開催しました 

ミートアップやサポートで頂いた意見をもとに機能を実装していきました。大きな機能のリリースではなかったのですが、使い勝手がよくなったと思います。頂いたフィードバックのお礼に実装で返すというマインドでした。

さいごに

ベータ版からまだ2年ですが、ユーザ数も増えてきました。まだ国内ユーザ数の方が多いですが、もうすぐ海外ユーザの数がそれを上回る見込みです。

2017年もよろしくお願いします!(大晦日の記事みたいな終わり方だ・・)

VAddyを運営するビットフォレストという会社

VAddy Adventカレンダー4日目の記事です。

私が最初にクラフトビールに出会ったのはたぶん2008年ごろ、アメリカにあるセーフウェイというスーパーに行った時でした。ビールの陳列棚の大きさもさることながら、多種多様なビールが置いてあり、ほとんどは小さなクラフトビール工場が作った6packと呼ばれる6本セットの瓶ビールでした。よく分からないながらもペールエールを中心に何度か飲みましたが、短期滞在で毎回6本セットを買うのは消費する側には厳しいもので。。この話を書いているうちに今日が終わりそうなのでこのへんにしておきますね。

 今日はVAddyを開発運営している株式会社ビットフォレストについて書いてみます。

株式会社ビットフォレスト

VAddyを開発運営しているのは、株式会社ビットフォレストです。

www.bitforest.jp

創業は2002年ですので、インターネット関係の会社としては古いほうですね。

創業当初はWebシステムの受託開発が中心でしたが、平行して運営していたセキュリティ事業が軌道に乗り、最近ではほとんどがセキュリティ事業となりました。受託開発から自社サービスの会社へと変わっていきました。

CTOの佐藤(金床)は開発もセキュリティも詳しいエンジニアで、オープンソースでWeb Application Firewall(WAF)やDoormanというProxyソフトなどを公開していました。書籍はこれが有名です。

ウェブアプリケーションセキュリティ

ウェブアプリケーションセキュリティ

 

Scutum

 彼が作っていたWAFをベースにクラウド型Web Application Firewallをサービスとして展開させたのが Scutum です。

WAF スキュータム(Scutum) - クラウド型Webアプリケーションファイアウォール

 

開発運営はビットフォレスト、契約、販売、サポートは株式会社セキュアスカイテクノロジーが行っています。 

2009年にScutumがリリースされた当時は、まだアプライアンスのWAFが主流で製品も保守費も高いものがほとんどでした。そこに手軽に導入できるクラウド型WAFを低価格で提供し、顧客に受け入れられ、2016年現在は1800サイトに導入されています。

選ばれてシェアNo.1!| クラウド型WAFサービス Scutum【スキュータム】

2010年からの国内SaaS型WAFシェアNo.1をキープしています。

VAddy

Scutumは通信をリアルタイムに解析して攻撃を遮断するサービスです。それとは別に、根本的な脆弱性(バグ)を発見して解決してもらうのがVAddyで、2014年にベータ版をリリースして、2015年に正式版をリリースしました。

Scutumで日々攻撃を監視し、防いでいるノウハウを使って、VAddyでもCTO金床が脆弱性検査するエンジンを自前で開発しています。

Scutumはサービスの特性上、国内展開が中心となっています。
VAddyは広く海外にも売れるものであると考え、VAddyは海外展開も積極的に行っています。

さいごに

特に何が言いたいか、書いててわからなくなってきましたw
最近、ビットフォレストのオフィスが新宿から大手町に移転しました。大手町にクラフトビアマーケットという良い感じのビールが飲める店があるので、興味がある方は一緒にいきましょう!

www.craftbeermarket.jp