2020年6月3日水曜日

私はこうやってEGSSに潜り込んだ 新卒編

こんにちは。エンジニアの竹添です。
本日は、新卒でセキュリティエンジニアになった私が、どのような経緯で業界に足を踏み入れ、どのようなお仕事をしているのか、というテーマで記事を書いてみたいと思います。

セキュリティエンジニアの業界に興味を持っている方に、今後の参考として読んでいただければ幸いです。

自己紹介

はじめに、私のプロフィールを公開します。
・年齢:25歳(1994年生まれ)
・出身:長崎県
・趣味:アニメ、バイク、お料理
・技術領域:ウェブセキュリティ全般、PHP、WordPress

我ながら、これといった特徴も無い普通のプロフィールだと思います。
技術領域に書いてある内容も、ここ2,3年で身に付けたものです。
大した事無いじゃないか、と思っていただくために書きました。


わたしの学生時代

大学は理系の情報工学部に所属していました。
絵に描いたようなインドア学生生活をしていたので、惰性で毎日を送っていました。
大学で出された課題をこなして後は好きなことをするだけの生活です。

そんなある日、知人の紹介でセキュリティ系の勉強会に足を運ぶ機会があり、
これをきっかけにセキュリティの分野に興味を持つようになりました。

あまり耳にしたことのない話が多くて、注目されている。
目新しい感じがして、難しそうなことをしていて、かっこいい。
雑ですが、最初に感じたイメージはこの通りでした。

その後、無知な状態からのスタートでしたが、
情報をキャッチアップする手段を覚え、
業界で起こっている出来事や考え方に触れる機会が増えたことで、
徐々に面白さが分かるようになっていきました。


卒業後の話

大学を卒業してからは、セキュリティエンジニアになりたいと思うようになりました。
理由はたくさんありますが、少し背伸びをするレベルのお仕事をやりたかったこと、とても多くの事を学ぶことが出来そうなこと、これまで会ってきたセキュリティエンジニアの方々が楽しそうにお仕事の話をしていたことが主な動機でした。

「新卒からセキュリティエンジニアを職にするのは難しいから、まずは開発や運用を学んでからにした方がいい」
というアドバイスを受けることもしばしばありましたが、諦めの悪い性分だったので就活の方向性をそのままセキュリティエンジニアに絞りました。

アルバイトを開始

まず、自分の実力が不足していることを知っていた私は、
セキュリティエンジニアになるために必要なスキルを身に付けたいと考えました。
そこで、知人のWeb系の会社に頼み込み、アルバイトとして雇って貰いました。
全くの未経験からのスタートでしたが、最終的にPHPとWordPressの話を多少出来るレベルになりました。

後から振り返ってみると、
この時勇気を出して開発経験を身に付けて良かったと思います。
作り手としての考え方はセキュリティを考える上で強い武器になるからです。

脆弱性診断を例に挙げると、
自分が送信した攻撃文字列が、システムに受け取られた後、
どのように処理されるか仮説を立てながら攻撃を行うことが出来るため、
精度面や効率面で大きなメリットを感じました。

採用に至るまで

Web業界への名残はありましたが、
1年のアルバイト期間を経て、私はEGセキュアソリューションズの門戸を叩きました。

EGセキュアソリューションズは、かの徳丸本の著者である徳丸さんの会社で、少数精鋭のため新卒を募集しておらず、狭き門だという事を理解していました。
ですが、他社と比べた時に、セキュリティベンダーとしての「建前」が無く、本気でお客様のセキュリティ向上に取り組んでいるように見えたので応募に踏み切りました。
※これから弊社に応募される方は、志望動機欄に同じ事を書かないようにお願いします。

実際の採用面接についてはあまり記憶が残っていませんが、志望動機等のヒアリングに加え、「ウェブの世界を安全にしたい」という社の方針に対する自分の考えを問われました。
また、二次試験では実技試験として、徳丸さんと一緒に脆弱性診断を行いながら見つけた事象に関する質問を受けますが、私はことごとく間違えました。

結果としては内定をいただくことが出来ましたが、
今になって思うと、Webの開発経験と、業界の情報を多少なりともキャッチアップしていたことが評価されたおかげではないかと思います。


入社後の話

セキュリティエンジニアといっても様々なお仕事がありますが、
EGセキュアソリューションズでは、社員の基本スキルとしてWebアプリケーションの脆弱性診断を学びます。
新入社員はまず、社長の著書『徳丸本』を片手に脆弱性の原理と影響を学び、研修用のやられサイトの脆弱性診断を行います。
結果は報告書にまとめ、社長から直接レビューを受けることになります。

やられサイトは名前の通り、「やられること」を目的としたサイトのため、たくさんのバグや不具合が見つかります。それらの中から脆弱性として問題のある事象を報告するのはとても大変で、確認漏れがあったり、分析が甘かったり、間違った解釈をしてしまったりと苦労することが多かったです。

また、脆弱性診断で技術力を磨く一方で、
お客様とのやり取りにも積極的に参加し、たくさんの事を学びます。

