AWSのApacheログにCannot allocate memoryと出た時の対処

はじめに

レンタルサーバーで運用していたサービス(Wordpress)をAWSに移行したら、管理画面の設定ページなどでHTTP 500エラーになることが度々あった。
以下のようにApacheのエラーログを見てみた

$ sudo less /etc/httpd/logs/error_log

するとCannot allocate memoryとかPHP Fatal error: Out of memoryとかのエラーが出ていて、メモリ不足だった。

とりあえず解決方法

PHPのメモリ使用料を無制限にしたら直った。

// php.iniを編集
$ sudo vi /etc/php.ini

memory.limit = 128Mってなってるところをmemory.limit = -1にしたら解決した。

テスト環境だったので、これでいいけど、本当はインスタンスのメモリを増強とかしないといけない気がする

続きを読む

[CloudFront][wordpress]CloudFrontで配信しているWordPressにビジュアルエディタが表示されない

WordPressを構築していて、こんな現象に出会った。

何をしてもビジュアルモードが表示されない!
スクリーンショット 2017-10-09 15.02.54.png

結論からいえばCloudFrontが噛んでいる構成の場合は、そいつが悪さしているようです。
わかってしまえば簡単なので、さくっとやってしまいましょう!

以下にまとめました

https://blog.vtryo.me/infra-engneering/cloudfront-wordpress-visualediter

続きを読む

[AWS] WordPressのBitnamiというバナーを消す

概要

AWSのWordPressのBitnamiというバナーを消す方法です。

1.ターミナルからbitnamiというユーザー名でログインする

こんな感じ。

$ ssh -i ~/.ssh/MyKeyPair.pem bitnami@{パブリック DNS}

ログインすると下記のようなロゴが表示されます。

       ___ _ _                   _
      | _ |_) |_ _ _  __ _ _ __ (_)
      | _  |  _| ' / _` | '  | |
      |___/_|__|_|_|__,_|_|_|_|_|

2.バナーを非表示にする

$ sudo /opt/bitnami/apps/wordpress/bnconfig --disable_banner 1

3.Apacheを再起動する

$ sudo /opt/bitnami/ctlscript.sh restart apache

おそらく役立つ情報

痒いところに手が届くかもしれない記事を書いています。
フォローしてくれるとやる気になります!

続きを読む

忙しい人のための Use AWS WAF to Mitigate OWASP’s Top 10 Web Application Vulnerabilities メモ

こんにちは、ひろかずです。

2017年7月に「Use AWS WAF to Mitigate OWASP’s Top 10 Web Application Vulnerabilities」が公開されました。
日本語翻訳されていないので、なかなか読めていない方もいると思います。
リリースから少し時間が経ってしまいましたが、読了したので一筆書きます。

どんなドキュメントか

OWASP Top10 で上っている各項目についての解説と、各項目についてAWS WAFでどのような対応ができるかを記載したもの。
Conditionを作る上でのアドバイスも記載されている。

参照ドキュメント

Use AWS WAF to Mitigate OWASP’s Top 10 Web Application Vulnerabilities

A1 – Injection

SQLインジェクション攻撃は、比較的簡単に検出できるが、バックエンドの構造によって複雑さが変わるため、アプリケーション側での対応も必要。
cookieやカスタムヘッダをデータベース参照に使う場合は、Conditionで検査対象とするように設定すること。
リクエスト中にクエリを流す事を是としているサービスの場合、対象URLを検知除外(バイパス)するような設定を検討すること。

A2 – Broken Authentication and Session Management

String Matchを活用して、盗まれた(怪しい)トークンを「安全のために」ブラックリストに登録する
デバイスのロケーションが異なるトークンを検出する等、ログから悪性利用をしているトークンを分析して、ブラックリストに登録するような使い方。
Rate-basedルールを用いて、認証URLを総当り攻撃を防ぐ施策も有効。

A3 – Cross-Site Scripting (XSS)

