MD5 хешированные пароли: где хешируется?

Я подключаюсь к локальной базе данных PostgreSQL с хешированным паролем md5.

Это работает, но я хочу понять, что происходит под капотом.
Pq хеширует пароль перед отправкой по сети? Как он узнает, нужно ли его хешировать или оставить в виде простого текста? Сервер (в pg_hba.conf) - это тот, кто указывает метод аутентификации того, как пароль передается по соединению.

Есть ли рукопожатие, которое происходит между pq и psql перед передачей строки соединения с паролем?

  user := "foo_user"
  password := "test"
  dbname := "bar"
  connectionString := fmt.Sprintf(
      "user=%s password=%s dbname=%s", 
      user, 
      password, 
      dbname)
  db, err := sql.Open("postgres", connectionString)

Пользователь был создан с паролем через:

ALTER USER foo_user WITH PASSWORD 'test';

И проверил, что пароль хранится как хеш:

postgres=# SELECT rolname, rolpassword from pg_authid;
      rolname      |             rolpassword             
-------------------+-------------------------------------
 postgres          | 
 pg_signal_backend | 
 foo_user          | md51083525553eab8f4090ada980d2b86e7
(3 rows)

И pg_hba.conf совершенно не изменяется:

# 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

1 ответ

Решение

Есть два места, где происходит хеширование паролей, и их не следует путать.

  1. Когда для роли установлен пароль, он объединяется с именем пользователя и затем хэшируется. Этот пароль хранится в pg_authidи это фактический пароль, используемый PostgreSQL. PostgreSQL использует не введенный вами пароль, а его хешированную версию, чтобы злоумышленники не могли украсть ваш пароль и затем пытаться использовать его вне PostgreSQL (в случае, если один и тот же пароль используется в нескольких местах).

    Таким образом, чтобы проникнуть в базу данных, вам на самом деле не нужно знать пароль в виде открытого текста, достаточно "фактического" хешированного пароля.

    Есть два места, где может происходить хеширование:

    • На стороне сервера, если вы используете

      CREATE/ALTER ROLE ... PASSWORD 'mypassword';
      

      Это не очень хорошо, потому что пароль передается по сети в виде открытого текста и может отображаться в журнале базы данных.

    • На стороне клиента, если вы используете

      CREATE/ALTER ROLE ... PASSWORD 'hashedpassword';
      

      Это лучше, и это то, что psql использует внутренне, если вы используете \password команда.

  2. Во время аутентификации сеанса, если метод аутентификации, указанный для базы данных и пользователя, требует этого. Затем сервер ответит на запрос соединения AuthenticationMD5Password сообщение (см. документацию).

    Затем клиент хеширует пароль в виде открытого текста, чтобы получить действительный пароль, а затем снова хеширует его со случайной "солью", предоставленной сервером.

    Сервер хеширует пароль от pg_authid таким же образом и сравнивает результат.

Другие вопросы по тегам