Безопасно отправлять пароли из формы входа в Flask - PullRequest
0 голосов
/ 22 марта 2019

У меня есть веб-сайт с простой функцией входа в систему с использованием сессий.Я думал, что это безопасно, потому что я хэшировал и хранил пароли, но я понял, что на самом деле (вероятно) происходит то, что я отправляю незашифрованный пароль в POST-запросе на сервер, и только тогда я хэширую и солюю его,Я думал, что понял, как управлять паролями, но теперь мне интересно, что делать.

Вот мой код:

import bcrypt
from argon2 import PasswordHasher, exceptions
import db as database

ph = PasswordHasher()


@app.route("/login", methods=["POST", "GET"])
def login():
    if check_logged_in(session, 0):
        return redirect("/index")
    else:
        error = ""  # set to nothing unless we get error below
        if request.method == "POST":  # if user submits form
            username = request.form["username"]  # retrieve username from form
            password = request.form["password"]  # retrieve password from form
            if verify_login(username, password):  # if their login is valid
                session["username"] = username  # update session with their username and redirect them to index
                return redirect("/index")
            error = "Invalid username or password"  # else update the error message
        return render_template("login.html", error=error)  # and return login with error message


def verify_login(username, password):
    db_hash, salt = database.retrieve_pw_salt(username)  # gets hashed/salted password and salt from database given a username
    if db_hash is None:
        return False  # invalid username
    try:
        ph.verify(db_hash, salt + password)
        return True  # valid username and password
    except exceptions.VerifyMismatchError:
        return False  # invalid password


def check_logged_in(session, required_privilege):
    if "username" not in session:
        return False  # not logged in
    elif session["username"] == "admin":
        return True  # logged in as admin
    elif session["username"] == "reception" and required_privilege <= 1:  # checks to ensure a reception isn't trying to access admin pages/features
        return True  # logged in as reception
    elif session["username"] == "teacher" and required_privilege == 0:  # checks to ensure a teacher isn't trying to access admin/reception pages/features
        return True  # logged in as teacher
    return False  # else not logged in

Я думаю, я думал, что этот код будет работать нана стороне клиента, но я не думаю, что это так.В таком случае, как я могу получить соль для моего пользователя на стороне клиента, а затем объединить ее с паролем, хэшировать ее и только потом отправлять на мой сервер?

Мой сервер работает под управлением Nginx с включенным uWSGIUbuntu 18.04, если это что-то меняет.

Спасибо.

РЕДАКТИРОВАТЬ: Вот как я генерировал соли в первую очередь:

def generate_salt():  # creates a salt
    salt = bcrypt.gensalt().decode("utf-8")
    return salt

Ответы [ 2 ]

1 голос
/ 23 марта 2019

Я использую HTTPS, но я думал, что он также использовался.

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

Похоже, вы обеспокоены тем, что кто-то может прочитать пароль в пути:

, но я понял, что на самом деле(вероятно) происходит то, что я отправляю незашифрованный пароль в POST-запросе на сервер

Вы ошибаетесь, когда говорите, что пароль отправляется в виде простого текста при использовании https,Https означает, что канал между сервером и браузером зашифрован и .. считается безопасным (*).Двойное шифрование не повышает безопасность, хотя может показаться, что выполнение дополнительной работы даст вам «что-то».

Если вы пытаетесь защитить от злоумышленника, который контролирует браузер или клиентский компьютер,тогда никакое количество шифрования на стороне клиента не поможет;Ситуация такая же, если вы пытаетесь защитить от злоумышленника, который контролирует сервер.

Одна из ситуаций, которая может привести к утечке паролей, - необработанные исключения во время процедуры POST.Большинство веб-приложений сообщают о таких ошибках либо по электронной почте, либо через такие службы, как Sentry.Веб-фреймворки обычно имеют способ смягчить эту проблему, который является более общим и более простым для работы, чем шифрование на стороне клиента (например, @sensitive_post_parameters(...) https://docs.djangoproject.com/en/2.1/howto/error-reporting/#django.views.decorators.debug.sensitive_post_parameters).

в Django). Одна из ситуаций, когда вы используете шифрование на стороне клиента, -если пользователь хочет сохранить / получить на сервере данные, которые администратор сервера не сможет прочитать. Сервер не может взаимодействовать с данными, поэтому он не используется для паролей при входе в систему.

(*) если вы хотите защититься от кого-то, кто может расшифровать канал https, вы выходите за рамки того, что необходимо для формы входа для обычных веб-сайтов (и если вы работаете в АНБ, вам, вероятно, следует спросить внутренне, а нена SO; -)

ps: вы, вероятно, не должны декодировать ('utf-8') результат bcrypt.gensalt() - я не смотрел, но не могу себе представить, что он возвращает utf-8 data.

дополнение: не все двоичные данные имеют формат utf-8. base64 - это один из способов создания представления в юникоде:

>>> b = b'\xc3\x28'   # byte sequence that is not valid utf-8
>>> b.decode('utf-8')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xc3 in position 0: invalid continuation byte
>>> import base64
>>> base64.b64encode(b)
b'wyg='
>>> base64.b64encode(b).decode('ascii')
'wyg='
>>>
0 голосов
/ 22 марта 2019

С точки зрения злоумышленника, хеширование на стороне клиента не обеспечивает дополнительной безопасности.Смотри https://security.stackexchange.com/questions/62280/client-side-hashing-of-password-before-sending-it-from-login-form

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...