メールや打ち合わせでのやり取りで、お客様が求めている事をヒアリングし、
弊社が出来る事を理解していただくのは口にするほど簡単ではありません。
「メールでどのような書き方をすればこちらの意図が伝わるだろうか…」
「お客様が本当に求めている事はどのように聞けば良いだろうか…」
日々こんなことばかり考えていますし、それが楽しいです。

担当した業務

業務は脆弱性診断とお客様連絡を中心にしつつ、
希望業務にはどんどん関わる社風のため、色々なお仕事に参加させて貰いました。
私は元々計画を立てることが好きだったこともあり、イベントの運営担当も務めました。
  • Web、プラットフォーム脆弱性診断
  • 開発ガイドラインの策定
  • お客様連絡
  • イベント運営 etc...

入社後に思った事

セキュリティには技術的な要素だけでなく、コミュニケーションによる状況把握能力や解決策を考える思考能力も必要で、総合力が要求されることが分かりました。

また、入社前に抱いていたイメージよりも地味で根気のいる作業が多く、地道に経験を積みながら業務に慣れることが出来ました。私は元々地道な作業を好んでいたこともあり、このお仕事に対する適正が高かったのかもしれません。

加えて、ビジネスにも共通する話だと思いますが、普段から心掛けていることが業務に役立つことも多々ありました。情報のキャッチアップ然りすぐ手を動かすこと然り。自分が必要と思う事は積極的に挑戦するべきだと思いました。


まとめ

本日のまとめです。
  • まずは行動を起こすことが大切
  • セキュリティエンジニアは技術力だけでなく、総合力が求められるお仕事

皆さんの中には、セキュリティエンジニアは華やかなお仕事というイメージを持っている方がいるかもしれません。
それは高難度の案件をずば抜けた技術力のエンジニアが解決するイメージが強いからだと思います。
ですが、私のような人間がセキュリティエンジニアとして生計を立てることが出来ているのも事実です。


セキュリティはこれからもっと一般的な業界になります。
この記事を通して皆さんも業界に興味を持っていただけると幸いです。


PR
EGセキュアソリューションズ株式会社では、私たちと一緒に働く仲間(脆弱性診断員、コンサルタント)を募集しています。新卒・既卒問いませんので、興味のある方は採用ページを参照下さい。

2020年1月30日木曜日

Apacheが最新版(2.4.41)かどうかを確認する方法

こんにちは。EGセキュアソリューションズの社長の徳丸です。
今日は、Apacheが本稿執筆時点での最新版 2.4.41 であるかを確認する方法を公開しちゃいます。

はじめに

脆弱性診断の一環で、サーバーソフトウェアのバージョンを確認したいというニーズがあります。今どき、Apache等のServerヘッダにバージョンが出ていることはまずない(…とも言えず実はよくある)ので、Serverヘッダ以外からソフトウェアのバージョンを確認する方法が知られています。以下はその例です。
2番目の、とある診断員さんの記事は、Apache 2.2のすべてのバージョンをビルドして確認する方法が具体的に説明されています。そして、上の2つの記事はApache 2.2を題材にしていますが、2.2はとっくにサポートが終了しており、2.4系のバージョン確認の方法が求められますよね。
実は、Apacheの最新版 2.4.41 になって、エラーメッセージの表示内容が微妙に変わりましたので、バージョン確認に使えます。まずは、404 Not Foundの表示を用いて説明します。

試してみよう

以下は、Apache 2.4.39(2.4.40は欠番)における存在しないパス /xx に対するレスポンスの例です。
HTTP/1.1 404 Not Found
Date: Thu, 30 Jan 2020 01:48:04 GMT
Server: Apache/2.4.39 (Unix) PHP/5.3.3
Content-Length: 200
Connection: close
Content-Type: text/html; charset=iso-8859-1

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL /xx was not found on this server.</p>
</body></html>
以下は、Apache 2.4.41(最新版)における /xx に対するレスポンスの例です。
HTTP/1.1 404 Not Found
Date: Thu, 30 Jan 2020 01:50:08 GMT
Server: Apache/2.4.41 (Unix) PHP/5.3.3
Content-Length: 196
Connection: close
Content-Type: text/html; charset=iso-8859-1

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL was not found on this server.</p>
</body></html>
2.4.39までと比べると、パス名(/xx)が省略されていることがわかります。これを使ってApache 2.4.41か、それより前のバージョンであるか判別できます。

404ページをカスタマイズしている場合

ただ、404 Not foundのページは通常カスタマイズされているのでApacheが生成するレスポンスボディを見ることはできないケースが多いと思います。その場合は、他のステータスを用いることができます。たとえば、TRACEメソッドは禁止されているケースが多いと思いますが、この禁止されている場合のレスポンスが使える場合があります。

まずは 2.4.39の場合(リクエストとレスポンス)
TRACE /xx HTTP/1.1
Host: apacheall:2439