XSS攻撃は、HTTPリクエストで特定のキーHTMLタグ名を必要とするため、一般的なシナリオで比較的簡単に軽減できる。
BODYやQUERY_STRING, HEADER: Cookieを検査するのが推奨される。
URLを検査対象とすることは一般的ではないが、アプリケーションが短縮URL使っていると、パラメータはURLパスセグメントの一部として表示され、クエリ文字列には表示されない(後でサーバー側で書き換えられる)
CMSエディタ等、たくさんHTMLを生成するサービスには効果は薄い。
対象URLを検知除外(バイパス)する場合は、別途対策を検討すること。
加えて、<script>タグを多用するイメージ(svgグラフィックフォーマット)やカスタムデータも誤検知率が高いので調整が必要。

A4 – Broken Access Control

2017年から新たに登場
認証ユーザーの制限が適切に動作せず、必要以上に内部アプリケーションオブジェクト(不正なデータの公開、内部Webアプリケーション状態の操作、パストラバーサル、リモート/ローカルファイルの呼び出し)を操作できるというもの。
機能レベルのアクセス制御の欠陥は、一般的に後で追加されたアプリケーションで発生する。
アクセスレベルは、呼び出し時に一度検証されるが、その後に呼び出される様々なサブルーチンについては、都度検証されない。
呼び出し元のコードが、ユーザーの代わりに他のモジュールやコンポーネントを呼び出す暗黙的な信頼ができてしまう。
アプリケーションが、アクセスレベルやサブスクリプションレベルに応じてコンポーネントへアクセスさせる場合は、呼び出しの都度、検証する必要がある。

AWS WAFとしては、「../」や「://」をQUERY_STRINGやURIに含むかを検証することで、リモート/ローカルファイルの呼び出しを検出できる。
これも、リクエスト中に「../」や「://」を含む事を是とするアプリケーションには効果は薄い。
管理モジュール、コンポーネント、プラグイン、または関数へのアクセスが既知の特権ユーザーのセットに限定されている場合、Byte_MatchとIPSetの組み合わせでアクセスを制限することができる。

認証要求がHTTPリクエストの一部として送信され、JWTトークン(のようなもの)でカプセル化されている場合

  • Lambda@Edgeファンクションを用いて、関連リクエストパラメータがトークン内のアサーションおよび承認と一致することを確認することで、権限不適合リクエストはバックエンドに届く前に拒否することができる。

A5 – Security Misconfiguration

セキュリティの影響を受けるパラメータの設定ミスは、アプリケーションだけではなく、OSやミドルウェア、フレームワーク全てにおいて発生し得る。
セキュリティの影響を受けるパラメータの設定ミス例

  • ApacheのServerTokens Full(デフォルト)構成
  • 本番Webサーバーでデフォルトのディレクトリ一覧を有効にしたまま
  • エラーのスタックトレースをユーザーに戻すアプリケーション
  • PHPの脆弱なバージョンと組み合わせて、HTTPリクエストを介して内部サーバ変数を上書き

