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のバージョンを推測する方法を紹介しました。本文中にも書いたように、アプリケーションの書き方によってはご判定の可能性もあり、機械的に上記の情報を適用してバージョンを推測することは危険ですが、複数の情報や顧客からのヒアリング内容等を組み合わせることにより、脆弱性診断に有用な情報が得られると考えます。

2017年5月12日金曜日

ECセキュリティ対策セミナー(大阪)開催します

HASHコンサルティング株式会社は、本日からEGセキュアソリューションズ株式会社に社名変更いたしました。

新しいオフィシャルサイト: https://www.eg-secure.co.jp/

皆様におかれましては、これまで同様のご愛顧をよろしくお願い申し上げます。
新社名での初めてのイベントとして、5月18日大阪にて株式会社ロックオンとの共催セミナーを開催いたします。

日時:2017年5月18日(木) 14:00~16:45
場所:大阪産業創造館 6F会議室B(大阪市中央区本町1-4-5)
費用:無料(申し込みはこちら
講演タイトル:ECサイトオーナーと開発会社が今やっておくべきセキュリティ施策とは

あいかわずECサイトに対する侵入事件が続いており、最近ではStruts2の脆弱性S2-045 (CVE-2017-5638) による一連の被害が記憶に新しいところです。
一方、脆弱性対処の責任はECサイトオーナーにあるのか、開発会社にあるのか、昔からある議論ではありますが、結論としては立場に応じて責務をまっとうするという当たり前のことしかないわけですが、それではその「当たり前」のことはどこまでやればよいのでしょうか。

実は、ウェブサイトの防御に用いる要素技術それぞれについては、目新しいものがあるわけではなく、その多くは昔からある技術の組み合わせです。つまり、新しい技術を導入すればよいということではないわけですが、脆弱性の発見から攻撃に至るスパンがますます短くなっており、攻撃が組織化・自動化されているにも関わらず、防御側の意識があまり変わっていないことが問題であると考えています。
とはいえ、セキュリティに掛けられる予算が無尽蔵にあるわけではないことから、限られた予算を効果的に配分して、効果的な防御を行うことが肝要と考えます。

当セミナーでは、まずはECサイトをめぐる攻撃について何パターンかデモでお見せした後、上記のための基本的な考え方と、弊社でお手伝いできるサービスについて紹介させていただきます。

皆様の参加をお待ちしております。

フォロワー