HTTP/1.1 405 Method Not Allowed
Date: Thu, 30 Jan 2020 01:59:48 GMT
Server: Apache/2.4.39 (Unix) PHP/5.3.3
Allow: 
Content-Length: 225
Content-Type: text/html; charset=iso-8859-1

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>405 Method Not Allowed</title>
</head><body>
<h1>Method Not Allowed</h1>
<p>The requested method TRACE is not allowed for the URL /xx.</p>
</body></html>
次に、2.4.41の場合(リクエストとレスポンス)
TRACE /xx HTTP/1.1
Host: apacheall:2441

HTTP/1.1 405 Method Not Allowed
Date: Thu, 30 Jan 2020 02:03:11 GMT
Server: Apache/2.4.41 (Unix) PHP/5.3.3
Allow: 
Content-Length: 222
Content-Type: text/html; charset=iso-8859-1

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>405 Method Not Allowed</title>
</head><body>
<h1>Method Not Allowed</h1>
<p>The requested method TRACE is not allowed for this URL.</p>
</body></html>
やはり、2.4.39まであったパス名が2.4.41では省略されています。脆弱性診断実務では、TRACEメソッドの許可を調べているケースが多い(参照)と思うので、一石二鳥ですよね!
ステータスの405までカスタムエラーページを用意してあればこの方法でもダメですけどね。Apacheのソースコード(./modules/http/http_protocol.c)の差分で見る限り、以下のメソッドがチェックに使えそうです。

CodeReason-Phrase
305Use Proxy
403Forbidden
404Not Found
405Method Not Allowed
406Not Acceptable
410Gone
412Precondition Failed
413Request Entity Too Large
451Unavailable For Legal Reasons
501Not Implemented
506Variant Also Negotiates

これらのステータスには、引き起こすのが難しいケースもありますが、403, 404, 405,  501あたりが使いやすそうです。

ただし、404を観察するくらいならともかく、エラーを故意に起こす通信は不正アクセスの予備行為と見なされ得るものですので、許可を得ていないサーバーで勝手に試すことは慎みましょう。

どうやって調べたか

Apache の2.2、2.4のすべてのバージョンをビルドして、それぞれポート番号を変えて実行する環境を作りました。先のリクエストで、apacheall:2441 というHost名が見えていましたか、ポート番号 2441 = Apache 2.4.41 という意味です。最終的にソースコードを確認する場合でも、動的解析であたりをつけておくと作業が楽ですよね。

まとめ

Apache 2.4.41以降か、それ未満かをチェックする方法について説明しました。まだApache のバージョンを2.4.41にしているサイトはそこまで多くないと思いますので、脆弱性診断等で「Apacheが最新版ですないです!! ドヤー」とすることができます…
というのは冗談で、この程度でドヤ顔はよくないですw ApacheはLinuxディストリビューションのパッケージで導入していて見かけのバージョンは古いがパッチが適用されているケースが多いですからね。現実的なリスクを踏まえて適切なアドバイスを心がけましょう。

PR

EGセキュアソリューションズ株式会社では、徳丸とともに働く仲間(脆弱性診断員、コンサルタント)を募集しています。興味のある方は採用ページを参照下さい。

2019年5月10日金曜日

【サービスのご紹介】徳丸本講座

こんにちは。EGセキュアソリューションズ セミナー運営事務局です。

本日は、6月3日(月)・4(火)に実施する『徳丸本講座』について、
受講いただくメリットや各講座の内容について簡単にご紹介します。


はじめに、『徳丸本講座』の概要について弊社ホームページでは以下の通り紹介をしております。
『体系的に学ぶ 安全なWebアプリケーションの作り方 脆弱性が生まれる原理と対策の実践 第2版』(通称:徳丸本第2版)の内容を著者とともに学ぶ講座です。
本講座は、Webアプリケーションの脆弱性について座学形式での解説を行うものです。基礎講座では徳丸本第2版の中から最低限押さえておくべき内容を応用講座では徳丸本第2版の中でも特に理解の難しい内容を学びます。

『徳丸本講座』では、皆様がWebアプリケーションの脆弱性(以下、脆弱性)に対する理解を深め、日常業務に役立てていただくことを第一の目的としています。そのため、脆弱性を突いた攻撃のデモを交えて、脆弱性の原理・影響・対策をお伝えします。脆弱性の特性について理解することで、脆弱性を作り込まないための考え方を養い、脆弱性が発見された場合の適切な対処を取ることを助けます。



続いて、それぞれの講座についてご紹介します。

基礎講座

 Webアプリケーションの脆弱性の中でも広く知られているもの・影響度の高いものを取り扱います。普段Webアプリケーションの開発を行っている方からWebサイトの開発を依頼する立場の方まで広くご参加いただきたい内容となっています。

本講座で取り扱う主な内容
  • HTTP通信の概要
  • クッキーとセッション管理
  • クロスサイト・スクリプティング(XSS)
  • SQL呼び出しに伴う脆弱性
  • クロスサイト・リクエストフォージェリ(CSRF) etc...