AWS WAFとしては、パラメータの設定ミスを悪用するHTTPリクエストパターンが認識可能な場合に限り対応可能。

  • A4 – Broken Access Controlと同様に、特定パスやコンポーネントに対してByte_MatchとIPSetの組み合わせでアクセスを制限を行う。(Wordpress管理画面 等)
  • 脆弱なPHPを利用している場合、QUERY_STRING中の“_SERVER[“を遮断する。

その他に考慮できること

  • Amazon Inspectorでの設定ミスの捜査(rootログイン許可や脆弱なミドルウェアバージョン、脆弱性の対応状況)
  • Amazon InspectorでのCISベンチマークとの適合性チェック
  • AWS ConfigやAmazon EC2 Systems Managerを用いた、システム構成変更の検出

A6 – Sensitive Data Exposure

アプリケーションの欠陥による機密情報の暴露をWAFで緩和するのは難しい。
この欠陥には、一般に不完全に実装された暗号化が含まれる(弱い暗号の利用を許容していること)

AWS WAFとしては、HTTPリクエスト中の機密情報を識別するパターンをString-Match Conditionで検出することで、機密情報へのアクセスを検出することができる。(ホストするアプリケーションに対する深い知識が必要)
アプリケーションが、アップロードを許容する場合、Base64を示す文字列の一部を検出するString-Match Conditionが有効(BodyはBase64でエンコードされているから)
一般的ではない手法

その他に考慮できること

  • AWS内の機能を使って、接続ポイントにて、ELBで強い暗号化suiteを使用するように制限する
  • クラシックロードバランサの場合、事前定義・カスタムセキュリティポリシーで制御できる。
  • アプリケーションロードバランサの場合、事前定義セキュリティポリシーで制御できる。
  • Cloud Frontでも利用するSSLプロトコルを制限できる。

A7 – Insufficient Attack Protection

2017年から新設
このカテゴリは、新しく発見された攻撃経路や異常なリクエストパターン、または発見されたアプリケーションの欠陥にタイムリーに対応する能力に重点を置いている。
幅広い攻撃ベクトルが含まれるので、他のカテゴリと重複する部分もある。

確認ポイント

  • アプリケーションに対して、異常なリクエストパターンや大量通信を検出できるか?
  • その検出を自動化できる仕組みはあるか?
  • 不要な通信に対して、ブロックできる仕組みはあるか?
  • 悪意のあるユーザーの攻撃開始を検出できるか?
  • アプリケーションの脆弱性に対するパッチ適用までの時間はどの程度かかる?
  • パッチ適用後の有効性を確認する仕組みはあるか?

AWS WAFで何ができるか

  • Size-Content Conditionを使うことで、アプリケーションで利用するサイズ以上の通信を検出・遮断できる。
  • URIやクエリ文字列のサイズを、アプリケーションにとって意味のある値に制限すること。
  • RESTful API用のAPIキーなどの特定のヘッダーが必要になるようにすることもできる。
  • 特定IPアドレスからの5分間隔での要求レートに対する閾値設定。(例えば、UserAgentとの組み合わせでのカウントも可能)
  • Web ACLはプログラマブルで反映が早いのが利点(CloudFrontに対しても約1分で反映)
  • ログの出力傾向から分析して、Web ACLを自動調整する機能も構築できる。

AWS WAFのセキュリティオートメーション機能の活用

  • Lambdaを使って、4xxエラーを多く出しているIPアドレスを特定してIPブラックリストに登録する。
  • 既知の攻撃者に対しては、外部ソースのIPブラックリストを活用する。
  • ボットとスクレイバに対しては、robots.txtファイルの ‘disallow’セクションにリストされている特定URLへのアクセスを行ったIPを、IPブラックリストに登録する。(ハニーポットと表現されています)

A8 – Cross-Site Request Forgery

CSRFは、WebアプリケーションのStateを変更する機能を対象としている。
State変更に係るURLやフォーム送信などのHTTPリクエストを考慮する。
「ユーザーがその行動を取っている」ということを必ず証明する機構がなければ、悪意のあるユーザーによるリクエスト偽造を判断する方法はない。

  • セッショントークンや送信元IPは偽造できるので、クライアント側の属性に頼るのは有効ではない。
  • CSRFは、特定のアクションのすべての詳細が予測可能であるという事実(フォームフィールド、クエリ文字列パラメータ)を利用する。
  • 攻撃は、クロスサイトスクリプティングやファイルインクルージョンなどの他の脆弱性を利用する方法で実行される。

CSRF攻撃への対処

  • アクションをトリガーするHTTPリクエストに予測困難なトークンを含める
  • ユーザー認証プロンプトの要求
  • アクション要求時のキャプチャの提示

AWS WAFで何ができるか

  • 固有トークンの存在確認
  • 例えば、UUIDv4を活用して、x-csrf-tokenという名前のカスタムHTTPヘッダーの値を期待する場合は、Byte-Size Conditionが使える。
  • ブロックルールには、POST HTTPリクエスト条件に加える

その他にできること

  • 上記のようなルールでは、古い/無効な/盗まれた トークンの検出については、アプリケーションでの対応が必要
  • 例えばの仕組み
  • サーバが、一意のトークンを隠しフィールドとしてブラウザに送信し、ユーザーのフォーム送信時の期待値にする。
  • 期待したトークンが含まれないPOSTリクエストを安全に破棄できる。
  • 処理後のセッションストアからトークンは削除しておくことで、再利用がされないことを保証。

A9 – Using Components with Known Vulnerabilities

既知の脆弱性を持つコンポーネントの利用
ソースや、商用/オープンソースのコンポーネント、フレームワークを最新に保つことが重要
最も簡単な攻撃ベクトルで、その他の攻撃手法の突破口にもなる。
脆弱なサブコンポーネントに依存するコンポーネントの利用しているケース。
コンポーネントの脆弱性は、CVEにて管理/追跡されないので、緩和が難しい。

  • アプリケーション開発者は、それぞれのベンダー、作成者、またはプロバイダとのコンポーネントのステータスを個別に追跡する責任を負う。
  • 脆弱性は、既存のバージョンを修正するのではなく、新機能を含む新しいバージョンのコンポーネントで解決される。
  • そのため、アプリケーション開発者は、新バージョンの実装、テスト、デプロイの工数を負担する。

基本的な対処に

  • アプリケーションの依存関係と基礎となるコンポーネントの依存関係の識別と追跡
  • コンポーネントのセキュリティを追跡するための監視プロセス
  • コンポーネントのパッチやリリース頻度、許容されるライセンスモデルを考慮したソフトウェア開発プロセスとポリシーの確立
  • これらにより、コンポーネントプロバイダーがコード内の脆弱性に対処する際に、迅速に対応できる。

AWS WAFで何ができるか

  • アプリケーションで使用していないコンポーネントの機能に対するHTTPリクエストをフィルタリングおよびブロックによる、攻撃面の削減
  • 例)HTTPリクエストを直接/間接的にアセンブルするコードへのアクセスのブロックする
  • String-matchコンディションを用いたURI検査(例えば、”/includes/”の制限)
  • アプリケーションでサードパーティのコンポーネントを使用しているが機能のサブセットのみを使用する場合は、同様のAWS WAF条件を使って、使用しないコンポーネントの機能への公開URLパスをブロックする。

