自動攻撃からPostgreSQLを保護する方法
序章
サーバーが最近立ち上げられたばかりであるか、トラフィックがほとんど見られないか、またはハッカーにとって見過ごされてしまう価値のあるものを何も提供していないため、考えたくなるかもしれません。 ただし、多くのエクスプロイトは自動化されており、構成の一般的なエラーを探すように特別に設計されています。 これらのプログラムは、コンテンツの性質に関係なく、ネットワークをスキャンしてサーバーを検出します。
リモート接続を許可することは、PostgreSQLデータベースの悪用につながる可能性のある一般的でより簡単に修正できる状況の1つです。 これは、特定の構成により、これらのようなプログラムがサーバーを簡単に検出できるために発生します。
このチュートリアルでは、リモート接続を許可することによってもたらされる特定のリスクを軽減する方法を示します。 これは重要な最初のステップですが、サーバーは他の方法で危険にさらされる可能性があるため、追加のセキュリティに関する考慮事項で概説されているように、データを保護するための追加の対策を講じることもお勧めします。
バックグラウンド
軽減している特定のリスクを理解するために、サーバーをストアとして想像してください。 サーバーがいずれかのポートでリッスンしている場合は、ネオンの「オープン」サインをオンにするのと少し似ています。 これにより、サーバー自体がネットワーク上で表示され、自動スクリプトでサーバーを見つけることができます。
各港は、ドアや窓のように、店に入る方法と考えることができます。 これらの入り口は、リッスンしているソフトウェアの状態に応じて、開いている、閉じている、ロックされている、または壊れている可能性がありますが、パブリックインターフェイスでリッスンしているということは、内部に入ろうとしているスクリプトが試行を開始できることを意味します。 たとえば、スクリプトは、変更されていない場合にデフォルトのパスワードでログインを試みるように構成されている可能性があります。 パッチが適用されていない場合は、リスニングデーモンの既知のエクスプロイトを試みる可能性があります。 スクリプトが何を試みようとも、弱点を見つけてそれを悪用することができれば、侵入者は内部にいて、サーバーを危険にさらすという深刻なビジネスに取り掛かることができます。
postgresql
のようなデーモンをローカルでリッスンするように制限すると、外部への特定のドアが存在しないようになります。 少なくともPostgresに関しては、次のステップを試す必要はありません。 ファイアウォールとVPNも同様の方法で保護します。 このチュートリアルでは、公的にアクセス可能な出入り口としてPostgreSQLを削除することに焦点を当てます。 デーモン自体または送信または保存されるデータを保護するには、追加のセキュリティに関する考慮事項を参照してください。
前提条件
このチュートリアルでは、 2つのUbuntuインストールを使用します。1つはデータベースホスト用で、もう1つはホストにリモート接続するクライアントとして使用します。 それぞれにsudo
ユーザーがあり、ファイアウォールが有効になっている必要があります。 ガイド「Ubuntu16.04を使用したサーバーの初期設定」がこれに役立ちます。
1つのUbuntu16.04PostgreSQLデータベースホスト:
PostgreSQLをまだインストールしていない場合は、次のコマンドを使用してインストールできます。
sudo apt-get update sudo apt-get install postgresql postgresql-contrib
1台のUbuntu16.04クライアントマシン:リモート接続を許可することを実証およびテストするために、PostgreSQLクライアントpsql
を使用します。 これをインストールするには、次のコマンドを使用します。
sudo apt-get update sudo apt-get install postgresql-client
これらの前提条件が整ったら、従う準備ができています。
デフォルト構成を理解する
PostgreSQLがUbuntuパッケージからインストールされる場合、デフォルトではローカルホストでのリッスンに制限されています。 このデフォルトは、postgresql.conf
ファイルのlisten_addresses
をオーバーライドすることで変更できますが、デフォルトでは、サーバーがパブリックインターフェイスで自動的にリッスンすることはできません。
さらに、pg_hba.conf
ファイルは、Unix / Linuxドメインソケットからの接続とサーバーのローカルループバックアドレスのみを許可するため、外部ホストからの接続を受け入れません。
交換
# Put your actual configuration here # ---------------------------------- # # If you want to allow non-local connections, you need to add more # "host" records. In that case you will also need to make PostgreSQL # listen on a non-local interface via the listen_addresses # configuration parameter, or via the -i or -h command line switches. # DO NOT DISABLE! # If you change this first entry you will need to make sure that the # database superuser can access the database using some other method. # Noninteractive access to all databases is required during automatic # maintenance (custom daily cronjobs, replication, and similar tasks). # # Database administrative login by Unix domain socket local all postgres peer # TYPE DATABASE USER ADDRESS METHOD # "local" is for Unix domain socket connections only local all all peer # IPv4 local connections: host all all 127.0.0.1/32 md5 # IPv6 local connections: host all all ::1/128 md5
これらのデフォルトは、パブリックインターフェイスでリッスンしないという目的を満たしています。 それらをそのままにしてファイアウォールを維持すれば、完了です。 追加のセキュリティに関する考慮事項に直接進んで、転送中のデータを保護する方法を学ぶことができます。
リモートホストから接続する必要がある場合は、次のセクションで、デフォルトをオーバーライドする方法と、サーバーを保護するために実行できる即時の手順について説明します。
リモート接続の構成
実稼働環境で機密データの処理を開始する前に、理想的には、PostgreSQLトラフィックをSSLで暗号化して転送するか、外部ファイアウォールの背後で保護するか、仮想プライベートネットワーク(VPN)で保護します。 そのために、データベースサーバーでファイアウォールを有効にし、ファイアウォールを必要とするホストへのアクセスを制限するという、それほど複雑ではない手順を実行できます。
ステップ1—ユーザーとデータベースを追加する
まず、作業をテストできるユーザーとデータベースを追加します。 そのためには、PostgreSQLクライアントpsql
を使用して、管理ユーザーpostgres
として接続します。 -i
オプションをsudo
に渡すことで、postgresユーザーのログインシェルを実行します。これにより、.profile
またはその他のログイン固有のリソースからオプションが確実に読み込まれます。 -u
はpostgresユーザーを指定します:
sudo -i -u postgres psql
次に、パスワードを使用してユーザーを作成します。 以下で強調表示されている例の代わりに、必ず安全なパスワードを使用してください。
CREATE USER sammy WITH PASSWORD 'password';
ユーザーが正常に作成されると、次の出力が表示されます。
OutputCREATE ROLE
注: PostgreSQL 8.1以降、ROLESとUSERSは同義語です。 慣例により、パスワードを持つロールは引き続きUSERと呼ばれ、パスワードを持たないロールはROLEと呼ばれるため、USERが表示されると予想される出力にROLEが表示される場合があります。
次に、データベースを作成し、新しいユーザーにフルアクセスを許可します。 ベストプラクティスでは、ユーザーに必要なアクセスと、必要なリソースのみを許可することを推奨しています。そのため、ユースケースによっては、ユーザーのアクセスをさらに制限することが適切な場合があります。 パーミッションの詳細については、ガイドVPS上のPostgreSQLでロールを使用して付与パーミッションを管理する方法を参照してください。
CREATE DATABASE sammydb OWNER sammy;
データベースが正常に作成されると、確認を受け取る必要があります。
OutputCREATE DATABASE
これで、ユーザーとデータベースが作成されたので、モニターを終了します。
\q
Enterキーを押すと、コマンドプロンプトが表示され、続行する準備が整います。
ステップ2—UFWの設定
Ubuntu 16.04 の前提条件を使用したサーバーの初期設定では、UFWを有効にし、SSH接続のみを許可しました。 構成を開始する前に、UFWのステータスを確認しましょう。
sudo ufw status
注:出力がファイアウォールがinactive
であることを示している場合、次の方法でアクティブ化できます。
sudo ufw enable
有効にした後、statusコマンドを再実行すると、sudo ufw status
に現在のルールが表示されます。 必要に応じて、SSHを許可してください。
sudo ufw allow OpenSSH
<$>
前提条件に変更を加えない限り、出力にはOpenSSHのみが許可されていることが示されます。
OutputStatus: active To Action From -- ------ ---- OpenSSH ALLOW Anywhere OpenSSH (v6) ALLOW Anywhere (v6)
ファイアウォールのステータスを確認したので、PostgreSQLポートへのアクセスを許可し、許可する1つまたは複数のホストに制限します。
以下のコマンドは、PostgreSQLのデフォルトポートである5432のルールを追加します。 そのポートを変更した場合は、必ず以下のコマンドで更新してください。 アクセスが必要なサーバーのIPアドレスを使用していることを確認してください。 必要に応じて、次のコマンドを再実行して、アクセスが必要な各クライアントIPアドレスを追加します。
sudo ufw allow from client_ip_address to any port 5432
ルールを再確認するために、ufw status
を再度実行できます。
sudo ufw status
OutputTo Action From -- ------ ---- OpenSSH ALLOW Anywhere 5432 ALLOW client_ip_address OpenSSH (v6) ALLOW Anywhere (v6)
<$>[注] ノート: UFWを初めて使用する場合は、ガイドで詳細を確認できます UFW Essentials:一般的なファイアウォールルールとコマンド 。
このファイアウォールルールを設定したら、パブリックIPアドレスをリッスンするようにPostgreSQLを構成します。 これには、pg_hba.conf
の接続ホストのエントリと、postgresql.conf
のlisten_addressesの構成の2つの設定の組み合わせが必要です。
ステップ3—許可されたホストを構成する
pg_hba.conf
にホストエントリを追加することから始めます。 別のバージョンのPostgreSQLがインストールされている場合は、必ず以下のパスに置き換えてください。
sudo nano /etc/postgresql/9.5/main/pg_hba.conf
非ローカル接続を許可する方法を説明するコメントブロックの下にhost
行を配置します。 また、ファイアウォールが正しく構成されていることをすばやくテストできるように、データベースサーバーのパブリックアドレスを含む行を含めます。 以下の例では、必ずyourマシンのホスト名またはIPアドレスに置き換えてください。
pg_hba.confからの抜粋
# If you want to allow non-local connections, you need to add more # "host" records. In that case you will also need to make PostgreSQL # listen on a non-local interface via the listen_addresses # configuration parameter, or via the -i or -h command line switches. host sammydb sammy client_ip_address/32 md5
変更を保存する前に、いくつかのオプションを変更する場合に備えて、この行の各値に注目しましょう。
- host最初のパラメーター
host
は、TCP/IP接続が使用されることを確立します。 - データベース
sammydb
The second column indicates which database/s the host can connect to. More than one database can be added by separating the names with commas. - ユーザー
sammy
indicates the user that is allowed to make the connection. As with the database column, multiple users can be specified, separated by commas. - address addressは、クライアントマシンのアドレスを指定し、ホスト名、IPアドレス範囲、またはその他の特別なキーワードを含めることができます。 上記の例では、クライアントの単一のIPアドレスのみを許可しています。
- auth-method 最後に、auth-method
md5
は、ダブルMD5ハッシュパスワードが認証用に提供されることを示します。 接続するユーザー用に作成されたパスワードを入力するだけで済みます。
これらおよび追加の設定の詳細については、pg_hba.confファイルPostgreSQLのドキュメントを参照してください。
完了したら、ファイルを保存して終了します。
ステップ4—リスニングアドレスを設定する
次に、postgresql.conf
ファイルにリッスンアドレスを設定します。
sudo nano /etc/postgresql/9.5/main/postgresql.conf
listen_addresses
行を見つけ、その下でリッスンアドレスを定義します。必ず、データベースホストのホスト名またはIPアドレスに置き換えてください。 接続しているクライアントではなく、データベースサーバーのパブリックIPを使用していることを再確認することをお勧めします。
postgresql.conf
#listen_addresses = 'localhost' # what IP address(es) to listen on; listen_addresses = 'localhost,server_ip_address'
完了したら、ファイルを保存して終了します。
ステップ5—PostgreSQLを再起動する
構成の変更はPostgreSQLデーモンを再起動するまで有効にならないため、テストする前に変更を行います。
sudo systemctl restart postgresql
systemctl
はフィードバックを提供しないため、ステータスをチェックして、デーモンが正常に再起動したことを確認します。
sudo systemctl status postgresql
出力に「Active:active」が含まれ、次のように終わる場合は、PostgreSQLデーモンが実行されています。
Output... Jan 10 23:02:20 PostgreSQL systemd[1]: Started PostgreSQL RDBMS.
デーモンを再起動したので、テストする準備が整いました。
ステップ6—テスト
最後に、クライアントマシンから接続できることをテストしましょう。 これを行うには、psql
と-U
を使用してユーザーを指定し、-h
を使用してクライアントのIPアドレスを指定し、-d
を使用してデータベースを指定します。 、sammy
が単一のデータベースにのみ接続できるようにセキュリティを強化したため、
psql -U sammy -h postgres_host_ip -d sammydb
すべてが正しく構成されている場合は、次のプロンプトが表示されます。
OutputPassword for user sammy:
PostgreSQLモニターにユーザーsammy
を追加したときに設定したパスワードを入力します。
次のプロンプトが表示されたら、正常に接続されています。
[secondary_label] sammydb=>
これにより、ファイアウォールを通過してデータベースに接続できることが確認されます。 今すぐ終了します:
\q
構成を確認したので、クリーンアップして終了します。
ステップ7—テストデータベースとユーザーの削除
接続のテストが終了したら、次のコマンドを使用してデータベースとユーザーを削除することもできます。
sudo -i -u postgres psql
データベースを削除するには:
DROP DATABASE sammydb;
アクションは、次の出力によって確認されます。
OutputDROP DATABASE
ユーザーを削除するには:
DROP USER sammy;
成功は次のように確認されます。
OutputDROP ROLE
sammydb
データベースのホストエントリをpg_hba.conf
ファイルから削除することでクリーンアップを終了します。これは、不要になったためです。
sudo nano /etc/postgresql/9.5/main/pg_hba.conf
`pg_hba.conf`から削除する行
host sammydb sammy client_ip_address/32 md5
変更を有効にするには、保存して終了し、データベースサーバーを再起動します。
sudo systemctl restart postgresl
正常に再起動したことを確認するために、ステータスを確認します。
sudo systemctl status postgres
「アクティブ:アクティブ」と表示されている場合は、再起動が成功したことがわかります。
この時点で、リモート接続が必要なクライアントでアプリケーションまたはサービスの構成を進めることができます。
追加のセキュリティに関する考慮事項
このチュートリアルは、PostgreSQLへのセキュリティで保護されていないリモート接続を許可することによってもたらされるリスクを軽減することを目的としています。これは、PostgreSQLを誤ってエクスプロイトにさらす一般的な状況です。 リスニングポートへのアクセスを特定のホストに制限しても、転送中のデータを暗号化する方法など、その他の重要なセキュリティ上の考慮事項には対応していません。
実際のデータを操作する前に、次のリソースを確認し、ユースケースに適した手順を実行することをお勧めします。
- PostgreSQL内のセキュリティ:GRANTステートメントは、特定のデータベースへのアクセスを許可するユーザーを決定し、ロールはそれらのユーザーの特権を確立します。 これらを組み合わせることで、1回のインストールで複数のデータベースを分離できます。
- PostgreSQLを使用したSSLの設定:SSLを設定すると、転送中のデータが暗号化されます。 これにより、送信時にデータが保護されます。
- SSHトンネルを使用したPostgreSQLTCP/ IP接続の保護:SSHトンネルは、SSL対応ではないクライアントと接続する場合に役立ちます。 他のほとんどの状況では、PostgresでSSLを設定することをお勧めします。
結論
このチュートリアルでは、アクセスが必要なホストからの接続のみを許可するようにサーバーのファイアウォールを構成し、それらのホストからの接続のみを受け入れるようにPostgreSQLを構成することにより、PostgreSQLインストールのアドバタイズを防ぐための重要な手順を実行しました。 これにより、特定の種類の攻撃のリスクが軽減されます。 これはデータを保護するための最初のステップにすぎないため、上記で概説した追加のセキュリティ対策を確認して実装することをお勧めします。