本講座の対象者
  • PHPやJavaScriptの初歩的な知識をお持ちの方
  • WebアプリケーションがWebサーバから受信した情報をブラウザで表示していることを理解出来る方
  • 脆弱性について一通り理解があるものの原理から学び直したいとお考えの方


応用講座

 Web APIやJavaScript、キャッシュ機能を利用する際の脆弱性等少し難易度の高い脆弱性を取り扱います。こちらには、OWASP Top10 2017にランクインしたXXEや安全でないデシリアライゼーション等が含まれます。

 開発スキルが向上すると、自由度の高い機能を使いこなす機会が増えてきますが、それと同時に取扱いにも注意が必要となります。応用講座は、開発技術やセキュリティ技術の向上を目指す方に是非受講していただきたい内容となっております。

本講座で取り扱う主な内容
  • 同一オリジンポリシー
  • CORS
  • Web API実装における脆弱性
  • 構造化データの読み込みにまつわる問題 etc...

本講座の対象者
  • PHPやJavaScriptの基礎的な知識をお持ちの方
  • Web APIとJSONの概要をご存知の方
  • 複数のページ間で行われる通信を想定できる方



最後に

 徳丸本講座は、Webアプリケーションの脆弱性についての理解を深めるには最適な講座です。詳細やお申込み方法については次のURLをご参照ください。

【2019年7月25日 追記】最新の講座詳細URLに更新しました。

2019年3月29日金曜日

【連載】JSONとJSONPの違い、そしてそれにまつわる脆弱性

こんにちは。EGセキュアソリューションズ診断チームです。
JSONとJSONPという、Webサイトを構築する上でよく目にする技術について、
使用する上で注意すべき脆弱性を、解説を交えながら紹介したいと思います。
連載第一回の今回は、前段の知識としてJSONとJSONPの概要について説明します

【JSONとは?】
JSONはXMLに代わるデータ交換形式として新たに提唱されたものです。
JavaScriptのオブジェクトリテラルの形式をベースとして作られています。
また、JSONはJavaScriptの式として解釈できる性質を持ちます。
JSONは名前と値がペアになっているデータの集合体として表されます。
名前と値を「:」(コロン)でペアとして記述し、データの間は「,」(カンマ)で区切ります。
これらを{}で囲んだものがJSON形式となります。実際のデータ例を下記に記します。

{ “title” : “Hello JSON!” , “No” : 123 }



【JSONPとは?】
JSONPとはJSON with Paddingの略です。
名前にJSONと含まれているため、同じようなものと思ってしまいがちですが、全く違うものです。
元々、データを異なるオリジン間でやり取りを行うために色々な手法が試されていましたが、
そのうちの一つがJSONPです。
JSONのやり取りにはXMLHttpRequestが使用されていますが、
XMLHttpRequestは元々同一オリジンポリシーの制約を受けていた(現在はCORSにより回避可能)ため
そのままでは異なるオリジン間でデータを受け渡すことができません。
そのため、XMLHttpRequestを使用せず、script要素を使用して外部のJavaScriptを直接実行することにより、
異なるオリジン間でデータをやり取りするという方法が考案されました。これがJSONPです。
ただし、やり取りするデータがJSONの場合、JSON文字列そのままでは
script要素でデータを受け取ることができないため、関数呼び出しの形でデータを生成します。




【JSONとJSONPの違い】
ここまで簡単にJSONとJSONPの概要を述べましたが、一言で書くと次のように表すことができます。


JSON :データ交換用の形式、またはデータそのもの
JSONP :データそのものを異なるオリジン間でやり取りするための手法

【次回予定】
第二回以降は、いくつかあるJSONとJSONPにまつわる脆弱性について、一つ一つ紹介していきたいと思います。

2019年2月22日金曜日

WordPressサイト移行に便利なDB置換ツールを使う際の注意点

WordPressサイトの引っ越しや、開発環境から本番環境への移行等によりドメイン名やディレクトリ構造を変更する必要がある場合、データベース内のドメインやURLをSQLで直接書き換えるのではなく、DB置換ツール(Search Replace DB)が広く利用されているようです。

WordPress の引越し(WordPress Codex 日本語版)
http://wpdocs.osdn.jp/WordPress_%E3%81%AE%E5%BC%95%E8%B6%8A%E3%81%97

Search Replace DB
https://interconnectit.com/products/search-and-replace-for-wordpress-databases/


Search Replace DBはとても便利なツールですが、データベースのユーザ名/パスワードを
入力することなくデータベースを書き換えることができるため、利用する際には、セキュリティを十分考慮してください。
利用の仕方によっては、サイト上のコンテンツが改ざんされるだけでなく、以下のような被害を受ける危険性があり、現在、放置されたSearch Replace DBを利用した攻撃が観測されています。


■想定される被害の例

  • データベースのアクセス情報(データベース名、ユーザ名、パスワード、
    ホスト、ポート)が漏洩し、データベース内のデータが漏洩する。
  • データベース内のデータにPHPコードを混入されることで、
    仮想通貨のマイニング、OSの不正操作等、任意のコードが実行される。


