自動化された攻撃からPostgreSQLを保護する方法

前書き

サーバーが最近立ち上げられたばかりで、トラフィックがほとんどないか、見過ごされることになるハッカーにとって価値があると思われるものを何も提供していないため、考えがちです。 ただし、多くのエクスプロイトは自動化されており、構成の一般的なエラーを探すように特別に設計されています。 これらのプログラムは、コンテンツの性質に関係なく、ネットワークをスキャンしてサーバーを検出します。

リモート接続を許可することは、PostgreSQLデータベースの悪用につながる可能性がある、一般的で修正が容易な状況の1つです。 これは、特定の構成により、これらのプログラムがサーバーを簡単に検出できるようになるために発生します。

このチュートリアルでは、リモート接続を許可することによって生じる特定のリスクを軽減する方法を示します。 これは重要な最初のステップですが、サーバーは他の方法で危険にさらされる可能性があるため、#additional-security-configuration [Additional Security Considerations]で説明されている追加の対策を講じることをお勧めします。

バックグラウンド

軽減している特定のリスクを理解するために、サーバーをストアと考えてください。 サーバーがポートをまったくリッスンしている場合は、ネオンの「オープン」サインをオンにするようなものです。 これにより、自動化されたスクリプトがサーバーを見つけることができるネットワーク上でサーバー自体が見えるようになります。

各ポートは、ドアや窓のような店に入る方法と考えることができます。 これらの入り口は、リッスンしているソフトウェアの状態に応じて、開いたり、閉じたり、ロックされたり、壊れたりする場合がありますが、パブリックインターフェイスでリッスンすると、内部に入ろうとするスクリプトが試行を開始できます。 たとえば、スクリプトは、変更されていない可能性がある場合にデフォルトのパスワードでログインを試みるように構成されている場合があります。 パッチが適用されていない場合、リスニングデーモンの既知の悪用を試みる可能性があります。 スクリプトが試行するものが何であれ、弱点を見つけてそれを悪用できる場合、侵入者は内部にいて、サーバーを侵害するという深刻なビジネスに取りかかることができます。

「+ postgresql +」のようなデーモンをローカルでリッスンするように制限すると、外部への特定のドアが存在しないようになります。 少なくともPostgresに関しては、次のステップはありません。 ファイアウォールとVPNも同様の方法で保護します。 このチュートリアルでは、一般公開されている出入り口としてPostgreSQLを削除することに焦点を当てます。 デーモン自体または送信または保存されたデータを保護するには、link:#additional-security-configuration [追加のセキュリティに関する考慮事項]を参照してください。

前提条件

このチュートリアルでは、* 2つのUbuntuインストール*を使用します。1つはデータベースホスト用で、もう1つはホストにリモート接続するクライアントとして使用します。 それぞれに「+ sudo +」ユーザーとファイアウォールが有効になっている必要があります。 このガイドは、https://www.digitalocean.com/community/tutorials/initial-server-setup-with-ubuntu-16-04 [Ubuntu 16.04での初期サーバーセットアップ]で役立ちます。

  • 1つのUbuntu 16.04 PostgreSQLデータベースホスト*:

PostgreSQLをまだインストールしていない場合は、次のコマンドを使用してインストールできます。

sudo apt-get update
sudo apt-get install postgresql postgresql-contrib
  • 1つのUbuntu 16.04クライアントマシン*:リモート接続の許可を実証およびテストするために、PostgreSQLクライアントの ` psql +`を使用します。 それをインストールするには、次のコマンドを使用します。

sudo apt-get update
sudo apt-get install postgresql-client

これらの前提条件が整ったら、準備ができています。

デフォルト設定について