その他にできること

  • ペネトレーションテスト。マーケットプレイスで買える。申請が必要だが、一部事前承認を受けているサービスでは申請が不要なこともある。(マーケットプレイス上のマークで識別可能)
  • 展開とテストのプロセスに統合して、潜在的な脆弱性を検出するとともに、展開されたパッチが対象となるアプリケーションの問題を適切に緩和する。

A10 – Underprotected APIs

2017年版の新カテゴリ
特定アプリケーションの欠陥パターンではなく、潜在的な攻撃ターゲットを示す

  • UIを持たないアプリケーションは増えてきている。(UI/API両方使えるサービスも同様)
  • 攻撃ベクトルは、A1-A9までと変わらないことが多い。
  • APIはプログラムからのアクセスのために設計されているので、セキュリティテストでは、追加の考慮事項がある。
  • APIは、(Rest,SOAP問わず)複雑なデータ構造での動作とより広い範囲の要求頻度と入力値を使用するように設計される事が多い。

AWS WAFでできること

  • A1-A9での対応と変わらないが、対APIとして追加でできる事がある。
  • 強化が必要な主要コンポーネントは、プロトコルパーサ自体(XML,YAML,JSON 等)
  • パーサーの欠陥を悪用しようとする特定の入力パターンをString-match Condition、またはByte-Size Conditionを使用して、そのような要求パターンをブロックする。

旧OWASP Top10 A10 – Unvalidated Redirects and Forwards