以下のチェックポイントにチェックがつく場合、至急いずれかの対策を実施いただくことを推奨します。

■チェックポイント

  • 作業が終わったにも関わらず、Search Replace DBを削除していない。
    (Ver.3の場合は「delete」ボタンをクリック)
  • Search Replace DBへのアクセス制限を実施していない。
  • Search Replace DBをWordPressのルートディレクトリ等わかりやすい場所に配置している。

■対策

  • Search Replace DBを削除する(推奨)
  • Search Replace DBを削除できない場合はアクセス制限を実施する

Search Replace DBのサイトには、インストール時の注意事項の記載があります。このようなツールやスクリプトを利用する際は、注意事項を正しく理解してから利用することが大切です。
また、利用完了後はただちに削除し、利用中も外部からアクセスできないように、アクセス制御することが鉄則です。


【参考】
WordPressのプラグインDuplicator 1.2.40以前にリモートコード実行の脆弱性(徳丸浩の日記)
https://blog.tokumaru.org/2018/09/wordpress-duplicator-plugin-vulnerabilty.html

2017年11月24日金曜日

OWASP Top 10 2017に対する弊社脆弱性診断の対応

先日OWASP Top 10の最新リリースである2017版が正式に公開されました。

OWASP Top 10 - 2017 [PDF]

OWASP Top 10 2017の公開に向けては、RC1が公開された際に議論百出した後いったん破棄されるなど波乱の幕開けとなりましたが、その後別メンバーにて作成されたRC2の内容で正式版として公開されたようです。

OWASP Top 10は多く企業にてガイドラインとして使われていると思いますし、PCI DSSなどの別の標準から参照されていますので、脆弱性診断サービスの内容がOWASP Top 10 2017にどのように対応するかは関心のある方が多いと思います。本稿では、弊社脆弱性診断サービスがOWASP Top 10 2017にどのように対応するかについて説明します。弊社診断サービスには、簡易なものから順に以下のものがあります。詳しくは弊社ウェブサイトを参照下さい。

  • ウェブ健康診断
  • ライト診断
  • スタンダード診断(標準的・網羅的なリモート診断)
  • プレミアム診断(スタンダードに加えてソースコード診断を併用する)

なお、以下の説明では、OWASP Top 10 2017の各項目の日本語訳として、以下のNTTデータ先端技術株式会社の記事で使われている翻訳に従いました。記してお礼申し上げます。

A1 インジェクション

インジェクションは、SQLインジェクションやOSコマンドインジェクション等の総称で、旧版である2013年版からの据え置きです。弊社の脆弱性診断サービスはすべてのサービスで標準的に対応しています。IPA ウェブ健康診断仕様では下記の項目が該当しますが、弊社のスタンダート以上のサービスではより詳細の試験を行います。以下の項目についても同様です。
  • (A) SQLインジェクション
  • (D) OSコマンドインジェクション

A2 認証の不備

文字通り認証処理における脆弱性です。2013年版は「認証とセッション管理の不備」となっていてタイトル上は2017年版にてセッション管理が外れました。しかし、2017年版も内容としてはセッション管理を含んでおり、ほぼ同じ内容をカバーしています。弊社の脆弱性診断サービスはすべてのサービスで標準的に対応しています。IPA ウェブ健康診断仕様では下記の項目が該当します。
  • (J) 認証
  • (K) セッション管理の不備

A3 機密データの露出

この項目は2013年版ではA6でしたが、A3に昇格しました。
「露出」はExposureの訳ですが、データが「見ようと思えば見られる状態」であることを指します。2000年代初頭の情報漏えい事件の多くが、機密データがドキュメントルート下に置かれていて、そのURLが2ch等に投稿されて騒ぎになるというパターンが多かったのですが、これがExposureです。弊社の脆弱性診断サービスはすべてのサービスで標準的に対応しています。IPA ウェブ健康診断仕様では下記の項目が該当します。
  • (E) ディレクトリ・リスティング
ただし、OWASP Top 10の解説を読むと、データの暗号化やハッシュ値による保存が強調されています。リモート診断(スタンダード)では、HTTPSによる保護は診断できますが、サーバー内部で暗号化保存されているかどうかは原理的に診断できません。これに対して、ソースコード含めて確認するプレミアム診断では、サーバー内部でのデータ暗号化についても確認できます。

A4 XML外部実体参照(XXE)

XML外部実体参照(XML External Entities; XXE)とは、XMLの外部実体参照の機能を悪用した攻撃および脆弱性であり、2017版でTop 10初お目見えとなりました。XXEに関する日本語ドキュメントはあまり多くありませんが、例えば海老原昂輔氏の下記のスライドが参考になります。

XML と PHP のイケナイ関係 (セキュリティ的な意味で) -Introduction of XXE attack and XML Bomb…

以下、簡単なサンプルを用いてXXEを説明します。以下は、POSTデータとしてXMLデータを受取り、その中から<data>タグを持つ最初の要素をとりだし、その要素内容をXMLとして返す簡単なPHPスクリプトです。

