如何保护PostgreSQL免受自动攻击

来自菜鸟教程
跳转至:导航、​搜索

介绍

可能很容易想到,因为服务器刚刚启动,流量很少,或者没有提供任何对黑客有价值的东西而不会被忽视。 然而,许多漏洞利用是自动化的,专门用于查找配置中的常见错误。 这些程序扫描网络以发现服务器,与内容的性质无关。

允许远程连接是可能导致 PostgreSQL 数据库被利用的常见且更容易纠正的情况之一。 发生这种情况是因为某些配置使此类程序很容易发现服务器。

在本教程中,我们将展示如何减轻允许远程连接带来的特定风险。 虽然这是重要的第一步,但由于服务器可能会以其他方式受到威胁,我们还建议您采取额外措施来保护您的数据,如 其他安全注意事项 中所述。

背景

要了解我们正在减轻的具体风险,请将服务器想象成一个商店。 如果服务器正在侦听任何端口,这有点像打开霓虹灯“打开”标志。 它使服务器本身在网络上可见,自动化脚本可以在其中找到它。

我们可以将每个端口视为进入商店的途径,就像一扇门或一扇窗户。 这些入口可能是打开、关闭、锁定或损坏,具体取决于正在侦听的软件的状态,但在公共界面上侦听意味着试图进入的脚本可以开始尝试。 例如,脚本可能被配置为尝试使用默认密码登录,但前提是该密码尚未更改。 如果尚未修补,它可能会尝试对侦听守护程序的已知漏洞利用。 无论脚本尝试什么,如果它能够找到一个弱点并加以利用,那么入侵者就在里面,并且可以着手处理破坏服务器的严肃事务。

当我们将 postgresql 之类的守护进程限制为在本地侦听时,就好像通往外部的特定门不存在。 至少在 Postgres 方面,没有下一步可以尝试。 防火墙和 VPN 以类似的方式进行保护。 在本教程中,我们将专注于删除 PostgreSQL 作为可公开访问的门户。 要保护守护程序本身或传输或存储数据时的安全,请参阅 Additional Security Considerations

先决条件

在本教程中,我们将使用 两个 Ubuntu 安装 ,一个用于数据库主机,一个作为将远程连接到主机的客户端。 每个人都应该有一个 sudo 用户并启用防火墙。 指南,Initial Server Setup with Ubuntu 16.04 可以帮助你。

一台 Ubuntu 16.04 PostgreSQL 数据库主机

如果您还没有安装 PostgreSQL,可以使用以下命令进行安装:

sudo apt-get update
sudo apt-get install postgresql postgresql-contrib

一台 Ubuntu 16.04 客户端机器:为了演示和测试允许远程连接,我们将使用 PostgreSQL 客户端 psql。 要安装它,请使用以下命令:

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

具备这些先决条件后,您就可以继续跟进了。

了解默认配置

从 Ubuntu 软件包安装 PostgreSQL 时,默认情况下它仅限于在 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

这些默认值满足不监听公共接口的目标。 如果我们保持它们完好无损并保持防火墙正常运行,我们就完成了! 我们可以直接进入 其他安全注意事项 以了解如何保护传输中的数据。

如果您需要从远程主机连接,我们将在下一节中介绍如何覆盖默认设置以及您可以立即采取的保护服务器的步骤。

配置远程连接

对于生产设置,在我们开始处理敏感数据之前,理想情况下,我们将在传输过程中使用 SSL 加密 PostgreSQL 流量,保护在外部防火墙后面,或通过虚拟专用网络 (VPN) 保护。 当我们朝着这个方向努力时,我们可以采取稍微不那么复杂的步骤,在我们的数据库服务器上启用防火墙并限制对需要它的主机的访问。

第 1 步 — 添加用户和数据库

我们将首先添加一个用户和数据库,以便我们测试我们的工作。 为此,我们将使用 PostgreSQL 客户端 psql 以管理用户 postgres 的身份进行连接。 通过将 -i 选项传递给 sudo 我们将运行 postgres 用户的登录 shell,这确保我们从 .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。


