Безопасный способ обновить пароль учетной записи UNIX, используя Python в качестве пользователя root?

#python #linux #unix #passwords

#python #linux #unix #пароли

Вопрос:

Рассмотрим учетную запись UNIX jdoe . Я хочу обновить jdoe пароль, используя скрипт Python, запущенный как root . В настоящее время я использую:

 cmd = 'echo "'   username   ":"   new_pass   '" | chpasswd '
os.system(cmd)
  

Однако это небезопасный метод. Если бы кто-то вошел new_pass как pass"; rm -rf / # , это было бы катастрофой.

Есть ли безопасный способ сделать это?

Ответ №1:

Если вас беспокоит ненадежный ввод, лучше избегать использования os.system , поскольку это вызывает оболочку, и, в общем, вы не хотите, чтобы оболочка находилась рядом с ненадежным вводом. Кроме того, вы обычно хотите избежать ввода секретов в аргументы командной строки, поскольку они могут быть прочитаны другими пользователями, хотя, поскольку echo это обычно встроено, это не является строго проблемой здесь.

Чтобы сделать это безопасно, вы можете использовать subprocess.Popen вместо этого, вот так:

 import subprocess

proc = subprocess.Popen(['chpasswd'], stdin=subprocess.PIPE)
proc.stdin.write(b"username:password")
  

Обратите внимание, что если вам нужно передать дополнительные аргументы chpasswd , вы бы сделали это, добавив аргументы в массив:

 proc = subprocess.Popen(['chpasswd', '-c', 'SHA512'], stdin=subprocess.PIPE)
  

Комментарии:

1. Похоже, это работает с new_pass = pass"; rm -rf / # . Надеюсь, я ничего не упускаю из виду.

2. Он действительно должен работать с произвольным паролем, включая пароль, содержащий внедрение оболочки. В этом случае это всего лишь часть пароля, а не уязвимость системы безопасности.

3. Удивительно, но это не работает с flask, я не могу понять, почему.

4. Ах, замена proc.stdin.write(...) на proc.communicate(input=...) исправила проблему.

Ответ №2:

Я бы изменил его так, чтобы введенный пароль был хэширован (sha512 является стандартным в современных системах Linux), а затем передал значение хэшей в ваш cmd.

 cmd = 'echo "'   username   ":"   new_pass   '" | chpasswd -e'
os.system(cmd)
  

Обратите внимание на -e после chpasswd

Уточняем приведенное выше предложение немного подробнее:

 import crypt
entered_password = 'pass"; rm -rf / #'
new_password = crypt.crypt(entered_password, '$6$'   'salt1234')
  

Комментарии:

1. Я делаю cmd = 'echo "' username ":" sha512(new_pass) '" | chpasswd -e' , os.system(cmd) но когда я пытаюсь войти в систему, new_pass это недопустимо. Для чего используется хэш по умолчанию chpasswd -e ? Похоже, что это не sha256.