<?php
  header('Content-Type: text/xml; charset=utf-8');
  $doc = new DOMDocument();
  $doc->loadXML(file_get_contents('php://input'));
  $data1 = $doc->getElementsByTagName('data')->item(0)->textContent;
  echo "<data>". htmlspecialchars($data1). "</data>";
このスクリプトに以下のXMLデータを与えます。
<?xml version="1.0"?>
<!DOCTYPE str [
<!ENTITY wget SYSTEM "http://192.168.0.2/">
]>
<str><data>&wget;</data></str>
すると、上記3行目で定義される外部実体が処理され、http://192.168.0.2/を参照した結果がXMLとして返されます。外部からは参照できないプライベートアドレスの内容が外部に漏洩することになります。
この種の攻撃は、XXE脆弱性を悪用したSSRF(Server Side Request Forgery)攻撃と呼ばれます。SSRF攻撃とは、ウェブサーバー等を中継して、外部からは到達できない別のサーバーやネットワーク機器等に攻撃することを指します。
また、URLではなくサーバー内のローカルファイル名(/etc/passwd等)を書くと、ディレクトリトラバーサルのように、サーバー内部のファイルを閲覧できます。

ただし、PHPでこの種の攻撃が設立するには、libxml2のバージョンが古い必要があります。上記の実験はまったくパッチを当てていないCentOS 6.3では成功しましたが、CentOS 6.4ではlibxml2にパッチが当たっていて成功しません。
弊社の脆弱性診断サービスはスタンダード以上のプランでXXEの診断に対応します。スタンダード診断ではリモート診断の手法により、既知の攻撃パターンを用いて脆弱性の有無を検証します。プレミアム診断では、これに加えてソースコードの確認により、より深い診断が可能です。

A5 アクセス制御の不備

アクセス制御の不備は、IPA 安全なウェブサイトの作り方の「アクセス制御や認可制御の欠落 」に該当します。すなわち、認証を必要とするページに認証なしでアクセスできたり、強い権限が必要な機能を弱い権限で使用できる問題などを含みます。この項目は、2013年版の「A4 安全でないオブジェクト直接参照」と「A7 機能レベルアクセス制御の欠落」をマージしたものです。
弊社の脆弱性診断サービスはすべてのサービスで標準的に対応しています。IPA ウェブ健康診断仕様では下記の項目が該当します。
  • (L) 認可制御の不備、欠落 

A6 セキュリティ設定のミス

文字通りセキュリティ設定の不備による問題を指します。典型例としては、デフォルトパスワードのままでソフトウェアを使用していたり、詳細のエラー内容やスタックトレースがウェブページに表示される状態などです。2013年版ではA5でした。
弊社の脆弱性診断サービスでは、スタンダード以上のプランで標準的に対応しています。また、ウェブ健康診断とライトプランでも、下記項目はセキュリティ設定のミスとも考えられます。また、他の診断項目の結果として副次的に判明した場合は報告いたします。
  • (E) ディレクトリ・リスティング

A7 クロスサイトスクリプティング

おなじみのクロスサイトスクリプティングです。2013年版ではA3でした。弊社の脆弱性診断サービスはすべてのサービスで標準的に対応しています。IPA ウェブ健康診断仕様では下記の項目が該当します。
  • (B)クロスサイト・スクリプティング

A8 安全でないデシリアライゼーション

この項目は2017年版からの新規導入となります。「安全でないデシリアライゼーション」はPHP界隈ではオブジェクトインジェクションと呼ばれる場合もあります。詳しくは以前に書いた以下の記事を参照下さい。

安全でないデシリアライゼーション(Insecure Deserialization)入門

弊社の脆弱性診断では、安全でないデシリアライゼーションはウェブアプリケーション診断の標準としては診断していませんでしたが、OWASP Top 10入りを受けて、スタンダード診断以上にて以下のように診断項目に含めることにしました。

スタンダードプラン(リモート診断):
リモート診断にてベストエフォートの診断を実施します。脆弱なアプリケーションの例として、Welcartの1.9.3を題材とします。Welcartにて会員ログインすると、以下のようなクッキーが発行されます。
a%3A2%3A%7Bs%3A4%3A%22name%22%3Bs%3A0%3A%22%22%3Bs%3A3%3A%22rme%22%3Bs%3A0%3A%22%22%3B%7D
これをパーセントデコードすると以下の形になります。
a:2:{s:4:"name";s:0:"";s:3:"rme";s:0:"";}
これはPHPのシリアライズ形式であることがわかります。シリアライズ形式がクッキーとして発行されている限りは、これをデシリアライズしている可能性が高いと考えられます。このようなケースでは、「安全でないデシリアライゼーションの可能性」として報告します。
現実には、クッキーは発行しているが利用していないケースとか、自作のデシリアライザを用いて安全に処理している(可能性は低いと思いますが…)可能性もあるので、あくまで可能性であり、過検知の可能性はあります。しかし、シリアライズ形式を外部に出すこと自体が好ましくないため、指摘自体は有益なものと考えます。一方、特殊なシリアライズ形式で見かけ上は単なるXMLにしか見えないケースなど、見落としの可能性もありえます。

