自動攻撃から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パッケージからインストールされる場合、デフォルトではローカルホストでのリッスンに制限されています。 このデフォルトは、オーバーライドすることで変更できます。 listen_addresses
の中に postgresql.conf
ファイルですが、デフォルトでは、サーバーがパブリックインターフェイスで自動的にリッスンすることはできません。
加えて pg_hba.conf
fileは、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を構成します。 これには、2つの設定の組み合わせ、接続しているホストのエントリが必要です。 pg_hba.conf
およびlisten_addressesの構成 postgresql.conf
.
ステップ3—許可されたホストを構成する
まず、ホストエントリをに追加します。 pg_hba.conf
. 別のバージョンのPostgreSQLがインストールされている場合は、必ず以下のパスに置き換えてください。
- sudo nano /etc/postgresql/9.5/main/pg_hba.conf
配置します host
非ローカル接続を許可する方法を説明するコメントブロックの下の行。 また、ファイアウォールが正しく構成されていることをすばやくテストできるように、データベースサーバーのパブリックアドレスを含む行を含めます。 以下の例では、必ずyourマシンのホスト名またはIPアドレスに置き換えてください。
# 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
2番目の列は、ホストが接続できるデータベースを示しています。 名前をコンマで区切ることにより、複数のデータベースを追加できます。 - ユーザー
sammy
接続を許可されているユーザーを示します。 データベース列と同様に、複数のユーザーをコンマで区切って指定できます。 - 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を使用していることを再確認することをお勧めします。
#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:
ユーザーを追加したときに設定したパスワードを入力します sammy
PostgreSQLモニターで。
次のプロンプトが表示されたら、正常に接続されています。
[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
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インストールのアドバタイズを防ぐための重要な手順を実行しました。 これにより、特定の種類の攻撃のリスクが軽減されます。 これはデータを保護するための最初のステップにすぎないため、上記で概説した追加のセキュリティ対策を確認して実装することをお勧めします。