2010-06-02 1 views
0

Я пишу веб-сервис в PHP в первый раз и столкнулся с некоторыми проблемами безопасности.Безопасность при написании веб-службы PHP?

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

2) Я слышал, что что-либо, что когда действие выполняется только для чтения, вы должны использовать GET, но если он изменяет базу данных, вы должны использовать POST. Не является ли сообщение столь же прозрачным, как GET, просто не в адресной строке?

+0

Не используйте md5, если вам нужна реальная безопасность, столкновение с Google MD5, используйте что-то со стандартом sha2. –

+0

ОК, но я думаю, что остальная часть вопроса остается в силе, верно? – chustar

+0

Столкновение md5 на самом деле не актуально, когда речь заходит о теме хэширования паролей, не так ли? Это больше относится к дайджесту сообщений, и даже тогда он на самом деле не был широко использован в реальном мире AFAIK. Я имею в виду, конечно, использовать SHA, но я никогда не слышал о том, что схема хэширования пароля скомпрометирована из-за слабостей MD5. –

ответ

5

Обычно не рекомендуется использовать собственный уровень хэширования. Я уверен, что md5 будет в порядке, если вы просто делаете действительно крошечный сайт для учебных целей, но если вы храните важную информацию для более крупного сайта, вы должны использовать библиотеку, такую ​​как PHPass:

Спасибо в Jacco для этого PHPass фрагмента кода:

require('PasswordHash.php'); 

$pwdHasher = new PasswordHash(8, FALSE); 

// $hash is what you would store in your database 
$hash = $pwdHasher->HashPassword($password); 

// $hash would be the $hashed stored in your database for this user 
$checked = $pwdHasher->CheckPassword($password, $hash); 
if ($checked) { 
    echo 'password correct'; 
} else { 
    echo 'wrong credentials'; 
} 

Если вы настаиваете на делать это самостоятельно, вы должны соль паролей. См. http://phpsec.org/articles/2005/password-hashing.html.

define('SALT_LENGTH', 9); 

function generateHash($plainText, $salt = null) 
{ 
    if ($salt === null) 
    { 
     $salt = substr(md5(uniqid(rand(), true)), 0, SALT_LENGTH); 
    } 
    else 
    { 
     $salt = substr($salt, 0, SALT_LENGTH); 
    } 

    return $salt . sha1($salt . $plainText); 
} 

Причина разницы между GET и POST заключается в том, как браузер интерпретирует запросы. Как упоминалось выше, веб-сканеры не будут выполнять POST-запросы. Но представьте, что вы отправились на страницу своего сайта http://example.com/deleteuser.php?userid=25, чтобы удалить неприятный спамер. Затем вы закроете свой браузер. В следующий раз, когда вы вернетесь, firefox снова откроет эту страницу, и вы, к сожалению, удалили пользователя, который только что зарегистрировался!

Другая причина для GET против POST - частичная профилактика против cross-site request forgeries.Если у вас была страница, в которой пользователь выходил из запроса GET, кто-то мог встроить тег изображения в комментарий или сообщение в форуме, например <img src="http://example.com/logout.php" />, и браузеру пришлось бы выполнить операцию выхода из системы. Таким образом, любой пользователь, который просмотрел эту страницу, будет выведен из системы, даже если они были администратором.

Редактировать: В стороне, вы должны, вероятно, использовать sha-256 или bcrypt вместо md5, который был взломан (?).

+0

+1. Соль сама по себе не в том, чтобы быть всем и заканчивать всю безопасность. «Адаптивное хеширование» - это современное состояние: http://www.securityfocus.com/blogs/262 –

1

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

Из-за этого я думал о md5(), используя его с клиентской стороной javascript, а затем повторно на сервере, но если javascript отключен, то пользователь не может войти в систему, верно?

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

2) Я слышал, что все, что когда действие выполняется только для чтения, вы должны использовать GET, но если он изменяет базу данных, вы должны использовать POST. Не является ли сообщение столь же прозрачным, как GET, просто не в адресной строке?

Сканеры (включая поисковые системы) не будут отправлять POST-запросы. Браузеры обычно предупреждают пользователей о повторной отправке данных POST.

Использование POST и GET для правильных вещей не является вопросом безопасности.

+0

Предварительная загрузка браузеров (FasterFox) также GET, но не будет POST. Для дальнейшего чтения см. Http://thedailywtf.com/articles/the_spider_of_doom.aspx и RFC 2616 http://www.w3.org/Protocols/rfc2616/rfc2616.html. Предполагается, что GET является идемпотентным и не имеет побочных эффектов. Сканеры и prefetchers рассчитывают на то, что это правда. –

+1

Как вы упомянули, хеширование клиентов мало помогает в попытке избежать нюхания пароля (вам нужно только обнюхивать хэш и отправлять его, как строку). Лучше использовать шифрованный протокол, например HTTPS. – jpabluz