プレミアムプラン:
プレミアムプランではソースコードの確認を行うため、各言語のデシリアライズ機能を確認することにより、精度の高い診断が可能となります。

A9 既知の脆弱性を持つコンポーネントの使用

文字通り、ソフトウェアから使用しているコンポーネントに既知の脆弱性があるケースを指します。この項目は2013年版でもA9でした。
弊社の脆弱性診断では、この項目は基本的にプラットフォーム診断として実施していますが、アプリケーション診断でも判明する場合があり、その場合は報告しています。
既知の脆弱性の代表例としてSturts2の脆弱性がありますが、リモートからの診断ではStruts2のバージョン把握等には限界があります。ヒアリングの結果、必要に応じてリモートログインさせていただいての内部からの診断を提案させて頂く場合があります。

A10 不十分なロギングおよび監視

こちらも2017年版からの新設になります。ログ取得は攻撃の検知および事後調査に重要ですし、攻撃に対する監視もできれば実施するべきでしょう。
通常のリモートからの脆弱性診断では、A10の項目を外部診断業者が診断することは困難です。このため、この項目は弊社のスタンダード診断では未実施となります。
プレミアムプランでは、ソースコードを確認するため、ログ取得の状況を確認することが可能です。一方、監視についてはソースコードを確認しても判明しません。
監視をカバーする弊社サービスとしては、ウェブアプリケーションアセスメントがあります。このサービスは通常の脆弱性診断に加えて監査手法を併用し、アプリケーションの運用状況やログの活用、監視の状況などを確認し、サイト運営の改善点を指摘するものです。

診断対応のまとめ


ウェブ健康診断・ライトスタンダードプレミアムアセスメント
A1 インジェクション
A2 認証
A3 機密データの露出◎(*1)
A4 XXE
A5 アクセス制御の不備
A6 セキュリティ設定のミス
A7 XSS
A8 安全でないデシリアライゼーション
A9 既知の脆弱性を持つコンポーネント
A10 不十分なロギングおよび監視◎(ログ)◎(監視)

*1 サーバー内のデータ暗号化も確認

凡例
◎:標準的で網羅的な検査
○:抜き取り診断
△:簡易的な診断
-:非対応

まとめ

OWASP Top 10の改定に伴い、弊社診断サービスと新OWASP Top 10 (2017)とのマッピングについて紹介しました。2017年版は、XXEや安全でないデシリアライゼーション等、従来日本ではあまり話題にならない項目も含まれており、診断業者としても対応を迫られています。新規の脆弱性診断はもちろんのこと、既に診断済みサイトに関してもこれら新規項目について安全性を確認する機会ではないでしょうか。
弊社のサービスが貴社ウェブサイトの安全に寄与できれば幸いです。

2017年9月7日木曜日

診断文字列を打ち込まずにPHPのバージョンを推測する

脆弱性診断においてApacheのバージョンを外部から調べる方法を複数の専門家がブログ記事に書いておられます。
いずれも大変興味深いものですが、ApacheでできるのであればPHPはどうだろうかと気になる方も多いと思います。これは人間の自然な感情だと思うのです。
このあたり、各診断会社の「秘伝のタレ」みたいなところもあるのでしょうが、私からも少し知見を披露したいと思います。

タイトルにも書いたように、診断文字列を打ち込まずに、言い換えれば、通常のウェブ閲覧の範囲で分かること、さらに言えばHTTPレスポンスヘッダから分かることについて書きます。こういうと、「X-Powered-Byヘッダを見れば一目瞭然www」みたいな反応も考えられますが、そういう自明なものは対象外とします。

(1) キャッシュ制御のヘッダ

PHPは、session_start()関数の実行によりセッション管理を有効にすると、キャッシュ制御用のレスポンスヘッダを自動的に生成します。この挙動は、session_cache_limiter() 関数により変更可能ですが、大半のサイトはデフォルトの nocache のまま使っていると思います。これは通常安全な設定ですが、CDNによっては注意が必要です。
このうちのCache-Controlヘッダですが、PHPのバージョンにより、以下のように変わります。

PHP 4.0.0~4.0.2 Cache-Control: no-cache, post-check=0, pre-check=0
PHP 4.0.3~5.6.x Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
PHP 7.0.0~  Cache-Control: no-store, no-cache, must-revalidate

PHP 4.0.0等を使っているサイトは今時多くないとは思いますが、PHP 5なのか、PHP 7なのかの違いには使えそうです。

(2) setcookie関数に空文字列を指定した場合の挙動