接下来,我们将创建一个数据库并授予我们的新用户完全访问权限。 最佳实践建议我们只授予用户他们需要的访问权限,并且只授予他们应该拥有的资源,因此根据用例,可能适当地限制用户的访问权限。 您可以在指南 How To Use Roles and Manage Grant Permissions in PostgreSQL on a VPS 中了解有关权限的更多信息。

CREATE DATABASE sammydb OWNER sammy;

成功创建数据库后,我们应该会收到确认:

OutputCREATE DATABASE

现在,我们已经创建了一个用户和数据库,我们将退出监视器

\q

按 ENTER 后,我们将进入命令提示符并准备继续。

第 2 步 — 配置 UFW

Initial Server Setup with Ubuntu 16.04 先决条件中,我们启用了 UFW 并且只允许 SSH 连接。 在开始配置之前,让我们验证 UFW 的状态:

sudo ufw status

注意: 如果输出表明防火墙是 inactive 我们可以通过以下方式激活它:

sudo ufw enable

启用后,重新运行状态命令,sudo ufw status 将显示当前规则。 如有必要,请务必允许 SSH。

sudo ufw allow OpenSSH

<$>

除非我们对先决条件进行了更改,否则输出应该显示只允许 OpenSSH:

OutputStatus: active

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

现在我们已经检查了防火墙状态,我们将允许访问 PostgreSQL 端口并将其限制为我们想要允许的主机或主机。

下面的命令将为 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:通用防火墙规则和命令 .


有了这个防火墙规则,我们现在将配置 PostgreSQL 来监听它的公共 IP 地址。 这需要两个设置的组合,pg_hba.conf 中的连接主机条目和 postgresql.conf 中的 listen_addresses 配置。

第 3 步 — 配置允许的主机

我们将首先在 pg_hba.conf 中添加主机条目。 如果您安装了不同版本的 PostgreSQL,请务必将其替换为以下路径:

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

我们将把 host 行放在描述如何允许非本地连接的注释块下。 我们还将包含一个包含数据库服务器公共地址的行,以便我们可以快速测试我们的防火墙是否配置正确。 请务必在下面的示例中替换 你的 机器的主机名或 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 连接。
  • 数据库 sammydbThe 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.
  • 地址地址指定客户端机器地址,可能包含主机名、IP地址范围或其他特殊关键字。 在上面的示例中,我们只允许客户端的单个 IP 地址。
  • auth-method 最后,auth-method md5 表示将提供 double-MD5-hashed 密码 用于身份验证。 您只需提供为连接用户创建的密码即可。

有关这些和其他设置的更完整讨论,请参阅 The 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

我们将通过从 pg_hba.conf 文件中删除 sammydb 数据库的主机条目来完成清理,因为我们不再需要它:

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

如果我们看到“Active: active”,我们就知道重启成功了。

此时,我们可以继续在需要远程连接的客户端上配置应用程序或服务。

其他安全注意事项

本教程旨在减轻允许与 PostgreSQL 的不安全远程连接所带来的风险,这是一种常见情况,会无意中将 PostgreSQL 暴露给漏洞利用。 将对侦听端口的访问限制为特定主机并不能解决其他重要的安全问题,例如如何加密传输中的数据。

在使用真实数据之前,我们建议您查看以下资源并针对您的使用案例采取适当的步骤。

  • PostgreSQL 中的安全性:GRANT 语句确定允许哪些用户访问任何特定数据库,而角色确定这些用户的权限。 结合起来,它们在单个安装中提供多个数据库之间的分离。
  • 使用 PostgreSQL 设置 SSL:配置 SSL 将加密传输中的数据。 这可以在发送数据时保护数据。
  • 使用 SSH 隧道保护 PostgreSQL TCP/IP 连接:SSH 隧道在连接不支持 SSL 的客户端时很有用。 在几乎任何其他情况下,最好使用 Postgres 设置 SSL。

结论

在本教程中,我们采取了必要的步骤来防止发布我们的 PostgreSQL 安装,方法是将服务器的防火墙配置为仅允许来自需要访问的主机的连接,并将 PostgreSQL 配置为仅接受来自这些主机的连接。 这减轻了某些类型的攻击的风险。 这只是保护数据的第一步,我们建议审查并实施上述额外的安全措施。