[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
ラベル security の投稿を表示しています。 すべての投稿を表示
ラベル security の投稿を表示しています。 すべての投稿を表示

2016年12月20日火曜日

クラウドN (cloudn)でのサーバ構築


クラウドといえばAWSしか使ったことがないので、主にAWSと比較しながら備忘録的にメモ。
FLATタイプでCentOS 7の場合。


AWSと同じようなところ

  • セキュリティグループの受信規則は、記述されていないものはDENYなので(デフォルトは設定なし=全て拒否)、許可するものを設定する。
  • セキュリティグループの送信規則は逆にデフォルトALLOWなので、禁止したい場合のみ設定する。
  • サーバ(Compute)を起動すると、サーバに対してグローバルIPが与えられる。
  • サーバにはデフォルトでPython 2.7が入っていた。


AWSと違うところ
(良いところ)

  • データ転送量についての課金が無い。
  • サービスが少ないので管理コンソールがシンプル。
  • 接続元IPアドレスによる管理コンソールのアクセス制限が簡単。
  • サーバ起動時に指定したhost名がサーバ内にも適用される。
  • 一番小さいインスタンスでもデフォルトでswapがある。
(悪いところ)
  • サーバ停止中でも課金される。(稼働中よりは安いが。)
  • サーバ削除のプロテクト設定が無いのがちょっと怖い。
  • 管理コンソール等のタイムゾーンがUTC。
  • 管理コンソールで意味不明な部分がある。(OpenStackの仕様をしらべればいいのか...?)
  • サーバ起動後にセキュリティグループを変更できない。
  • サーバはデフォルトでrootのSSHログインが可能。鍵ファイルではなくパスワード認証。
    ※パスワードはサーバ登録時に生成され、管理コンソール上で1度だけ表示される。管理コンソールからリセットもできる。リセットするとsshdの設定(SSHのrootログイン禁止、パスワード認証禁止、鍵ファイルによる認証の許可など)も初期化される。
  • サーバのテンプレート(AWSでいうところのAMI)を作る前に、手動でサーバを停止しないといけない。
(その他)
  • サーバのSELinuxはデフォルトで有効。
  • SMTPはpostfixが入っている。



本番用テンプレートを作る時にまずやることのメモ
CentOS 7のコマンドがCentOS 6から色々変わってるので慣れないと...。

  • タイムゾーンの設定(/root/tzconfigurator.shという対話形式の設定ツールが用意されているが、itamaeと相性が悪い?)
  • yum update
  • Linuxユーザーの追加(SSH用公開鍵のセットも)
  • rootのSSHログイン禁止
  • SSHのパスワード認証の禁止と、鍵認証の許可
  • メール送信先の変更(/etc/aliasesの編集)

以下は必要に応じて




参考



2016年10月30日日曜日

MySQLへの接続の暗号化



基本
MySQLでSSLクライアント証明書を使う - Qiita

※MySQL側のCommon Nameはサーバのホスト名にする


暗号化されていることを確認するSQL
show status like'Ssl_cipher';
MySQL5.6での注意点 MySQL 5.6でSSL接続が有効にならない・クライアントからSSL接続できない。 - ah-2 WindowsのMySQL Query Browserでは、caだけでなく、下記の全てを指定しないと接続できないようだ。
USE_SSL => "Yes" SSL_CA => ca.crtのファイルパス SSL_CERT => client.crtのファイルパス SSL_KEY => client.keyのファイルパス
ファイルパスのバックスラッシュ(¥)はバックスラッシュのままでも、スラッシュにしてもどちらでもOK。 ファイルパスのスペースが含まれていてもOK。 ca.crtは、server.crtとclient.crtの中身を合わせる必要はないようだ。 参考:MySQL :: MySQL Administrator :: 21.4.1 SSL Connections REQUIRE SSLなユーザーだと、MySQL Query Browserの上部メニューからのMySQL Administratorの起動や、逆にMySQL AdministratorからMySQL Query Browserの起動ができない。(直接起動すれば起動できる。)

2016年6月25日土曜日

Let's Encryptの cronによる実行が動かなくなった時の対策

certbot (Let's Encrypt)を Amazon Linuxにインストールの後日談。
OSはAmazon linux。

cronの結果がメールで送られてきた。

Checking for new version...
Upgrading certbot-auto 0.6.0 to 0.7.0...
Replacing certbot-auto...
Creating virtual environment...
./certbot/certbot-auto: line 530: virtualenv: command not found

cronを再実行してみる。
WARNING: Amazon Linux support is very experimental at present...
if you would like to work on improving it, please ensure you have backups
and then run this script again with the --debug flag!

言われた通りにコマンドを変更。
./certbot/certbot-auto renew --debug && sudo service httpd reload

再実行。
Bootstrapping dependencies via Amazon Linux...
yum is /usr/bin/yum
Loaded plugins: priorities, update-motd, upgrade-helper
Package gcc-4.8.3-3.20.amzn1.noarch already installed and latest version
Package dialog-1.1-9.20080819.1.5.amzn1.x86_64 already installed and latest version
Package augeas-libs-1.0.0-5.7.amzn1.x86_64 already installed and latest version
Package 1:openssl-1.0.1k-14.91.amzn1.x86_64 already installed and latest version
Package 1:openssl-devel-1.0.1k-14.91.amzn1.x86_64 already installed and latest version
Package libffi-devel-3.0.13-11.4.amzn1.x86_64 already installed and latest version
Package system-rpm-config-9.0.3-42.27.amzn1.noarch already installed and latest version
Package ca-certificates-2015.2.6-65.0.1.15.amzn1.noarch already installed and latest version
Package python27-2.7.10-4.120.amzn1.x86_64 already installed and latest version
Package python27-devel-2.7.10-4.120.amzn1.x86_64 already installed and latest version
Resolving Dependencies
--> Running transaction check
---> Package python27-pip.noarch 0:6.1.1-1.21.amzn1 will be installed
---> Package python27-tools.x86_64 0:2.7.10-4.120.amzn1 will be installed
---> Package python27-virtualenv.noarch 0:12.0.7-1.12.amzn1 will be installed
--> Finished Dependency Resolution
Dependencies Resolved
================================================================================
 Package                 Arch       Version                 Repository     Size
================================================================================
Installing:
 python27-pip            noarch     6.1.1-1.21.amzn1        amzn-main     1.9 M
 python27-tools          x86_64     2.7.10-4.120.amzn1      amzn-main     706 k
 python27-virtualenv     noarch     12.0.7-1.12.amzn1       amzn-main     2.0 M
Transaction Summary
================================================================================
Install  3 Packages
Total download size: 4.6 M
Installed size: 11 M
Is this ok [y/d/N]: Exiting on user command
Your transaction was saved, rerun it with:
 yum load-transaction /tmp/yum_save_tx.2016-06-22.11-17.hYs7z_.yumtx
Could not install OS dependencies. Aborting bootstrap!

cronでなく手動で実行し、パッケージをインストール
./certbot/certbot-auto renew --debug

正常終了。
以降はcronでも"--debug"無しでも大丈夫になったが、"--debug"を付けておいた方が無難?

2016年5月21日土曜日

Qualys SSL Server Testでレートを Aプラスにする


Qualys SSL LabsのSSL Server Testで、A評価を得てみる。


環境

  • OS: Amazon Linux 2016.03
  • Webサーバ: Apache 2.4.18
  • OpenSSL: 1.0.1k
  • サーバ証明書: Let's Encrypt(certbot)



デフォルト設定
SSLProtocol all -SSLv3
SSLHonorCipherOrder on

B
This server accepts RC4 cipher, but only with older protocol versions. Grade capped to B.


SSLCipherSuiteも指定(コメントアウトされている推奨?設定+RC4も禁止)
SSLCipherSuite HIGH:MEDIUM:!RC4:!aNULL:!MD5

A


HSTSを追加
Header always set Strict-Transport-Security "max-age=15768000"

A+
HTTP Strict Transport Security (HSTS) with long duration deployed on this server.


さらにProtocol Supportを満点にするには、TLS1.2のみにすればOK。
Key ExchangeとCipher Strengthを満点にするには?SSLCipherSuiteをきちんと指定する??



参考



certbot (Let's Encrypt)を Amazon Linuxにインストール


以前一度挫折した(古いAmazon Linuxをアップデートして使っているためだと思われる)が、certbotに改名後に試してみたら、できた。


前提

  • gitはインストール済み
  • WebサーバはApache



手順

  1. sudo easy_install pip
  2. sudo pip install --upgrade pip
  3. sudo /usr/local/bin/pip install --upgrade virtualenv
  4. (作業用ディレクトリで)
    git clone https://github.com/certbot/certbot
  5. cd certbot
  6. ./certbot-auto certonly --webroot -w /var/www/html -d ドメイン名 --agree-tos -m メールアドレス --debug
  7. /etc/httpd/conf.d/ssl.confの下記箇所を変更する。(Apache2.4.8より前のバージョン場合は微妙に違うので参考サイト参照。)
    SSLCertificateFile /etc/letsencrypt/live/ドメイン名/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/ドメイン名/privkey.pem
  8. httpdを再起動


証明書の自動更新
証明書の期限は90日なので、cronで定期更新させる。cronがメールを飛ばすように設定してあれば結果がメールで来る。

(例:月に1回更新する場合。日時は月初にすると混雑しそうなので、適当にずらした方がよいかも。)
45 3 12 * * ./certbot/certbot-auto renew && sudo service httpd reload

(2016/6/25 追記)
--debugも付けた方がよいかも?参考→Let's Encryptの cronによる実行が動かなくなった時の対策
(追記終わり)

期限まで30日以上ある場合は更新されない。それでも更新したい場合は--force-renewオプションを付ける。
上記例を試した時はまだ更新されなかったので、本当にこれでよいかはその日が来てから確認する。(--debug無しとか大丈夫か?タイミングによっては、月イチだと期限切れになるケースがあるかも?)


備考的な

  • Aapcheは停止しなくても大丈夫。(webrootオプションを使う場合はいいらしい。)
  • 証明書生成時にポート443は開いてなくても大丈夫。
  • /var/www/htmlに.well-knownディレクトリが残る。消してもいいのかな?



さよなら自己署名!さよならオレオレ証明書!


参考



2016年5月1日日曜日

シマンテックのクロスルートなサーバ証明書が使えなくなる?

2016年4月のマイクロソフト社のルート証明書情報更新の影響と対策に関するご案内(続報) | Symantec

意訳
Microsoftが2016年4月19~20日(日本時間)に配信するルート証明書情報の更新により、シマンテックのクロスルートを付けているサーバ証明書を使っている場合にWindows上の(Firefox以外の)ブラウザで警告が出るようになる。
回避するにはクロスルートを外す。


このMicrosoftの更新はWindows Updateとは別らしい。
なお、4/19~20となっているが4/20になってMicrosoftが更新を延期したらしい。(結局、4/26~27に実施。)


クロスルートを外すと、ガラケー等で使えなくなるのでは?

クロスルート設定用証明書の設定について、どのような対応が必要でしょうか? | Symantec のPDFによると、ガラケーへの影響は2機種のみ。スマホでもいくつか影響があるが、発売が2010年以前なので影響は少なそう。SHA-1を切り捨てたことにより、既に古いガラケーの多くはSSL/TLSの対象外になっていた。

ちなみに、 Windowsが遂にSymantecG1ルートを捨てるらしい - 情緒不安定。 によるとクロスルート証明書のIssuerが問題なので、中間CA証明書(クロスルートを含む)自体がG1でなくても影響がある。(シマンテックがクロスルート証明書として配布している VeriSign Class 3 Public Primary Certification Authority - G5 のIssuerがG1なので。)


クロスルートを付けている場合に問題が発生するクライアントPC(Windows)の条件を見ると、

条件3 : クライアント環境のルート証明書ストア(Windows Trusted Root Store)に、G5ルート証明書*2が含まれていない場合
*2「VeriSign Class 3 Public Primary Certification Authority - G5」
とある。

おのれSSL!謀ったな・・!! | ツチノコブログ によると、
最近のブラウザではPC/スマフォ問わずにG5証明書が予めインポートされています。ですがwindowsXPのSP2以前やフィーチャーフォンの一部端末はG5証明書がインポートされておらず、『VeriSign Class 3 Public Primary CA』(通称:G1証明書)がインポートされています。

【追記有(2016.04.22)】Windowsが遂にSymantecG1ルートを捨てるらしい - 情緒不安定。 でも、
SymantecG5ルート証明書が入っていないパソコン。
つまり、レガシーなパソコンです。(WindowsXP以前、WindowsUpdateなどを定期的に行ってないと怪しいです。)
とあるので、Windows Vista以降は大丈夫?

でも 2016年4月のマイクロソフト社のルート証明書情報更新の影響と対策に関するご案内(続報) | Symantec によると、XP以降はG5証明書が初期状態ではインストールされていなくて、必要になったらインストールされるらしい。インストールされていない状態でシマンテックのクロスルートに当たると、G1の方を読んでしまうのでエラーになってしまう。


HTTPS セキュリティ証明書における SHA-1 から SHA-256 へのハッシュアルゴリズムの変更について によると、クロスルート無しでクライアント(接続元)がJavaの場合、
1.4.2 より前 → 接続できない
1.4.2 ~ 1.6.0_18 → ごにょごにょしてG5をCAストアに追加すれば接続できる
1.6.0_19 以上 → 接続できる

Java SE 6 Update 19 Release Notes. から Bug ID: JDK-6904162 Add new VeriSign root CA certificates to JRE and remove some old/unused ones を見ても、「verisignclass3g5ca」とあるので6u19でG5が追加されたようだ。


シマンテックによるG5のテストサイトは Symantec SSL test (中間CAがクロスルート無しの「Symantec Class 3 EV SSL CA - G3 」で、そのIssuerがG5。)

2016年1月9日土曜日

EC2の MySQLを S3にバックアップする方法(世代管理付き)


S3への送信はaws-cliが良さそう。
参考:aws-cli - AWS CLIでS3を操作する - Qiita


aws-cliはAmazon Linuxなら最初から入っているが、手元のインスタンスはconfigure等をするにはバージョンアップが必要だった。
yumでもバージョンアップできるが、今回は諸事情により依存関係のある諸々をそっとしておきたかったので、下記を参考にyumを使わずにaws-cliをバージョンアップ。

参考:AWSCLIで運用検討中の人必見! AWSCLIを使用したS3へのファイルコピー | クラウド工房 Powered by Amazon Web Services

sudo easy_install pip
sudo pip install awscli -U


IAMでS3のみに権限を絞り込んだユーザーを作り、その認証情報をconfigure。(もう少し権限を絞っても良いかも。)

aws configure

AWS Access Key ID [None]: (アクセスキーを入力)
AWS Secret Access Key [None]: (シークレットアクセスキーを入力)
Default region name [None]:
Default output format [None]:


世代管理はS3の機能であるバージョニングとライフサイクルを使う。
S3でバケットを作成し、バージョニングを有効化。
ライフサイクルでルールを追加。(例「以前のバージョン」を30日後に削除)


後は適当にダンプとS3へのコピーのスクリプトを作ってcronに登録する。
分かりやすいようにディレクトリを作成し、そこにスクリプトを作った。

バックアップ用スクリプト作成。
vi backup.sh

#!/bin/sh
echo "START " `date +'%Y/%m/%d %H:%M:%S'`
MYSQL_PWD='MySQLのパスワード' mysqldump -u MySQLのユーザー 対象DB > data.dump
aws s3 cp data.dump s3://バケット名/
echo "E N D " `date +'%Y/%m/%d %H:%M:%S'
(パスワード直書きにしたが、きちんとやるならMySQLのパスワードは隠したい。)

スクリプトのファイルに実行権限を付ける。
chmod 700 backup.sh

cronに登録。
crontab -e

0 1 * * * cd /スクリプトのディレクトリ; ./backup.sh >> history.log


aws-cliを使うと、AWSのサービス間の通信はSSL(TLS?)で暗号化されるようだ。
参考
aws — AWS CLI 1.9.17 Command Reference
By default, the AWS CLI uses SSL when communicating with AWS services.

Amazon Web Service aws cliはデフォルトで暗号化通信されるのか? - なぜか数学者にはワイン好きが多い



S3を使わずにサーバ上で世代管理するだけなら、下記が一番分かりやすかった。
mysqldumpをcronで1日1回取得し、バックアップ用ファイルを保存する - サイト制作の豆知識

2015年3月8日日曜日

Linuxのセキュリティ対策


  • 基本
  • ファイアウォール
    • firewalld(RHEL7/CnetOS7以降)
    • iptalbes
    • Amazon EC2の場合は(EC2の)Security Groupsによる簡易ファイアウォールでも
  • WAF
    • ModSecurity
  • ウィルス対策
    • Clam AntiVirus
  • Rootkit検査
    • rkhunter
    • chkrootkit
  • 改鼠検知
    • AIDE
    • Tripwire
    • OSSEC (2015/4/4追記)
  • ログ報告
    • Logwatch

2015年3月6日金曜日

愛称?の付けられた脆弱性

(2015/6/29 VENOMとLogjamを追加)

愛称というか、通称というか、ニックネームというか。


2011年 9月 BEAST (CBC)

2012年 9月 CRIME (TLS)


2013年 2月 Lucky Thirteen (TLS)
2013年 8月 BREACH (SSL/TLS)


2014年 4月 Heartbleed (OpenSSL)
2014年 6月 CCS Injection (OpenSSL)

2014年 9月 Shellshock (bash)
2014年10月 POODLE (CBC)
2014年11月 WinShock (Windows)


2015年 1月 GHOST (glibc)

2015年 3月 FREAK (OpenSSL他)

2015年 5月 VENOM(QEMU)
2015年 5月 Logjam(SSL/TLS)


2014年はWindows XPサポート期限終了(4月)もあって当たり年と言われたが、今年はそれを上回る勢い...
ところでSSL/TLSはPOODLE対応を境にTLS/SSLと呼び替えられ始めてるみたい。いまだにサーバ証明書はSSL証明書と書かれることが多いけど...


参考

Transport Layer Security - Wikipedia
華麗なる因数分解:FREAK攻撃の仕組み - ぼちぼち日記

2015年2月25日水曜日

Content Security Policy

ApacheでContent Security Policyを設定したメモ。


httpd.confで設定する例。

Header set Content-Security-Policy "default-src 'self'; script-src 'self', 'unsafe-inline', www.example.com"


とりあえずレポートだけ見たい場合の例。
Header set Content-Security-Policy-Report-Only \
"default-src 'none';\
 script-src 'self';\
 object-src 'none';\
 img-src 'self';\
 media-src 'none';\
 frame-src 'none';\
 font-src 'none';\
 connect-src 'none';\
 style-src 'self';\
 report-uri /csp-report.php?v=1"

レポートでどのポリシーに違反したのか見やすくするため、xxxx-srcを全部書いた。
何がエラーになるか分かるように基本厳し目に、使わなそうなのはとりあえずnoneにしている。
report-uriのパラメータ(v=1)は後述。

右辺の書き方については下記参照。
CSP policy directives - Security | MDN

はまりそうなとこだけ書くと、

  • 'none'・'self'・'unsafe-inline'・'unsafe-eval'はシングルクォーテーションも含めて書く必要がある。
  • データスキーム(data:)はコロンも含めて書く。
    (mod_pagespeedを使っていると、気づかない間にデータスキームが使われていたりする。)
    ちなみに、スキームはデータに限らず、"https:"など特定のスキーム限定を指定できるみたい。
  • URLはスキームを省略可(例:www.example.com)。省略した場合、元のページと同じスキームと同じもののみ許可する。
    ポートも同様。
  • URLで別のスキームを許可したい場合、別途記載が必要。
    例:元のページがhttpで、読み込むCSSがhttpsの場合、httpsのURLも書く必要がある。
    ワイルドカードが使えるという説明もあったが、下記のどちらも駄目だった(ブラウザによる?)
  • *://www.example.com
  • *//www.example.com
  • URLのサブドメインはワイルドカード(*)が使える。
    サブドメインをワイルドカードにすると、サブサブ(...略)ドメインまでワイルドに適用される。
    ただしサブドメイン無しには適用されないらしい。


レポートをログに書き出すPHPの例。
<?php
if (!$_GET || $_GET['v'] < 1) {
        exit;
}
$report = json_decode(file_get_contents('php://input'), true);
$log = date('[Y-m-d H:i:s] ') . $_SERVER['HTTP_USER_AGENT'] . ' ';
$log .= var_export($report['csp-report'], true) . "\n";
error_log($log, 3, '/var/log/csp-report.log');

Content-Security-Policy-Report-Onlyの例でreport-uriにパラメータを付けたのは、このPHPの2行目で古いポリシーを無視するため。
ブラウザによってはキャッシュしてしまうようで、古いポリシーに基づき送信してくることがあり、ノイズになるので。
ポリシーを変えたら、パラメータの数字とPHPの2行目の数字を両方インクリメントする。

ログファイルはApacheが書き込めるように権限設定しておく。

(2015/3/2 追記)
logrotateも追加しておく。(phpのlogrotate設定をコピーして作成。)
/var/log/csp-report.log { missingok notifempty}

(追記終わり)

また、ModSecurityを使っている場合はレポートがModSecurityではじかれないように注意。

ログを見ていると、違反URLとして報告される"about"はabout:blankだと思うけど、"asset"って何だろう?



ちなみに、Gmailのポリシーはこんな感じだった。
script-src https://*.talkgadget.google.com 'self' 'unsafe-inline' 'unsafe-eval' https://talkgadget.google.com https://www.googleapis.com https://www-gm-opensocial.googleusercontent.com https://docs.google.com https://www.google.com https://s.ytimg.com https://www.youtube.com https://ssl.google-analytics.com https://apis.google.com https://clients1.google.com https://ssl.gstatic.com https://www.gstatic.com blob:;frame-src https://*.talkgadget.google.com https://www.gstatic.com 'self' https://accounts.google.com https://apis.google.com https://clients6.google.com https://content.googleapis.com https://mail-attachment.googleusercontent.com https://www.google.com https://docs.google.com https://drive.google.com https://*.googleusercontent.com https://feedback.googleusercontent.com https://talkgadget.google.com https://isolated.mail.google.com https://www-gm-opensocial.googleusercontent.com https://plus.google.com https://wallet.google.com https://www.youtube.com https://clients5.google.com https://ci3.googleusercontent.com;object-src https://mail-attachment.googleusercontent.com;report-uri /mail/cspreport

見やすく整形。
script-src
https://*.talkgadget.google.com
'self'
'unsafe-inline'
'unsafe-eval'
https://talkgadget.google.com
https://www.googleapis.com
https://www-gm-opensocial.googleusercontent.com
https://docs.google.com
https://www.google.com
https://s.ytimg.com
https://www.youtube.com
https://ssl.google-analytics.com
https://apis.google.com
https://clients1.google.com
https://ssl.gstatic.com
https://www.gstatic.com
blob:
frame-src
https://*.talkgadget.google.com
https://www.gstatic.com
'self'
https://accounts.google.com
https://apis.google.com
https://clients6.google.com
https://content.googleapis.com
https://mail-attachment.googleusercontent.com
https://www.google.com
https://docs.google.com
https://drive.google.com
https://*.googleusercontent.com
https://feedback.googleusercontent.com
https://talkgadget.google.com
https://isolated.mail.google.com
https://www-gm-opensocial.googleusercontent.com
https://plus.google.com
https://wallet.google.com
https://www.youtube.com
https://clients5.google.com
https://ci3.googleusercontent.com
object-src
https://mail-attachment.googleusercontent.com
report-uri
/mail/cspreport

scriptは'unsafe-inline'も'unsafe-eval'も許可してしまっているが、imgも含めて*を使っていないのは立派。
style等は(defaultも)指定していないが、不要という判断か、指定すると差し障りがあるのか、どちらだろう?

また、1バイトを削るのにもこだわるGoogleがわざわざこれだけの文字列を送信するのは、セキュリティの方が重要だからということだろう。
サブドメインをワイルドカードでまとめれば随分減りそうだが、Googleともなると使っているサブドメインも膨大なので、セキュリティが担保しづらくなるのだろう。
policy-uriを指定してポリシーをXMLでやりとりしてキャッシュを効かせれば総通信料は減りそうだが、柔軟性とのトレードオフか。
report-uriも送信料を増やすが、これ無しは運用的にきっと難しいだろう。

2015年1月25日日曜日

自己証明書の作り方 2015年版


Apache用(他でも使えると思うけど)の、自己署名のサーバ証明書(SSL証明書、改め、TLS証明書?)の作り方のメモ。

条件

  • 秘密鍵はパスフレーズ無し=暗号化しない
  • 2048ビット
  • SHA-2

コマンド
# 秘密鍵作成(2048ビットを指定、暗号化指定は無し)
openssl genrsa -out server.key 2048
# CSR作成
openssl req -new -key server.key -out server.csr
# 証明書作成(SHA-256を指定、期間は適当に)
openssl x509 -req -in server.csr -signkey server.key -days 3650 -out server.crt -sha256

手元のブラウザで、"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"になった(最強?)

参考:CentOS OpenSSLを使用したSSL用の秘密鍵と証明書の作成 | kakiro-web カキローウェブ

2014年2月1日土曜日

mod_sslの SSLCipherSuiteについての調査メモ

mod_ssl本家マニュアル(日本語版は無い)

mod_ssl - Apache HTTP Server
mod_ssl - Apache HTTP Server



CBCモードと圧縮機能の脆弱性についての経緯について

どさにっき



SSLCipherSuiteでRC4を優先するのはよろしくなさそう

ApacheのSSLCipherSuiteにRC4を設定すべきではない - Qiita [キータ]



GlobalSignのSSL脆弱性チェックツール

設定状況や信頼性がわかる!SSLチェックツール|GMOグローバルサイン



mod_sslで現在有効な暗号化方式を調べる方法

今日も明日もググったー: SSLCipherSuite

2013年12月14日土曜日

IEのバージョン別の X-Content-Type-Options: nosniffの対応状況

IE8以下は内容がHTMLっぽいとHTTPレスポンスヘッダ‐のContent-typeに関わらず、HTMLとしてレンダリングしてしまう。
IE8はnosniffをつければ、Content-typeに従う。

参考: X-Content-Type-Options: nosniffの効果を確認してみる | UCWD-Studio.【ホームページ制作 / 京都】


PHPの実験用コード

<?php header('Content-type: text/plain') ?>
<script>alert(1)</script>


IE9以降およびChrome・Firefoxなどは、nosniffがある場合はJavaScriptやCSSの外部ファイルのContent-typeが妥当でないと、その外部ファイルは読み込まない。

参考:
X-Content-Type-Options: nosniff の効果 : swdyh
MIME タイプのセキュリティ リスクの軽減 (Windows)

2013年12月10日火曜日

今どきのHTTPヘッダーによるセキュリティ向上の調査メモ

今夜つける HTTPレスポンスヘッダー (セキュリティ編) - うさぎ文学日記の中で、よく知らなかったヘッダーについて調べたメモ。

いくつかのヘッダーについてのブラウザ別のサポート状況はこちら。
(ちょっと古いが、少なくともこれ以降のバージョンではサポートしているということは分かる。)

IPA ISEC セキュア・プログラミング講座:Webアプリケーション編 第8章 マッシュアップ:クライアントサイドマッシュアップ: #4 対策に利用できる技術


X-XSS-Protection

IE8以降のXSSフィルターはデフォルトで有効になっている(ブロッキングモードではない)。

Security through HTTP response headers

[IEInternals] XSS フィルターを制御する | Hebikuzure's Tech Memo

Internet Explorer 8 には、XSS フィルターとして知られている、反射型クロスサイト スクリプティング攻撃を防止するのに有効な画期的新機能があります。このフィルターは既定ではインターネット ゾーン、信頼済みサイト ゾーン、制限付きサイト ゾーンで動作します。

オフにしている人や、XSS on XSS Filterに備えて、ブロッキングモードで有効にさせるのが無難?
X-XSS-Protection: 1; mode=block


Content-Security-Policy

(参考)Content Security PolicyでXSSを断ち切る | monoの開発ブログ

インラインリソースは'unsafe-inline'で許可できる。
dataスキームURIには"data:"で許可できる。

An Introduction to Content Security Policy - HTML5 Rocks

IEがほぼサポートしていないようなので、効果は限定的か。

CSP policy directives - Security | MDN
CSP is quite usable in Chrome 16+, Safari 6+, and Firefox 4+, and has (very) limited support in IE 10.

セキュリティとしては非常に強力だが、ホワイトリストのメンテが面倒なので外部リソースを気軽に使うようなサイトでは使うのは難しい?

あるいは、こんな風に思いっきり緩くしておくか?(これだと意味がないか...)
Content-Security-Policy:
default-src 'self';
script-src 'unsafe-inline' *;
img-src data: *;
frame-src *;
font-src *;
style-src 'unsafe-inline' *;
report-uri /csp-report.php

見やすくするために改行している。未検証なので取扱注意。
faviconはimg-srcに含まれる。
違反が見つかったら、report-uriにJSONでPOSTされる。
eval()が必要なら'unsafe-inline'も追加する。

Content-Security-Policy-Report-Onlyでチェックのみに使うのが良いかもしれない。


Strict-Transport-Security

IEが10でもサポートしていないことを考えると、これが効かない場合のリダイレクト等の処理も必要。

HTTP Strict Transport Security - OWASP

2013年8月6日火曜日

ホスト型侵入検知ツール(IDS)の aideを Amazon Linuxにインストール

徳丸さんが改ざん検知を導入したそうなので、うちにも入れてみた。徳丸さんはionotifywait(とTripwire)を採用したそうだけど、調べてみたらaideの方が使いやすそう。aideはTripwireなどと同じホスト型の侵入検知ツールというか改竄検知ツール、というか差分ファイル調査ツール。
なのでaideをAmazon Linuxにインストールしてcronで動かすまでの備忘録。rootで作業した。

インストール
yum install aide

設定ファイル編集
vi /etc/aide.conf
  • デフォルト設定の注意点
    • /var/www が含まれていないのでWebファイルの改竄を検知できない
    • /etc/httpd も含まれていない
    • /var/log が含まれているのでログが書かれると反応してしまう
  • 最初は厳し目(検知多め)にしておいて、使いながら緩くしていくのが良さそう

cron設定例
MAILTO=foo@example.com
00 2 * * * cd /var/lib/aide; cp aide.db.new.gz aide.db.gz; /usr/sbin/aide -u > /dev/null || cat /var/log/aide/aide.log
  • 毎晩2時に、前回作ったDBを適用し、チェック&DB作成を実行し、異常があった場合のみログの内容をメールで送付する場合の例
  • エラーがある場合は標準出力に出力されるエラー情報と同じ内容がログにも出力されるので、標準出力は /dev/null に捨てている


きちんとやるなら、aideのDBをどうやって守るか(別サーバに置くなど)とかも考えないといけないみたい。

2012年1月18日水曜日

Linuxで外部からアクセス可能なサービス(デーモン)を調べる方法

メモ。

Runレベルごとの起動状況を調べ、ファイアウォールも調べ、使われているポートを調べる。ポートを使っているのがxinetdならそれを使ってる本体も調べる。



2011年6月13日月曜日

JavaScriptの HTMLエスケープ関数を 140字以内で書いてみる

JavaScriptで動的にWebページの内容を書き換える場合に、文字列のHTMLエスケープをしたい時がある。具体的には、「& " ' < >」の5つを変換したい。
PHPならhtmlSpecialChars()、Railsならh()でよいが、JavaScriptにはHTMLエスケープ用の関数が用意されていないので自分で書く必要がある。

せっかくなので、Twitterでつぶやける文字数以内で書くことを目指してみる。

で、こうなった。

function h(s){return s.replace(/[&"'<>]/g,function(m){return"&"+["amp","quot","#039","lt","gt"]["&\"'<>".indexOf(m)]+";"})}
123文字。
意外と余裕だ。



クォーテーションのエスケープをしないでいいなら(HTML要素の属性値のHTMLエスケープに使わないなら)、こんな方法もある。
function h(s,p){p=document.createElement("p");p.innerText=p.textContent=s;return p.innerHTML}
93文字。
(第2引数のpは変数宣言を避けて文字数を減らすためのダミーの引数なので、実際に使うときには第1引数のみ渡せばよい。)
innerTextはFirefoxでは使えないしtextContentはIEでは使えないので、両方に対応させるために両方書いている。


でも、innerTextには細かい問題ある(参考:DOM の textContent と innerText について - フリーフォーム フリークアウト)ようなので、環境依存を避けて丁寧にやりたいなら、少し長くなるけどdocument.createTextNode()を使った方が無難かも?
function h(s,d,p){d=document;p=d.createElement("p");p.appendChild(d.createTextNode(s));return p.innerHTML}
106文字。


でもでも、それなら最初の正規表現を使ったやり方のほうが短い。
function h(s){return s.replace(/[&<>]/g,function(m){return{"&":"&amp;","<":"&lt;",">":"&gt;"}[m]})}
99文字。



(2011/06/22 追記)
はてなブックマークやTwitterで教えてもらったので追記。


hatestさん
引数sがStringであることをチェックしてないから、{replace:function(){return "<script>"}}とかいうオブジェクト渡されたら終わるぞ
そうですね。用途によってはパラメータのチェックとか型変換とかすべきかも。


ひなしさん
function h(s){return s.replace(/[&<>"']/g,function(m){return "&#"+m.charCodeAt(0)+';'})} の88文字でよくない?
なるほど。こっちの方がスマートかつ短い。
(ところでTopsyの検索にひっかからないのは何故?)


uuuさん
最近はreturn s.replace(/["'&><]/g, function(m){return "&#"+m .charCodeAt(0).toString(16) + ";"})みたいのがマイブーム
こちらもcharCodeAt()。16進数なので"&#"のところは"&#x"の書き間違いと思われる。16進数にするメリットとかあるのかな?


ということでcharCodeAt()を使って書き直してみる。もうエスケープ対象文字の判別とか無しで、全てユニコード化してしまおう。
function h(s,i,t,r){for(i=t="";r=s.charCodeAt(i);i++)t+="&#"+r+";";return t}
76文字!

charCodeAt()を使っているのでJavaScript1.2未対応ブラウザ(IE3とか)では動かないだろう。あと文字コードによっては問題ある?
Null文字が入っていると変換の途中で終わってしまうが、NULL文字は非SGML文字らしいので良しとしよう。
インクリメントに使う「i」を空文字("")で初期化するのは気持ちが悪いがとりあえず動くみたい。JavaScriptの仕様としてはどうなんだろう。微妙なところか?(参考:JavaScript講座 : インクリメント/1加算
(追記終わり)


関連:floatingdays: JavaScriptで HTMLエスケープ

2011年4月4日月曜日

PHPの crypt()で SHA2のハッシュを生成する

PHPのcrypt()を使うと、パスワードで使うのに便利な文字列を生成できる。(説明のために3色に色付けした。)

$str = crypt('test'); => $1$X0zFikbH$z9QaylK29Eu4VQajK6PKw0

生成された文字列は$記号で区切られた3つの部分から構成されている。
  • $1$ → MD5でハッシュを生成したことを表す
  • X0zFikbH → ハッシュ生成に使ったsalt。crypt()の第2引数でsaltを指定した場合は指定したsaltが使われるが、指定しないと自動生成されたsaltが使われる
  • z9QaylK29Eu4VQajK6PKw0 → 生成されたハッシュ


この文字列を使ってパスワードが正しいか確認したい場合、下記のようにcrypt()だけで確認できる。
if (crypt($input_password, $str) === $str) {
    echo 'OK';
} else {
    echo 'NG';
}

crypt()の第2引数としてcrypt()で生成した文字列を渡すと、saltの部分だけを取り出してsaltとして使ってくれる(後ろのハッシュ値は無視される)ので、わざわざsaltだけを取り出す必要はない。(便利だが一見しただけでは分かり辛い...)


crypt()の第2引数でsaltを指定しなかった場合のハッシュアルゴリズムは、手元の環境ではMD5が使われた。
第2引数でsaltを指定する場合は、saltの前に付ける文字列によって下記のようにハッシュアルゴリズムを指定することができる。
  • 何も付けない → DES(拡張DESではなく標準DES?)
  • $1$ → MD5
  • $2a$ → Blowfish
  • $5$ → SHA-256 (PHP 5.3.2以降)
  • $6$ → SHA-512 (PHP 5.3.2以降)

上記のように、PHP 5.3.2以降ではcrypt()でSHA2(SHA-256/512)が使えるようになった。
(既に脆弱性が発見されているSHA-1はスキップされたようだ。)

BlowfishやSHA-256/512を使う場合は自動生成のsaltが使えないので、文字列生成時にはsaltを渡してあげないといけない。
saltは推測可能な値でも構わない(元の文字列が同じでもハッシュが異なるようにすることに意味がある)ので、uniqid()あたりでいいんじゃないかな。
$str = crypt('test', '$6$' . uniqid());


参考:PHP: crypt - Manual


関連記事

2010年12月7日火曜日

PHPの htmlSpecialChars()の 第3引数(文字コード)の調査メモ

そもそも

基本的に内部的な文字コードは(ソースファイルもDBもその他の設定も)全てUTF-8にしておき、POSTやGETなどで入力値を受け取る時には入力値をUTF-8に変換してから使うのが良いと思うし、そうすれば漏れがない限りはhtmlSpecialChars()等で出力時に不正文字コードを気にする必要はない。



しかし

現実的にはPOST/GETで受け取る以外にも下記の様に様々な方法でデータが入ってくることもある。

それぞれデータを取り出す時に適切に文字コード変換すべきだが、やっぱりいつか誰かが漏らしそう。

なので、やはり出力時にも不正な文字コードは弾いた方がよい。



で、調べてみた

2009年の後半にいくつかのブログでこのことが論じられていた。(そういえば読んだ記憶が...。詳細は下の方の参考リンクを参照。)
中でも「htmlspecialchars - 第45回PHP勉強会@関東 :: handsOut.jp」が簡潔でわかりやすかった。
PHP5.2.5以降を使い、htmlspecialchars()の第3引数にUTF-8を指定するのが一番堅実のようだ。

蛇足だが、もしUTF-8以外でWebページを入出力したい場合は、mb_http_output()とob_start()を使って出力完了後に文字コードをSJIS-WINなどに変換させるようにしておいて、そこにUTF-8で出力するのが良いと思う。(処理量が多いとオーバーヘッドが気になる?)



以外な落とし穴が

しかし、htmlspecialchars()の文字コード検出には思わぬ落とし穴があった。
htmlspecialchars()は不正な文字コードを見つけても、PHPの設定でdisplay_errorsがfalseの場合しかWarningを出さない
  • display_errors = true → Warningを画面にもログにも出さない
  • display_errors = false → Warningをログにも出す(画面には出さない)
これでは、開発環境では文字コードが不正になりうる箇所に気づかないまま、本番環境でWarningを出しまくるかもしれない。

これは意図的なものなので、修正されない可能性が高そう。(参考:display_errorsが謎の副作用を持っている箇所について - muddy brown thang
また、@htmlspecialchars()に@(アットマーク)を付けてもログへのエラー出力を抑制できなかった。

Warningを出さないようにする対策としては、htmlspecialchars()の手前で強制的に文字コードを変換するという手がある。
$str = mb_convert_encoding($str, 'UTF-8', 'UTF-8');
echo htmlSpecialCahrs($str, ENT_QUOTES, 'UTF-8');
現在のサーバ性能とPHPの速さなら、こんな富豪的な重複処理もあまり問題にならない環境が多い。
mb_convert_encoding()とhtmlSpecialChars()の検出基準(?)が違うというようなことをどこかで読んだ気がするんで、その場合はこれでもWarningが出るのだろう。
でも、どうせmb_convert_encoding()するのなら、そもそもhtmlSpecialChars()での文字コード指定は要らないか。

ただし、本道としては、せっかく出してくれるWarningを手がかりにして、該当箇所で適切な文字コード変換をするようコードを修正するのが筋だろう。
PHPのWarningはset_error_handlerで捕まえられる。



もう1つ

htmlspecialchars/htmlentitiesはBMP外の文字を正しく扱えない - [php] - 徳丸浩の日記」という落とし穴もあるようだが、これはPHPの5.3.2でFixした。(5.2系は?)
また、(線文字Bは置いておいて)一部の漢字を「使えません。仕様です。」で済ませられるなら、こちらの問題は黙殺できそうだ。



参考

2010年11月28日日曜日

HMAC方式で認証用のハッシュを生成するメモ


HMAC
(Keyed-Hashing for Message Authentication Code)とは?

HMACはハッシュ(Message Digest)生成アルゴリズムで、MD5やSHA1、SHA2等と組み合わせて使う。(それぞれ「HMAC-MD5」「HMAC-SHA1」などと呼ばれる。)



なぜ認証用のハッシュがHMACでなければいけないのか?

HMACでないハッシュ関数を認証用のハッシュ(トークン)生成に使うと、秘密鍵を知らなくても任意のハッシュを生成できるケースがあるらしい。(参考:Kazuho@Cybozu Labs: Re: はてな認証 API

よく理解していないけど、ハッシュアルゴリズムがデータブロック単位で処理することに起因している?
暗号化においてCBCでIVが固定の場合と同じような問題?(参考:floatingdays: PHPで AES方式 (Rijndael-128)で暗号化するメモ

それに対してHMACでは、変換元の値とは別に指定する秘密鍵組み合わせることにより、上記の問題を回避しているらしい。(参考:HMAC: Keyed-Hashing for Message Authentication



HMAC方式でハッシュを生成する方法

今どきのプログラム環境は言語レベルで実装してるみたい。

PHP 5.1.2以降の場合
HMAC 方式を使用してハッシュ値を生成する - PHP 5.3 日本語マニュアル

PHP 5.1.1以前の場合、外部ライブラリとしてmhashが必要 (参考:導入 - PHP 5.3 日本語マニュアル
ハッシュ値を計算する - PHP 5.3 日本語マニュアル

Javaの場合
試験管のなかのコード :: JDK 1.4.x 環境で HMAC with the SHA256 を使用する方法



参考:

ブログ アーカイブ

tags