リダイレクトや転送要求を検証しない場合、悪意のある当事者が正当なドメインを使用してユーザーを不要な宛先に誘導する可能性がある。

  • 例)短縮URLを生成する機能がある場合、URLジェネレータがターゲットドメインを検証しないことで、悪意を持ったユーザーが正式サービス上から悪意のあるサイトへの短縮URLを発行できる。

AWS WAFでできること

  • まず、アプリケーションでリダイレクトとフォワードがどこで発生するのかを理解する(リクエストパターン等)
  • アプリケーションが使用する、サードパーティコンポーネントも同様にチェックする。
  • エンドユーザからのHTTPリクエストに応じてリダイレクトと転送が生成された場合は、AWS WAFでリクエストをQUERY_STRINGやURIに対するString-Match Conditionでフィルタリングする(リダイレクト/転送の目的で信頼されているドメインのホワイトリストを維持する)

Cloud Formationテンプレート

Web ACLと、このドキュメントで推奨されている条件タイプとルールを含むAWS CloudFormationテンプレートが用意されています。
今回は、解説を割愛します。

所感

AWS WAFの設定は基本的にDIYですが、実装のポイントをOWASP Top10になぞらえて、その対応を解説する良いヒント集だと思いました。
AWS WAFを設定する人は、一読するのがいいですね。
外部にAWS WAFの設定を依頼する人は、アプリケーションの特性をよく理解している人を立てて、設定する人とよくコミュニケーションを取ることが重要だとわかります。
セキュリティ製品の真価を発揮するには、保護する対象のサービスへの理解とサービスへの適合化が必要なのは、どんなソリューションにも共通しますね。

今日はここまでです。
お疲れ様でした。

続きを読む

AWSのマルチAZ環境でWordPress

Webサーバが2台構成(オートスケールではない)の環境でWordPressを使おうとしたら、なかなか厄介だったので作業内容をメモ。
AWSのマルチAZ環境を前提とした調査だが、複数台構成の環境全般に言える。

基本方針

WordPressは複数台サーバを前提とした設計になっていない(WordPressがローカルファイルを書き換える)ので、マルチAZ環境には向いていない。
どうしても複数台サーバにしたければ、一案としてrsyncでファイル同期する方法がある。
データベースは通常通り、RDSを使える。

ただし単純に「web1をweb2に同期」としても、WordPressがweb2サーバのファイルを書き換える可能性がある。
(後述するが、「rsyncで双方向同期+ロードバランサーでスティッキーセッション」で対応できる。)

また、gitでファイルを管理していてもWordPressがファイルを書き換えるため、この対策も必要となる。
(後述するが、「専用のテーマのみgit管理対象」で対応できる。)

具体的な構築内容

サーバ構成

Webサーバはweb1とweb2の二台構成とする。アクセスはELBで割り振るものとする。
データベースにはRDSを使うものとする。(EC2にMySQLをインストールしてデータベースサーバを構築する場合も、作業の流れは同じ。)
以下の手順では、メディア置き場としてS3は使っていない。(メディアはWebサーバに保存し、rsyncで同期する。)

公開ディレクトリ

一例として /var/www/html とする。(/var/www/vhosts/wordpress/html など他の場所の場合も、作業の流れは同じ。)

同期設定

rsyncで /var/www を双方向同期する。同期ユーザは一例としてrsyncとする。(専用に作成する。)
意図しないファイルの削除&復元を避けるため、/etc/lsyncd.conf のsyncブロックで以下の指定を行う。

delete = "running",
init   = false,

WordPress設置場所のディレクトリに以下の指定を行い、この中で作成されたファイル&ディレクトリの所有グループをapacheにする。

chown apache. /var/www
chmod 0777 /var/www
chmod g+s /var/www

セッション切れを防ぐため、ELBでスティッキーセッションを有効にする。
「Aサーバでメディアをアップロードしたが、直後にBサーバにアクセスしたのでメディアが表示されない(同期が完了していない)。」もこれで防げる。