以前、ログアウト機能の目的と実現方法にて書きましたが、徳丸自身はログアウト時にセッションクッキーを削除する必要はないと考えていますが、PHP本家のマニュアルには、ログアウト時にはセッションIDのクッキーを削除しなければならない(原文は"the session cookie must be deleted")とあります。このため、ログアウト時にセッションクッキーを削除するサイトはそれなりに見かけます。前述のマニュアルには、以下のようにセッションクッキーの削除スクリプトの例まで紹介されているので、これをコピペして用いる場合も多いかと思います。
$params = session_get_cookie_params();
setcookie(session_name(), '', time() - 42000,
    $params["path"], $params["domain"],
    $params["secure"], $params["httponly"]
);
これ、パッと見は、42000秒(11時間40分)前のExpireを指定したSet-Cookieを発行するように見えますが、実はそうではない…ということは以前の記事に書きました。これは、setcookie関数の第2引数に空文字列を指定した場合の特別な挙動です。そして、この挙動がPHPのバージョンによって異なります。

PHP 4.0.0~4.0.1  Set-Cookie: PHPSESSID=deleted; expires=Tuesday, 06-Sep-16 07:46:47 GMT; path=/
PHP 4.0.2~4.2.x  Set-Cookie: PHPSESSID=deleted; expires=Tue, 06-Sep-16 07:46:47 GMT; path=/
PHP 4.3.0~5.3.6  Set-Cookie: PHPSESSID=deleted; expires=Tue, 06-Sep-2016 07:46:48 GMT; path=/
PHP 5.3.7~5.4.x  Set-Cookie: PHPSESSID=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/
PHP 5.5.0~       Set-Cookie: PHPSESSID=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT; Max-Age=0; path=/

expires属性の値と、Max-Age属性の有無によって、PHPのバージョンが推測できます。特に、PHP 5.3.6まで expiresが約1年前の日時だったのに対して、PHP 5.3.7以降では1970年1月1日になるところが使えそうですね。PHP 5.5以降でMax-Age=0; が付与されるのも有用です。

(3) setcookieに空文字列を指定されたのかを判別する

しかし、上記の方法には欠点があり、本当にsetcookie関数の第2引数に空文字列が指定されたのか、実は第2引数に deleted を明示したのかは簡単には分かりません。しかし、Set-Cookieの挙動をよく見ると、これらを区別できる場合があります。
まず、PHP 5.3.6までは「約1年前」のexpiresと前述しましたが、厳密には1年+1秒前のExpiresになります。PHP 5.3.6でのレスポンスヘッダの例を下記に示します。
HTTP/1.1 200 OK
Date: Wed, 06 Sep 2017 08:38:34 GMT
Server: Apache/2.2.31 (Unix) PHP/5.3.6
X-Powered-By: PHP/5.3.6
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Set-Cookie: PHPSESSID=deleted; expires=Tue, 06-Sep-2016 08:38:33 GMT; path=/
Content-Length: 5
Content-Type: text/html
Dateヘッダの時刻とSet-Cookieヘッダのexpires属性が1秒ずれていることがわかります。これがヒントになります。もちろん、明示的に1年+1秒前のexpiresを指定している可能性もありますが、通常はそういうことはしないでしょう。

また、setcookieヘッダの第2引数に空文字列以外を指定した場合は、過去日付のexpiresに対するMax-Ageの挙動が変わります。下記は、1年前のexpiresを指定した場合のSet-Cookieです。
PHP 5.5.0~7.0.18  Set-Cookie: PHPSESSID=deleted; expires=Tue, 06-Sep-2016 08:22:17 GMT; Max-Age=-31536000; path=/
PHP 7.0.19~       Set-Cookie: PHPSESSID=deleted; expires=Tue, 06-Sep-2016 08:22:17 GMT; Max-Age=0; path=/
上記のように、PHP 5.5.0~PHP 7.0.18までは、負のMax-Ageがセットされますが、PHP 7.0.19以降では、Max-Age=0がセットされます。setcookieの第2引数に空文字列を指定した場合と挙動が変わるのが興味深いですね。

どうやって調べたか

このような細かい調査をするには、実際にPoCを書いて動かしてみるのが確実ですが、PHPの全バージョンとなると200を超えるので、そう簡単ではありません。私は過去の記事で紹介した modphpall を用いて、実際に動かすことで調査しました。とある診断員さんのApacheの記事では以下のように書かれていますが、
以下のコマンド(以前検証した際、togakushiさんにご指導いただいたシェル芸を記載しています)を実行してApache HTTP Serverの2.2系を全部ソースインストールして、バージョンごとに別々のポートで起動させてみます。
僕が調べたApacheバージョン判定の小ネタ より引用
modphpallも、PHPのバージョン毎に別々のポートでApacheを起動するもので、似たようなことを考えるものだな思いました。

まとめ

診断文字列を打ち込まずにHTTPレスポンスヘッダだけからPHPのバージョンを推測する方法を紹介しました。本文中にも書いたように、アプリケーションの書き方によってはご判定の可能性もあり、機械的に上記の情報を適用してバージョンを推測することは危険ですが、複数の情報や顧客からのヒアリング内容等を組み合わせることにより、脆弱性診断に有用な情報が得られると考えます。

フォロワー