PostgreSQLをUbuntuパッケージからインストールすると、デフォルトでlocalhostでのリッスンに制限されます。 このデフォルトは、 `+ 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

これらのデフォルトは、パブリックインターフェイスをリッスンしないという目的を満たしています。 それらをそのままにしてファイアウォールを維持すれば、完了です! link:#additional-security-configuration [Additional Security Considerations]に直接進んで、転送中のデータを保護する方法を学ぶことができます。

リモートホストから接続する必要がある場合は、デフォルトをオーバーライドする方法と、次のセクションでサーバーを保護するためにすぐに実行できる手順について説明します。

リモート接続の構成

実稼働環境で、機密データの操作を開始する前に、理想的には、PostgreSQLトラフィックを転送中にSSLで暗号化し、外部ファイアウォールの背後で保護するか、仮想プライベートネットワーク(VPN)で保護します。 そのために、データベースサーバーでファイアウォールを有効にし、それを必要とするホストへのアクセスを制限する、それほど複雑ではない手順を踏むことができます。

手順1-ユーザーとデータベースの追加

まず、作業をテストできるユーザーとデータベースを追加します。 そのために、PostgreSQLクライアントの `+ psql `を使用して、管理ユーザーの ` postgres `として接続します。 ` -i `オプションを ` sudo `に渡すことで、postgresユーザーのログインシェルを実行し、 ` .profile `またはその他のログイン固有のリソースからオプションを確実にロードします。 ` -u +`はpostgresユーザーを特定します:

sudo -i -u postgres psql

次に、パスワードを持つユーザーを作成します。 以下で強調表示されている例の代わりに、安全なパスワードを使用してください。

CREATE USER  WITH PASSWORD '';

ユーザーが正常に作成されると、次の出力が表示されます。

OutputCREATE ROLE

次に、データベースを作成し、新しいユーザーにフルアクセスを許可します。 ベストプラクティスでは、ユーザーに必要なアクセスのみを許可し、必要なリソースのみに許可することを推奨しています。そのため、ユースケースによっては、ユーザーのアクセスをさらに制限することが適切な場合があります。 許可の詳細については、ガイドhttps://www.digitalocean.com/community/tutorials/how-to-use-roles-and-manage-grant-permissions-in-postgresql-on-a-vps—​をご覧ください。 2 [VPS上のPostgreSQLでロールを使用して権限を付与する方法]。

CREATE DATABASE  OWNER ;

データベースが正常に作成されると、確認が表示されます。

OutputCREATE DATABASE

ユーザーとデータベースを作成したので、モニターを終了します

\q

Enterキーを押すと、コマンドプロンプトが表示され、続行する準備が整います。

ステップ2-UFWの構成

Ubuntu 16.04での初期サーバー設定前提条件では、UFWを有効にし、SSH接続のみを許可しました。 設定を開始する前に、UFWのステータスを確認しましょう。

sudo ufw status

前提条件に変更を加えない限り、出力にはOpenSSHのみが許可されていることが示されます。

OutputStatus: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
OpenSSH (v6)               ALLOW       Anywhere (v6)

ファイアウォールのステータスを確認したので、PostgreSQLポートへのアクセスを許可し、許可するホストに制限します。

以下のコマンドは、PostgreSQLのデフォルトポート(5432)のルールを追加します。 そのポートを変更した場合は、以下のコマンドで必ず更新してください。 アクセスが必要なサーバーのIPアドレスを使用していることを確認してください。 必要な場合は、このコマンドを再実行して、アクセスが必要な各クライアントIPアドレスを追加します。

sudo ufw allow from  to any port

ルールを再確認するには、 `+ ufw status +`を再度実行します:

sudo ufw status
OutputTo                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
5432                       ALLOW
OpenSSH (v6)               ALLOW       Anywhere (v6)

このファイアウォールルールを設定したら、PostgreSQLをパブリックIPアドレスでリッスンするように構成します。 これには、2つの設定の組み合わせ、「+ pg_hba.conf 」の接続ホストのエントリと「 postgresql.conf +」のlisten_addressesの設定が必要です。

ステップ3-許可されたホストの構成

まず、 `+ pg_hba.conf +`にホストエントリを追加します。 異なるバージョンのPostgreSQLがインストールされている場合は、必ず以下のパスで置き換えてください。

sudo nano /etc/postgresql//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       /32   md5

変更を保存する前に、オプションの一部を変更する場合に備えて、この行の各値に注目しましょう。

  • ホスト 最初のパラメーター「+ host +」は、TCP / IP接続が使用されることを確立します。

  • データベース + sammydb + 2番目の列は、ホストが接続できるデータベースを示します。 名前をコンマで区切ることにより、複数のデータベースを追加できます。

  • ユーザー `+ sammy +`は、接続を確立できるユーザーを示します。 データベース列と同様に、複数のユーザーをコンマで区切って指定できます。

  • 住所 アドレスは、クライアントマシンのアドレスを指定し、ホスト名、IPアドレス範囲、またはその他のhttps://www.postgresql.org/docs/9.5/static/auth-pg-hba-conf.html [特別なキーワード]を含めることができます。 上記の例では、クライアントの単一のIPアドレスのみを許可しています。

  • 認証方法 最後に、auth-method、 `+ md5 +`はhttps://www.postgresql.org/docs/9.5/static/auth-methods.html#AUTH-PASSWORD[double-MD5-hashed password]が提供されることを示します認証。 接続するユーザー用に作成されたパスワードを入力するだけです。

これらおよび追加の設定の詳細については、https://www.postgresql.org/docs/9.5/static/auth-pg-hba-conf.html [The + pg_hba.conf + File] PostgreSQLのドキュメントを参照してください。

完了したら、ファイルを保存して終了します。

手順4-リスニングアドレスの構成

次に、 `+ postgresql.conf +`ファイルにリスンアドレスを設定します。

sudo nano /etc/postgresql//main/postgresql.conf

`+ listen_addresses +`行を見つけ、その下にリスンアドレスを定義します。データベースホストのホスト名またはIPアドレスに置き換えてください。 接続しているクライアントではなく、データベースサーバーのパブリックIPを使用していることを再確認してください。

postgresql.conf

#listen_addresses = 'localhost'         # what IP address(es) to listen on;
listen_addresses = 'localhost,'

完了したら、ファイルを保存して終了します。

ステップ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-テスト

最後に、クライアントマシンから接続できることをテストしましょう。 これを行うには、「-p +」と「+ -U 」を使用してユーザーを指定し、「-h 」を使用してクライアントのIPアドレスを指定し、「-d 」を使用してデータベースを指定します。 ` sammy +`が単一のデータベースにのみ接続できるようにセキュリティを強化しました。

psql -U  -h  -d

すべてが正しく構成されている場合、次のプロンプトが表示されます。

OutputPassword for user sammy:

PostgreSQLモニターでユーザー `+ sammy +`を追加したときに設定したパスワードを入力します。

次のプロンプトが表示されたら、接続に成功しています:

[secondary_label]
sammydb=>

これにより、ファイアウォールを通過してデータベースに接続できることが確認されます。 今すぐ終了します。

\q

設定を確認したので、クリーンアップして終了します。

手順7-テストデータベースとユーザーの削除

接続のテストが終了したら、ホストに戻り、次のコマンドを使用してデータベースとユーザーも削除できます。

sudo -i -u postgres psql

データベースを削除するには:

DROP DATABASE ;

アクションは、次の出力によって確認されます。

OutputDROP DATABASE

ユーザーを削除するには:

DROP USER ;

成功は次によって確認されます。

OutputDROP ROLE

不要になったため、 `+ pg_hba.conf `ファイルから ` sammydb +`データベースのホストエントリを削除して、クリーンアップを終了します。

sudo nano /etc/postgresql//main/pg_hba.conf

`pg_hba.conf`から削除する行

host       /32   md5

変更を有効にするために、保存して終了し、データベースサーバーを再起動します。

sudo systemctl restart postgresl

正常に再起動したことを確認するために、ステータスを確認します。

sudo systemctl status postgres

「アクティブ:アクティブ」と表示される場合、再起動が成功したことがわかります。

この時点で、リモートで接続する必要があるクライアントでアプリケーションまたはサービスを構成することで前進できます。

セキュリティに関する追加の考慮事項

このチュートリアルは、PostgreSQLへのセキュリティ保護されていないリモート接続を許可することによってもたらされるリスクを軽減することを目的としています。これは、PostgreSQLを不注意にエクスプロイトにさらす一般的な状況です。 リスニングポートへのアクセスを特定のホストに制限しても、転送中のデータを暗号化する方法など、セキュリティに関するその他の重要な考慮事項に対処することにはなりません。

実際のデータを使用する前に、次のリソースを確認し、ユースケースに適した手順を実行することをお勧めします。

  • PostgreSQL内のセキュリティ:GRANTステートメントは、アクセスできるユーザーを決定します特定のデータベース、ロールはそれらのユーザーの権限を確立します。 組み合わせて、単一のインストールで複数のデータベースを分離します。

  • PostgreSQLでSSLを設定:SSLを設定すると、転送中のデータが暗号化されます。 これにより、送信されるデータが保護されます。

  • SSHトンネルを使用したPostgreSQL TCP / IP接続の保護:SSHトンネルは、SSL対応でないクライアントと接続する場合に役立ちます。 他のほとんどの状況では、PostgresでSSLをセットアップすることをお勧めします。

結論

このチュートリアルでは、アクセスを必要とするホストからの接続のみを許可するようにサーバーのファイアウォールを構成し、それらのホストからの接続のみを受け入れるようにPostgreSQLを構成することにより、PostgreSQLインストールのアドバタイズを防ぐための重要な手順を実行しました。 これにより、特定の種類の攻撃のリスクが軽減されます。 これは、データを保護するための最初のステップにすぎません。上記の追加のセキュリティ対策を確認して実装することをお勧めします。

Related