更新方法

ファイルアップロードユーザは一例としてweb-userとする。(専用に作成する。)
アップロードはweb1サーバからweb-userで行う。(web2サーバから行っても問題ないはずだが、統一しておくと無難。)
これでファイル&ディレクトリの所有者&所有グループは

  • アップロードした … web-user / apache
  • WordPressが作成した … apache / apache
  • 同期された … rsync / apache

となる。すべて同じグループになるので、グループに対して読み書きの権限を与えれば、各ファイルの読み書きができる。

gitを使う場合

デプロイの仕組みを作る場合、web1サーバからapacheユーザでデプロイする。rsyncで同期されるので、web2サーバでのデプロイは不要。
ただしWordPress自体が自身のプログラムを書き換えるため、最低限のファイルのみgitで管理する。
.gitignore で以下の指定を行い、wordpress ディレクトリをgit管理対象外にして、専用のテーマのみgit管理対象とする。
(テーマ以外にも管理対象を追加したければ、都度追加する。)

/wordpress/*
!/wordpress/wp-content
/wordpress/wp-content/*
!/wordpress/wp-content/themes
/wordpress/wp-content/themes/*
!/wordpress/wp-content/themes/mysite

オートスケールに対応させるなら

双方向同期では対応できないので、素直にAWS公式の解説通りにすると良さそう。(未検証。)

外部 Amazon RDS データベースを備えた高可用性の WordPress ウェブサイトを Elastic Beanstalk にデプロイする – AWS Elastic Beanstalk

続きを読む

AWS(EC2+RDS)でWordPressサイトを構築する際にやることリスト

以下の構成でWordpress環境を構築する際にやることを箇条書きでまとめました。(元ブログはこちら

<構成>
Webサーバ:EC2(nginx+php7)
DBサーバ:RDS(MySQL)

各作業の細かい手順は以下を参考にしてください。

1.EC2インスタンス作成・設定

  • インスタンス作成
  • セキュリティグループ設定(インバウンド)
    • HTTP(0.0.0.0/0)
    • HTTPS(0.0.0.0/0)
    • SSH(特定のIPのみ)
  • Elastic IP設定
  • SSHログイン確認(KEY作成&ローカル配置)

2.各種ソフトウェアインストール・設定

インストール

  • sudo yum update
  • sudo yum install -y nginx
  • sudo yum install -y mysql
  • sudo yum install -y php70
  • sudo yum install -y php70-mysqlnd php70-mbstring php70-mcrypt php70-pdo php70-xml php70-fpm

自動起動設定

  • sudo chkconfig nginx on
  • sudo chkconfig php-fpm on

設定変更&再起動

php-fpm
 user = nginx
 group = nginx
 listen.owner = nginx
 listen.group = nginx
 listen.mode = 0660
 listen = /var/run/php-fpm.sock
  • sudo /etc/init.d/php-fpm restart
nginx
  • sudo vim /etc/nginx/conf.d/default.conf(新規作成)
server {
  listen 80;
  server_name hostname;
  root /var/www/html;
  index index.php index.html index.htm;

  location / {
    try_files $uri $uri/ /index.php?$query_string;
  }

  location ~ \.php$ {
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    fastcgi_pass unix:/var/run/php-fpm.sock;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param PATH_INFO $fastcgi_path_info;
    include fastcgi_params;
  }
}
  • sudo /etc/init.d/nginx restart

3.RDSインスタンス作成・設定

  • DBのパラメータグループの作成(日本語対応)

    • character_set_client → utf8
    • character_set_connection → utf8
    • character_set_database → utf8
    • character_set_server → utf8
    • character_set_system → utf8
  • インスタンス作成
    • MySQL
    • パラメータグループ指定
  • セキュリティグループ設定(インバウンド)
    • MySQL/Aurora(EC2のセキュリティグループを指定)

4.Wordpressインストール・設定

続きを読む