Onishi注意喚起と反省をかねて書きます。マルウェア化しました。この拡張機能はjQuery未導入ウェブページにワンクリックでjQueryをロードできる開発者向けものです。拡張機能ストアからは削除済み)なお、今回は私用のChromeアカウントで感染が判明し、仕事などで使用している個別のアカウントでは関連する拡張機能を導入しておりませんので、所属する会社や個々に依頼いただいている業務データなどへの影響はないことを先に明記いたします。いうポップアップ広告が出現するようになりました。偶然にも最初の数回が初回アクセスの英語圏のサイトで起こったため、マルウェアによるものだと気付くのが遅れてしまいました。何度か表示されている内に、拡張機能によるものだと推測し調査を始めました。ほか)情報が公開されました。次のページに日本語で完結にまとまっているため、是非一読ください。(英語)https://imagetragick.com/概要と影響範囲ImageMagick内で処理する際にコマンドのエスケープが完全でなかったことが原因で、リモートで任意のコードを実行可能になります。次のmvgファイルを作り、処理させることで再現できます。Onishi随分昔に話題になっていたのですが、Twitterで偶然この話題を見つけたので書いてみます。使用しているiPhone端末などから、接続しているWiFiアクセスポイント(以下AP)のMACアドレスとモバイル端末のGPS情報を収集しています。ために使われています。(別にこの手法はGoogleが悪者というわけではなく、MicrosoftやAppleをはじめとして、日本ではPlaceEngineなど、広く使われています。いうものが提供されています。問題はこのAPIの一部に対し、APのMACアドレスを与えることで、誤差数十メートルの圏内までAPの位置が特定できることにあります。これは悪用を考えたとき、例えば遊びに行った友達のMACアドレスを使えば過去に住んでいた場所が特定できる可能性もありますし、引っ越した後も同じAPを使っていれば容易に新しい住所を知ることができます。一般的なケースでは、例えば古いAP機器を友人に譲る際に、下記のオプトアウトを実施していないと自宅の住所が知られてしまいます。Encryptをnginxで使ってみる)SSLの更新時期を思い出したウソです忘れてました。忘れてたところ、こんなメールが先週届いていました。これはありがたい・・・本当にエラーになってから思い出すところでした。Encrypt本体をアップデートしておきます。Onishi最近、アプリケーションなどから利用するAWSの認証情報(credentials)をgithubなどの公開リポジトリに誤ってコミットしてしまい、不正利用され高額な使用料を請求されるケースが増えています。いくらルートアカウントを無効化してIAMユーザーを使おうが、2段階認証を導入しようが、認証情報をヒューマンミスで公開してしまっては意味がありません。万が一、認証情報を公開してしまった場合は、一刻も早くAWSの管理コンソールから公開してしまった認証情報のアクセス権限を取り消しましょう。それが会社で使っている認証情報だとしたら本当に1分1秒を争いますので、深夜だろうが構わずにAWSを管理しているエンジニアを電話で叩き起こして助けを求めてください。放置すると高確率で首が飛びます。いうgitのプラグインがあります。する必要がありました。先月の26日にformulaがHomebrewのmasterにマージされ、brew経由でより簡単にインストールできるようになりました。昔からhomebrewを使っていた人は、formulaの一覧を更新しないとインストールできないため、まずupdateしてからinstallします。コマンドが使えるようになっているはずです。リポジトリへ設定git-secretsはまだ有効になっていません。リポジトリ単位で有効化する必要があるので、ここでは適当に新しいリポジトリを作ることにします。.git/hooks/prepare-commit-msg見ての通り、pre-commitをフックして実現しています。次にどのルールにマッチしたとき、コミットを拒否するか指定します。パラメータを使えます。パラメータで確認できます。wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY上の出力3行目では、大文字英数20文字にマッチして拒否しているようですね。乱暴じゃないかと思いましたが、実際プログラミングをしていて大文字固定で20文字も打ちませんからね。keys)だそうです。実際に使ってみるちゃんと弾いてくれるか確認してみます。"wJalrXUtnFEMI/K1MDENG/bPxRfiCYEXAMPLEKEY";適当にそれっぽいのを書いて、これでコミット。positive弾いてくれました!まとめ実際の運用では、認証情報やパスワードなど本当に外部に漏れてマズいものは、環境変数にセットするのが個人的にはオススメです。そもそもファイルに書かない運用であれば、ファイルの取扱い不備でリークする可能性がゼロになり、セキュリティリスクを減らせます。いえ、実情そんなこと言ってられないケースも多いですので、ファイル+.gitignoreで気をつけて運用するのが一般的でしょうか...。万が一のためにAWS内外問わず、トークンごとに権限設定ができるものは必要最小限の付与に留めるようにしましょう。AWSの場合、ルートキーでないと使えないAPIがあったりもするみたいですが......。secretsは他にも、既にインデックスされているファイルの中にキーが混ざっていないかどうかをスキャンしたりすることもできます。詳しく知りたい方は公式のドキュメントをどうぞ。所感AWSなんかは凄い勢いで請求額が増えていくサービスが山ほどあります。ルートキーなんかが漏洩したと思うとゾッとしますね......。従量課金制のクラウドサービスを使う際には、そのセキュリティにはより一層の注意を払って取り扱いたいですね。Onishiたいそうなタイトルだけど実際そんなことない。思ったより長くなってしまったのでお時間のあるときにどうぞ。今までWordPressのデプロイにはrsyncを使って同期させていたんですが、WordPress専用のRuby製デプロイツール、WordMoveを使ってみようと思い立ちこちらの記事を参考にしながら準備しました。WordMoveはSSHやFTPでログインしてファイルを置き換えるために、ログインユーザーがドキュメントルート以下への書き込み権限を持っていないとデプロイできません。前述の参考記事ではドキュメントルート以下の所有者と、ウェブサーバーの実行ユーザーをec2-userに変更する荒技で解決しています。ここが自分の中でめちゃくちゃ引っかかったので、セキュリティ的により良いと考える権限管理ついて書いてみます。Hatが共有ディレクトリのベストプラクティスとして提案していたようです。)今回のゴールデプロイ用の専用ユーザーを作り、WordMoveはデプロイ用のユーザーからデプロイを実施するウェブサーバーの実行ユーザーは変更しない(apacheまたはnginx)上記のままうまく回るようにユーザーとディレクトリのパーミッションを変更するデプロイ元の環境で鍵ペアを作る今回はVCCWを使ったVagrant内のWordMoveを使います。WordMoveはrootになって使う必要もないので、今回はvagrantユーザーで鍵を作ります。~/.ssh/id_rsa.pub秘密鍵のパスフレーズは必要に応じて設定してください。ように最後にpubが付いたものだけです。これがWordMoveの公開鍵になるので控えておきます。これを漏らしてしまうとデプロイ対象のドキュメントルート以下を丸々書き換えることができてしまうので、十分に気をつけてください。いう名前で作成します。authorized_keysを保護デプロイユーザーが対象のディレクトリに書き込めるようにする今回のデプロイ対象はウェブサーバーの実行ユーザーが所有しているドキュメントルートです。今回はnginxを使っており、所有権はnginx:nginxです。戦略としては、nginxのグループにdeployerユーザーを追加し、ドキュメントルート以下のディレクトリに対してグループ内からの書き込み権限を付与します。グループに書き込み権限を与えるこれで終わり...なら簡単で、記事にすることもないんですが、2つ問題があります。deployerでファイルの編集をしてみます。/usr/share/nginx/html/index.php次はデプロイ先にないファイルをデプロイしてファイルを作成することを想定してtouchしてみます。/usr/share/nginx/html/index-new.php次にパーミッションをチェックします。index-new.php1つめの問題です。deployerグループにnginxを追加してしまう方法もありますが、一貫性が無くなってしまう上に、何かグループに対して権限を付与する際にも複数のグループを気にすることとなり運用コストが高まります。これを解決する方法として特殊なパーミッションビット、setgidを使います。並んで紹介されることの多いLinux系ファイルシステムにおける特殊なパーミッションビットのことです。bitは使わないので省略します。idの略で、このパーミッションを有効にしたディレクトリ内でファイルやサブディレクトリを作成すると、setgidを付与したディレクトリと同じグループが所有グループとなります。グループを継承することができるということです。指定することで設定できます。/usr/share/nginx/html/index-new2.phpチェックしてみます。index-new2.phpデフォルトでグループがnginxに割り当てられています。思ったら、新しく作られたファイルのグループはnginxになっていますが、よく見るとグループへの書き込み権限がありません。デフォルトパーミッションを変更するここまでで、ファイルやディレクトリを作成したときに所有グループを継承できるようになりました。最後は、デフォルトのパーミッションでグループに書き込み権限を付与することです。これにはumaskを使います。umaskは許可*しない*ビットを指定する方法なのでかなり柔軟に設定できます。002(=664、自分とグループの人が書き込み可)に変更したいわけです。002テストしてみます。index-new3.php新規ファイルも664のパーミッションで、グループを継承できました!念のためにサブディレクトリを作って、その中でファイルを作っても同様の結果になることを確認しておきましょう。テストが済んだらテスト用ファイルはすべて消しておきます。WordMoveでデプロイしてみる今回はWordMoveを使っていますがWordMoveの紹介ではないので簡単に。実際にdeployerユーザーを使ってデプロイしてみます。Databaseで、サーバー側でmysqldumpが効かなくて一度コケましたがmysqlをyumで入れて解決しました。--themesちゃんとプッシュできていることを確認して終わりです。雑感ここまで書いておいて何ですが、本当はこのように役割ごとにユーザーを切り分けるべきだと信じています。面倒くさくて、最後デプロイツールでも一工夫必要なことを考えると、同一ユーザーでやってしまいたくなるのもとても分かります。Onishi非SSL環境で動かしていたWordPressをSSL化するときの手順です。Encryptを使って認証された証明書が手に入ったので、これを使ってWordPress全体をSSL化してみました。手順を備忘録として残しておきます。wp-config.phpの修正まずは基本ですね。WP_HOMEとWP_SITEURLを書き換えます。FORCE_SSL_ADMINを設定することで管理画面はHTTPSを強制できます。option_nameカラムがsiteurlになっているレコードを探し、値のhttp://をhttps://に書き換えます。続いてoption_nameカラムがhomeになっているレコードを探し、同じように書き換えます。HTTP接続をHTTPSにリダイレクト上の2ステップでWordPressのシステム的な部分の移行が終わりました。HTTPSで適当なページを開いて正しくリンクが遷移できるか、リンク遷移後もページもHTTPSになっているか、画像や画像のサムネイルが正しく読み込めているか、管理画面へHTTPSのままログインできるか、などをチェックします。問題がないようであれば、httpでの接続はすべてhttpsにリダイレクトするようにします。httpsにすると若干サーバーの負荷も増えますので、ハイトラフィックなブログを運営されている方はhttpの方が有利という考え方もできます。ブログであれば、http/httpsどちらでもアクセス出来るようにしておき、通信を暗号化するかどうか判断をユーザーに委ねるのも良い方法です。)今回nginxを使っているので、nginx.confを書き換えることにしましょう。リダイレクトにはrewiteを使っているブログも多く見られますが、nginx.orgではreturnが使われていたのでreturnを使うことにします。計った訳ではないですが、シンプルな分処理も早そうです。ssl;}保存したらnginxを再起動します。restart再起動が終わったら、適当なURLを叩いてみてHTTPSに正しくリダイレクトされることを確認します。Content問題)これで9割方終わっていて、SSLにするという目的自体は達成なのですが、次のように「このページに安全でない他のリソースが含まれています。」と表示され、URLのアイコンや文字色も緑色にならないことがあります。これは、アクセスしているページはSSL接続にも関わらず、そのページ内から非SSLの静的ファイル等をロードしているためです。続く形でロードしていることに起因するものが多いです。これらを見つけて、httpsが提供されているコンテンツはhttpsでロードするように、提供されていない場合はライセンスを確認して自分のサーバーでホスティングできるか確認して移行するなどの対策を行います。量が多いと結構大変ですね...。Chromeのデベロッパーツールにあるコンソールが助けになります。上の画像のように、過去にアップロードした画像ファイルに起因するものであれば、次の項を読んでみてください。テーマやプラグインに起因するものは、手動で直さなければいけません。URLという仕様により、CSSやJavaScriptをロードする際のhttpやhttpsを省いて記述すると、読み込み元のスキーム(SSLか非SSLか)に従って読み込むスキームも変更されポータビリティが高まります。SSLのページからロードさせた場合はhttps://〜と解釈され、非SSLのページからロードさせた場合はhttp://〜と解釈されます。Contents問題を直すこの場合、基本的には記事を編集して、画像へのURLを書き直すことで修正できますが、過去の記事・画像が多いと直すのに骨が折れます。RelativeなURLに画像リンクを書き換えるSQL文を使うと一瞬で解消できるでしょう。テストしていますが、万一のために必ず実行前にテーブルのバックアップを取ってください。ContentsによるSSLの警告も消えました。雑感サクっとこなすつもりが意外と色々気にすることがあって大変でした。一度やっておくとノウハウ的に使い回せるので、知識として蓄えておきたいですね。SPDY対応や、証明書の透明性確保あたりを触れたらいいなと思っています。Encryptとはhttps://letsencrypt.org/無料で認証されたSSL証明書を発行できるサービスです。今月パブリックベータになり、誰でも試すことができるようになりました。Tech界隈では今アツい技術の一つです。今回使うnginxは1.8系のため、HTTP/2、SPDYは使えません。メインラインの1.9系を使うことで対応できるので、興味がある方は別に調べてみてください。Encryptを使うためには、nginxやapacheなどのウェブサーバーのほかGitが必要です。Encryptが自動的にインストールしてくれます。Gitがインストールされていなければ、事前にyumで入れておきます。Encryptのクライアント本体を適当な場所にgitでクローンしておきましょう。gitが必要な箇所はここだけです。頻繁に更新されているようなので、都度ローカルリポジトリも追従させてあげるのが良いでしょう。このコマンドを実行した場合、letsencryptが使用する必要なライブラリがインストールされていなければ自動でインストールしようとします。rootで実行していない場合はパスワードを入力してください。EC2で実行している関係で上のような警告が表示されました。EC2上で利用するのであれば一般的なCentOS等と使い方は何ら変わりませんので、言われるままに継続します。manually一度debugをつけて実行した後はdebugなしで利用できるようです。発行にはドメインの所有権認証が必要です。letsencrypt-autoでは、次の方法でこの認証を簡単なコマンドだけで実行できます。3種類の証明書取得方法をサポートしています。apacheを使っている場合はapacheを使うと自動でインストールしてくれます。standaloneはletsencrypt自身がウェブサーバーを起動して所有権の認証を行います。webrootは既にウェブサーバーが起動している場合、ドキュメントルートを指定して既存のサーバーを介して認証を行います。今回はnginxですし、既に起動しているサーバーに対してインストールしょうとしているので、3番目のwebrootオプションを使って認証を行います。<ドメイン>上記を実行するとメールアドレスの入力と利用規約への同意が求められますので、指示通り進みます。認証情報を紛失した際などは、ここで登録したメールアドレスを使ってリカバリするので間違えないように気をつけてください。次のようなメッセージが出力されれば、正しく証明書を取得することができました。中に証明書類が保存されています。証明書をウェブサーバーにインストールする前に、セキュリティ向上のために実行することをおすすめします。opensslコマンドで生成します。AWSのsmallインスタンスで3分程度かかりました。環境によってはもっと時間がかかるかもしれません。最後に取得したSSL証明書をnginxから参照して利用できるようにします。includeSubDomains;';}上の通り変更して、nginxを再起動します。設定ファイルに問題がなければSSLで通信できるようになっていますので、テストしてみましょう。使って簡単に実施できます。最低限の設定を施しただけだとCやDランクになるかと思います。POODLEや弱いDHパラメーター、ダウングレード攻撃などの脆弱性を防いでいない場合は評価が下がります。前述のnginx.confの設定を施せばAまたはA+の評価になると思います。ときどきこのサイトでSSLの安全性をチェックして、常にこの評価をキープしていきましょう。以前から無料で発行できるSSL証明書もありましたが、手続きが煩雑だったりと色々厄介なことが多かったです。Encryptもまだ改善の余地はあり、速い速度で開発も進んでいますので、まだまだ今後に期待できるでしょう。EncryptでSSL対応が当たり前な時代になれば良いですね。OnishiいくらWordPressをホストするサーバーのセキュリティを高めたところで、WordPressが脆弱だと意味がありません。WordPressのセキュリティ対策をまとめてみます。それぞれの先頭の★は、3段階でその対策の効果を元にしたお勧め度を表します。管理用のユーザー名を変更する(★★★)ログインする際のユーザー名は管理画面の設定から変更することができません。新しくユーザーを作成し、古いユーザーを削除する方法で管理用のアカウントを作り直すことができます(記事は引き継げます)。adminのような脆弱なユーザー名を使っているのであれば、今すぐにでも変更すべきです。当然ですがパスワードは使い回さず、堅牢なものを設定しましょう。ログイン時に2段階認証を行う(★★★)2段階認証というのは、IDとパスワードの他にワンタイムパスワードを入力する方式のことです。管理画面へのブルートフォース攻撃対策にとても有効です。Authenticator」プラグインがお勧めです。ユーザー毎に二段階認証の有効無効を切り替えることができます。Authenticator」のアプリをインストールして、WordPressのユーザー管理画面に表示されたQRコードをスキャンして紐付けます。ちなみに、有料版の1Passwordなど一部その他ワンタイムパスワード用のアプリでも利用可能です。アクセスすることでログインページが表示されますが、このログイン用のファイル名を変更してしまうことでそもそも不正なログインを試される可能性がぐんと下がります。直接コードに手を加えて実現することも可能ですが、日本語対応のお勧めプラグインもあります。これも簡単に実装可能な上、効果はとても大きいので是非実装しましょう。他のセキュリティ系プラグインとの相性が悪いこともあるのでその点は要注意です。wp-config.phpファイルを守る(★★☆)このファイルはWPがデータベースに接続するための接続情報などが含まれ、流出などに一番気をつけなくてはいけないファイルです。PHPのコードになっているため、PHPファイルが正しく処理される環境下では基本的に問題になることはありませんが、万が一PHPが正常に処理されなかった場合に備えてウェブサーバー側で対策を講じておきましょう。nginxの場合、/etc/nginx/nginx.confのserverセクションに以下を記述します(ただしphpをハンドリングしている箇所より上に書く必要があります)。}apacheの場合、WPルートにある.htaccessに下記を追記します。all</files>xmlrpc.phpを無効化する(★★☆)WordPressは3.5以降、デフォルトでXML-RPCの機能が有効になっています。これはpingbackやメール投稿などの機能をサポートするものですが、pingbackの悪用によりDoS攻撃の踏み台にされることがあります。Forbiddenが返されるはずです。WordPressのバージョンを隠す(★☆☆)WordPressで生成されたページのソースコードには、metaタグやcssのサフィックスとしてWordPressのバージョン番号が記載されています。バージョン番号が知られてしまうと、既知の脆弱性を用いた攻撃が容易となります。悪意のある攻撃者へ情報を与えないために、バージョン番号を出力しないようにしましょう。これもプラグインを用いることで用意に実現できます。Version」というプラグインをインストールして有効化するだけで、ソースコードにバージョン番号が出力されなくなります。readme.htmlを削除する(★☆☆)インストールする際のreadme.htmlがルートディレクトリに残っていたりしませんか?このファイルにもWordPressのバージョン番号が含まれています。存在するようなら消しておきましょう。テーブルのプレフィックスを変更する(★☆☆)データベースのテーブルに割り当てられるプレフィックスです。設定されているのであれば、これも別のものに変更されることをお勧めします。SQLインジェクションの対策になります。インストール済みのWPでプレフィックスを変更することも可能ですが、手を入れなければならない箇所が多く、長くなるので割愛します。管理画面からソースコードの編集を禁止する(★☆☆)wp-config.phpに次の行を追記することで、管理画面からテーマやプラグインのソースコードを編集できなくすることができます。true);これは管理権限を持つユーザーの不正なコードの改竄を防ぐ効果があります。不正に第三者に管理画面にアクセスされた際にも限定的ながら有効です。その他wp-adminのホスト制限これも良い対策の一つですが、私の場合は外出先からでも執筆のためアクセスすることが多く、IPを固定できないため敢えて導入していません。その場合でも、国外からのアクセスなど出来るだけ絞り込むというのは十分にアリな対策です。HTTPS化DBユーザの権限設定ファイルパーミッションなどまとめいくつか対策を挙げてみました。WordPressを用いたサイトを運用する上での、セキュリティ対策の一助になれば幸いです。