Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
C++. Мастер-класс в задачах и примерах. Авторы: Кузнецов М.В., Симдянов И.В. Объектно-ориентированное программирование на PHP. Авторы: Кузнецов М.В., Симдянов И.В. Социальная инженерия и социальные хакеры. Авторы: Кузнецов М.В., Симдянов И.В. PHP. Практика создания Web-сайтов (второе издание). Авторы: Кузнецов М.В., Симдянов И.В. PHP на примерах (2 издание). Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум PHP

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Активация письмом
 
 автор: serjinio   (20.01.2009 в 00:41)   письмо автору
 
 

Что передавать в ссылке на активацию в письме????
id юзера, хэш его логина , маил..,.какой нибудь кей уже сгенерированный и записанный в бд...кто это реализовывал ,подскажите...

  Ответить  
 
 автор: Николай2357   (20.01.2009 в 05:36)   письмо автору
 
   для: serjinio   (20.01.2009 в 00:41)
 

Теоретически большой разницы нет, что передать, лишь бы это было ключем к активации. Но для "чистоты эксперемента" этот ключ должен быть уникальным. Одно из решений - "солёный" хэш E-mail'а. Допустим так:
<?
$code 
md5($email.rand());
Его нужно хранить в базе до момента активации или истечения времени, отведенного на активацию.

  Ответить  
 
 автор: Trianon   (20.01.2009 в 11:17)   письмо автору
 
   для: Николай2357   (20.01.2009 в 05:36)
 

что помешает посчитать его третьей стороне, не владеющей ящиком?

  Ответить  
 
 автор: Николай2357   (20.01.2009 в 11:39)   письмо автору
 
   для: Trianon   (20.01.2009 в 11:17)
 

А какой смысл его считать? Помочь активировать аккуант? Информации полезной там нет, пусть считают на здоровье. Это же для антиспама процедура, не более того...

  Ответить  
 
 автор: serjinio   (20.01.2009 в 16:41)   письмо автору
 
   для: Николай2357   (20.01.2009 в 11:39)
 

так что передавать...
id и key
майл и кей
хэш логина и id
или что-то еще ..какой оптимальный вариант,учитываю что по какому либо переданному параметру будет выборка в бд ..как правильно...

  Ответить  
 
 автор: Николай2357   (20.01.2009 в 17:14)   письмо автору
 
   для: serjinio   (20.01.2009 в 16:41)
 

Вот потому, что выборка будет именно по этому ключу и нужно, что бы он был уникальным. Если Вы проверяете до этого наличие Е-mail в бд при валидации формы, то он и будет уникальным. А для того, что бы по "счастливой" случайности он не попал в лапы какого нибудь спам-бота, его нужно закэшировать, а для пущей важности еще "посолить". Только если есть автологин, то при активации записи, когда человек придет по ссылке, желательно попросить пароль, дабы не поставить кукис злоумышленнику. Можете поставить вместо него id, даже лучше наверное. Смотря какая структура таблиц при регистрации.

  Ответить  
 
 автор: Trianon   (20.01.2009 в 17:51)   письмо автору
 
   для: Николай2357   (20.01.2009 в 11:39)
 

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

  Ответить  
 
 автор: serjinio   (20.01.2009 в 18:50)   письмо автору
 
   для: Trianon   (20.01.2009 в 17:51)
 

Что-то я совсем запутался ....

  Ответить  
 
 автор: Trianon   (20.01.2009 в 19:37)   письмо автору
 
   для: serjinio   (20.01.2009 в 18:50)
 

зачем вообще нужна активация по e-mail ?

  Ответить  
 
 автор: Николай2357   (20.01.2009 в 19:35)   письмо автору
 
   для: Trianon   (20.01.2009 в 17:51)
 

При регистрации с подтверждением на почтовый ящик информация о этом самом почтовом ящике как раз априори и не является особо секретной, так как в любом случае (используется) хранится в открытом виде. Так что по моему скрывать эту информацию каким то изощренным способом особой причины нет. Другое дело постараться обезопаситься от таких обвинений, сделав расшифровку этого кода, в случае перехвата, нерентабельной.
А вот как сделать идентификацию клиента по информации, известной только ему, я что то не понимаю... С чем то сверять её надо всё равно. Единственное, что приходит на ум - сначала провести проверку, а потом регистрацию. Но вопрос то именно в активации уже готовой учетной записи.
Помнится Вы преподали мне урок по системе восстановления пароля, может быть я и тут многого недопонимаю...

  Ответить  
 
 автор: Trianon   (20.01.2009 в 19:40)   письмо автору
 
   для: Николай2357   (20.01.2009 в 19:35)
 

>При регистрации с подтверждением на почтовый ящик информация о этом самом почтовом ящике как раз априори и не является особо секретной...

Вот именно.
Поэтому полагаться на то, что подтвердить регистрацию ссылкой, построенной на основе лишь этой информации, сможет только владелец почтового ящика и никто другой - нельзя.
Мы и ссылку то в ящик отправляем не от хорошей жизни, а лишь надеясь, что никто, кроме владельца ящика, по ней не перейдет. Что и будет косвенным подтверждением, что адрес, указанный при регистрации логина действительно принадлежит лицу, регистрирующему логин.

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

  Ответить  
 
 автор: Николай2357   (20.01.2009 в 20:01)   письмо автору
 
   для: Trianon   (20.01.2009 в 19:40)
 

Но работа с почтой зачастую необходима (рассылки, уведомления и пр). Так хоть как то усложняется жизнь спамерам. Как он сможет нахэшировать соленые рандомом коды подтверждения, я чего то не пойму... К тому же обычно код подтверждения анулируется при третьей - пятой неудачной попытке. В любом случае ему придется принимать почту. Универсального решения все равно нет, если не считать премодерацию. Но ведь в данном случае и она как мертвому припарка. На соискателе ведь не написано - Я ЗЛОБНЫЙ СПАМЕР...

  Ответить  
 
 автор: Trianon   (20.01.2009 в 20:08)   письмо автору
 
   для: Николай2357   (20.01.2009 в 20:01)
 

Стоп. Прошу прощения. Случайной составляющей я и вправду не заметил. Прочел как $code = md5($email);.
Тогда пойдет. Ну то есть можно конечно придраться к источнику этой самой составляющей, но в принципе пойдет.

  Ответить  
 
 автор: BinLaden   (20.01.2009 в 20:09)   письмо автору
 
   для: Николай2357   (20.01.2009 в 20:01)
 

> Как он сможет нахэшировать соленые рандомом коды подтверждения, я чего то не пойму

Вашу "соль" можно угадать: это от нуля до RAND_MAX (часто 32768). Это сравнительно малое количество вариантов.

  Ответить  
 
 автор: Николай2357   (20.01.2009 в 20:16)   письмо автору
 
   для: BinLaden   (20.01.2009 в 20:09)
 

Ну ведь больше трёх... В принципе наверное и впрямь лучше использовать id записи, хотя бы из этических соображений.

  Ответить  
 
 автор: BinLaden   (20.01.2009 в 20:26)   письмо автору
 
   для: Николай2357   (20.01.2009 в 20:16)
 

id записи?.. Думаете, так сложно его угадать?

  Ответить  
 
 автор: Trianon   (20.01.2009 в 20:29)   письмо автору
 
   для: Николай2357   (20.01.2009 в 20:16)
 

Уж он-то куда более детерминирован. Тем более - в потоке последовательных регистраций.
Что имеет смысл брать в качестве случайной составляющей в хеше здесь уже не раз обсуждалось...

  Ответить  
 
 автор: Николай2357   (20.01.2009 в 20:44)   письмо автору
 
   для: Trianon   (20.01.2009 в 20:29)
 

>Что имеет смысл брать в качестве случайной составляющей в хеше здесь уже не раз обсуждалось...
Вопрос не в случайности а именно в уникальности. А подобрать теоретически можно всё что угодно. Даже макака при определенном стечении обстоятельств может исполнить 7-ю сонату Бетховена. Дело не в невозможности а в нерентабельности. Прочность замков определяется тестовым временем на его взлом. Если оно превышает среднестатистическое время попытки домушника проникнуть в помещение, замок признается надежным. Сколько времени потребуется скрипту на такой подбор, если после трех неудачных попытках заставить его снова запрашивать код подтверждения с вводом адреса??

  Ответить  
 
 автор: BinLaden   (20.01.2009 в 21:52)   письмо автору
 
   для: Николай2357   (20.01.2009 в 20:44)
 

Чо такое, Николай? Пишите проще и более кратко. Вместо того, чтобы сказать "ой, я ляпнул про id с дуру" Вы нам рассказываете о макаке с Бетховеном?

  Ответить  
 
 автор: Николай2357   (20.01.2009 в 22:02)   письмо автору
 
   для: BinLaden   (20.01.2009 в 21:52)
 

Ну вот кратко:
<?
session_start
();
$code = ... $_GET['code']:null;
$_SESSION['count'] ++;

if(
$_SESSION['count'] > 3)
{
sleep(3);
header("location: страница с вводом E-mail и обнулением переменной сессии");
exit();
}

$res mysql_query("SELECT COUNT(*) AS cnt WHERE `code`='".$code."' ");

if(!
mysql_result($res,0,'cnt'))
{
echo 
"Осталось попыток: ".($_SESSION['count']);
echo  
"Введите код активации: <form  action='?' method='get'>...";
}
else
{
// здесь  активация
Тут можно в принципе и id солёный захэшировать... Кому охота будет ресурсы на такое тратить?

  Ответить  
 
 автор: Trianon   (20.01.2009 в 22:05)   письмо автору
 
   для: Николай2357   (20.01.2009 в 22:02)
 

???

Письмо с подтверждением запросто может прийти, когда время сессии двадцать раз выйдет.

  Ответить  
 
 автор: Николай2357   (20.01.2009 в 22:07)   письмо автору
 
   для: Trianon   (20.01.2009 в 22:05)
 

Вообще я понимаю, что можно и заголовок подделать, чтоб сессию обнулить. Это просто принцип. А письмо тут не при чем. Попытки считаются с момента начала активации, а не с момента отправки письма.
PS маленько исправил, чтоб понятней.

  Ответить  
 
 автор: BinLaden   (20.01.2009 в 22:23)   письмо автору
 
   для: Николай2357   (20.01.2009 в 22:02)
 

> Ну вот кратко:

OK, а какое отношение этот код имеет к вопросу о хешировании идентификатора?

  Ответить  
 
 автор: Николай2357   (20.01.2009 в 22:32)   письмо автору
 
   для: BinLaden   (20.01.2009 в 22:23)
 

Этот код имеет отношение к макаке с Бетховеном. Я же написал, что бороться с подбором можно другим, более радикальным способом, нежели пытаться запутать взломщика страшными случайными строками. А идентифицировать клиента все равно нужно по уникальному ключу, буде то id, E-mail или логин на худой конц... Лишь бы не повторялось.

  Ответить  
 
 автор: BinLaden   (20.01.2009 в 23:21)   письмо автору
 
   для: Николай2357   (20.01.2009 в 22:32)
 

> Этот код имеет отношение к макаке с Бетховеном
Понятно. Вы всё о своём.

  Ответить  
 
 автор: Trianon   (20.01.2009 в 22:07)   письмо автору
 
   для: Николай2357   (20.01.2009 в 20:44)
 

Макаронные изделия на ушах мне не нужны.

  Ответить  
 
 автор: serjinio   (20.01.2009 в 20:51)   письмо автору
 
   для: Trianon   (20.01.2009 в 20:29)
 

я лично сделал так...

/* Функция получения Соли */
function G_s($n=5) 
{
$ch = 'abcdefghijklmnopqrstuvwxyzABCDEFGHI JKLMNOPQRSTUVWXYZ1234567890.,*_-=+';
$key = '';
$c = strlen($ch) - 1;
while (strlen($key) < $n){$key .= $ch[mt_rand(0,$c)];}
return $key;


$md_p = md5(sha1($p));

получаю в бд
log                      pass                   salt
CerG      22e9cd68b6e09804e25c8a857d08a1a0      N+gGm


/* Получаем Id, под которым юзер добавился в базу */
$id = mysql_result(mysql_query("SELECT LAST_INSERT_ID()", $db), 0);

// Отправляю письмо со ссылкой на активацию
$key = G_s ().$md_p;
$message.='<br/>http://www.xxx.ru/reg.php?id='.$id.'&amp;key='.$key.'<br/>';

получаю ссылку типа...
.php?id=36&key=xa1HC3049a1f0f1c808cdaa4fbed0e01649 b1


юзер по ссылке приходит на страницу активации в ней форма
введите ваше имя..получаем
$id=$_GET['log']; // 36
$ key=$_GET['key']; // N+gGm22e9cd68b6e09804e25c8a857d08a1a0

$repit_log=$_POST['login']; // CerG

выбираем из бд значение salt где $id=36
производим сравнение
$ key==$row['salt'].md5(sha1($_POST['log']));
если все нормально то регистрируем..


есть ли по этому какие-то мысли ???

  Ответить  
 
 автор: Trianon   (20.01.2009 в 21:00)   письмо автору
 
   для: serjinio   (20.01.2009 в 20:51)
 

Я так и не понял, где считается $p.... и зачем в письме светить id

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

Вы полагаете, что если пять раз повторите mt_rand() - её результат случайнее станет? Отнюдь.

Пожалуй с мыслями всё.

  Ответить  
 
 автор: serjinio   (20.01.2009 в 21:15)   письмо автору
 
   для: Trianon   (20.01.2009 в 21:00)
 

$p=$_POST['login'];

  Ответить  
 
 автор: Axxil   (21.01.2009 в 10:53)   письмо автору
 
   для: Trianon   (20.01.2009 в 21:00)
 

Псевдослучайные генераторы в php вообще весёлая штука, как показывают исследования

http://www.xakep.ru/post/46797/default.asp

  Ответить  
 
 автор: Trianon   (21.01.2009 в 11:39)   письмо автору
 
   для: Axxil   (21.01.2009 в 10:53)
 

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

Семейство функций rand изначально разрабатывалось вовсе не для того , чтобы получить одно случайное число, а для генерации последовательностей с приличной статистикой. И уж точно не для криптологических целей.

А что до microtime(), то источник-то идеологически правильный, если его всякими srand() не портить.
Но, понятное дело, слабенький - достаточное количество бит из него выжать тяжело.

  Ответить  
 
 автор: Николай2357   (21.01.2009 в 11:58)   письмо автору
 
   для: Trianon   (21.01.2009 в 11:39)
 

>То, что понемножку хорошего в криптологии оборачивается в конечном итоге крахом, предпочитают не думать. Как Николай здесь.
Я предпочитаю думать не о том, как сделать код абсолютно криптостойким, вероятно это в принципе не возможно, а о том, что бы какими то другими мерами отбить охоту даже пытаться расшифровать информацию. Ведь согласитесь, если после трех неудачных попыток изменить этод код и начать процедуру сначала, вряд ли у кого возникнет идея использовать всяческий брутфорс и иже с ним.

  Ответить  
 
 автор: Trianon   (21.01.2009 в 12:05)   письмо автору
 
   для: Николай2357   (21.01.2009 в 11:58)
 

Если делать эти попытки руками - да. Если скриптом - отнюдь.
Но отповедь моя не конкретно на тему активации, а вообще на отношение к.

  Ответить  
 
 автор: Николай2357   (21.01.2009 в 12:19)   письмо автору
 
   для: Trianon   (21.01.2009 в 12:05)
 

>Если делать эти попытки руками - да. Если скриптом - отнюдь.
Вынужден не согласиться. Может Вы не заметили в примере моего кода вот этой строчки:
<?
sleep
(3);

>Но отповедь моя не конкретно на тему активации, а вообще на отношение к.
А мои рассуждения как раз именно про оптимизации данной проблемы. То есть во главу угла поставлена не криптостойкость особонезначимого кода, а надежность защиты другими, более радикальными мерами. А по откношению к вопрос другой, там разумеется и совсем другой подход.

  Ответить  
 
 автор: Trianon   (21.01.2009 в 12:33)   письмо автору
 
   для: Николай2357   (21.01.2009 в 12:19)
 

>>Если делать эти попытки руками - да. Если скриптом - отнюдь.
>Вынужден не согласиться. Может Вы не заметили в примере моего кода вот этой строчки: sleep(3);

Я заметил другое. Строка эта никогда не выполнится потому,
if($_SESSION['count'] > 3)

что $_SESSION['count'] никогда не будет определено.

Какой же дурак будет передавать идентификатор сессии в скрипт такой проверки?

  Ответить  
 
 автор: Николай2357   (21.01.2009 в 12:45)   письмо автору
 
   для: Trianon   (21.01.2009 в 12:33)
 

>Я заметил другое. Строка эта никогда не выполнится потому,
Вы не заметили еще и этого в следующем моем посте:

>Вообще я понимаю, что можно и заголовок подделать, чтоб сессию обнулить. Это просто принцип.
Я не говорил, что это рабочий код, я говорил про принцип, а сессия - первое что пришло на ум для наглядности. Но сам то принцип ограничения числа попыток имеет право на жизнь?
Мне всё таки этот способ кажэтся более надежным, нежели повышение криптостойкости.

  Ответить  
 
 автор: Trianon   (21.01.2009 в 12:12)   письмо автору
 
   для: Николай2357   (21.01.2009 в 11:58)
 

Вот Вам пример последствий неряшливого отношения.
Автор скрипта активации применяет rand(0 при генерации крипточувствительной информации.
Владелец сайта, приделывает ко всем страницам (через php_prepend или руками) какую-нибудь рекламную фигню, в коде которой тоже применяется rand() , значение которого напрямую вылезает в URLе баннера.
И всё. Текущее состояние генератора rand() открыто. Следующее, которое идет в генерацию ключа - вычисляется безо всякого подбора. Не нужны три попытки.

Вы скажете - а не приделывай всякую фигню.
А я скажу - верно. Но возлагать вину на владельца сайта (а не автора скрипта) мне было б совестно.

  Ответить  
 
 автор: Николай2357   (21.01.2009 в 12:30)   письмо автору
 
   для: Trianon   (21.01.2009 в 12:12)
 

>Следующее, которое идет в генерацию ключа - вычисляется безо всякого подбора. Не нужны три попытки.
Да, но есть ведь еще параметр, кроме rand(), и к тому же хэш. Всё же некоторые усилия потребуются. Я и клоню к тому, что бы сделать эти усилия экономически невыгодными.

  Ответить  
 
 автор: Trianon   (21.01.2009 в 13:03)   письмо автору
 
   для: Николай2357   (21.01.2009 в 12:30)
 

>>Следующее, которое идет в генерацию ключа - вычисляется безо всякого подбора. Не нужны три попытки.
>Да, но есть ведь еще параметр, кроме rand(),
id пользователя известен.
unixtime известен.

>и к тому же хэш.
так а что хеш? Хеш ведь по ним вычисляется, а не наоборот?

  Ответить  
 
 автор: Николай2357   (21.01.2009 в 13:23)   письмо автору
 
   для: Trianon   (21.01.2009 в 13:03)
 

>id пользователя известен.
Oткуда? Это же новый, неактивированный пользователь... Другое дело, что он может быть вычислен с помощью разных ухищрений. А на это вычисление как раз и понадобятся усилия. Можно конечно зарегистрировать первого пользователя руками и подставить следующий id в скрипт, но это как раз и есть экономическая нецелесообразность. Вариант не идеальный, но вполне оправданный. Нужно ведь сначала вычислить алгоритм формирования этого хэша (если конечно это не открытый код). А можно ведь так:
<?
$code 
= (rand() % == 0)?md5($id.rand()):md5(rand().$id());
Уникальность не пострадает...

  Ответить  
 
 автор: Trianon   (21.01.2009 в 13:29)   письмо автору
 
   для: Николай2357   (21.01.2009 в 13:23)
 

Новый. Но число пользователей обычно известно, так что спрогнозировать номер следующего - не задача.
А даже если известно, то из серии можно пожертвовать одним живым емэйлом (т.е. создать одного пользователя честно) , остальные пойдут по нарастанию.

$code = (rand() % 2 == 0)?md5($id.rand()):md5(rand.$id());

Ввот эта страшная на первый взгляд конструкция основана на том, что очередное значение rand() - неизвестно. А в моем примере оно известно - см. предыдущий ответ.

  Ответить  
 
 автор: Trianon   (21.01.2009 в 13:32)   письмо автору
 
   для: Trianon   (21.01.2009 в 13:29)
 

Заметьте, Николай, Вы спорите уже просто по инерции.
А замените rand() на microtime() и всё. Уязвимость уйдет.

  Ответить  
 
 автор: Николай2357   (21.01.2009 в 13:40)   письмо автору
 
   для: Trianon   (21.01.2009 в 13:32)
 

>Заметьте, Николай, Вы спорите уже просто по инерции.
Нет, я вовсе не спорю, я хочу разобраться до конца. А разве microtime() на много сложнее вычислить, зная время запуска скрипта? Все равно с 10, 20, 100-й попытки можно угадать, если дать возможность угадывать... Конечно microtime() лучше в данном контексте, глупо спорить. Но я всё таки не это имею ввиду, а сам принцип построения защиты.

  Ответить  
 
 автор: Axxil   (21.01.2009 в 13:55)   письмо автору
 
   для: Николай2357   (21.01.2009 в 13:40)
 

Если есть ссылка, то рано или поздно тупым брутфорсом точно можно активировать аккаунт.

Но если ввести пару id - хеш и ограничить число попыток активации для данного id одним разом, то проблема просто перестанет существовать при любой функции составления кода активации.

Причём, понятно, что открытый id должен вычисляться непредсказуемо (не тупо последовательные целые числа), чтоб злоумышленник не смог превентивно убить все эти активационные ссылки.

  Ответить  
 
 автор: Trianon   (21.01.2009 в 14:05)   письмо автору
 
   для: Axxil   (21.01.2009 в 13:55)
 

>ограничить число попыток активации для данного id одним разом,

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

  Ответить  
 
 автор: Axxil   (21.01.2009 в 14:09)   письмо автору
 
   для: Trianon   (21.01.2009 в 14:05)
 

> Это жестко
почему?

Пользователю достаточно кликнуть по правильной ссылке, чтобы попытка засчиталась.

Я не могу представить ситуации, когда пользователю понадобится менять код ссылки (разве что когда в почтовом редакторе ссылки иногда бьются).

Но в таком случае обычно пишется про "скопируйте ссылку целиком в строку браузера".

Тогда 2-3 попытки. Точно хватит. Если нет, то contact support :)

> А смысл нашего спитча в том, что если хеш вычислим на основании известных данных, то даже это ограничение не спасет.

Если он 100% вычислим в пределах 2-3 попыток, тогда да. Но наличие в коде даже функции rand, даёт очень мало шансов на это, при условии что ещё надо id подобрать.

  Ответить  
 
 автор: Trianon   (21.01.2009 в 14:15)   письмо автору
 
   для: Axxil   (21.01.2009 в 14:09)
 

>Тогда 2-3 попытки. Точно хватит. Если нет, то contact support :)
в принципе - да. Порядка этого.

>> А смысл нашего спитча в том, что если хеш вычислим на основании известных данных, то даже это ограничение не спасет.
>
>Если он 100% вычислим в пределах 2-3 попыток, тогда да. Но наличие в коде даже функции rand, даёт очень мало шансов на это, при условии что ещё надо id подобрать.

Ну вот я привел пример в 21.01.2009 в 12:12 .

  Ответить  
 
 автор: Axxil   (21.01.2009 в 14:53)   письмо автору
 
   для: Trianon   (21.01.2009 в 14:15)
 

Ну это на словах легко :)

Предлагаю тест. Максимально просто для начала.

http://www.kazuals.ru/test/test.php

Здесь показывается сгенерированное случайное число в каком-то диапазоне.

Потом генерируется хеш для случайного числа:

echo md5(rand())


и записывается в секретный файл.

Далее. Тут предлагается этот самый хеш ввести:

http://www.kazuals.ru/test/test1.php

Одна попытка, если хеш неугадан, то файл стирается и всё сначала.

Задача: скопировать сюда фразу, которая выводится при удачном решении.

PS. Детям: просьба скриптами не ддосить. Это просто тест.

  Ответить  
 
 автор: Trianon   (21.01.2009 в 14:57)   письмо автору
 
   для: Axxil   (21.01.2009 в 14:53)
 

>Ну это на словах легко :)
Понятно, что на деле сложнее.
Так за дело и деньги платят :)

  Ответить  
 
 автор: Axxil   (21.01.2009 в 15:10)   письмо автору
 
   для: Trianon   (21.01.2009 в 14:57)
 

Тогда вопрос снят :)

Просто у вас это звучало так, как будто это слишком просто. Вот я и засомневался, может на самом деле это раз плюнуть :)

  Ответить  
 
 автор: Николай2357   (21.01.2009 в 15:58)   письмо автору
 
   для: Axxil   (21.01.2009 в 15:10)
 

Жалко что снят, я хотел повозиться...
Не могу я успокоится. Вот попробовал посчитать microtime(). Если кому интересно, вот так:
<? 
session_start
();
/*unset($_SESSION['a']);
unset($_SESSION['b']);
exit();*/
$_SESSION['a'] ++;
$a microtime()."<br>";
//for($i=0;$i<100;$i++)
$e 1+1;
$b  microtime();
$c $a $b;
$d $_SESSION['b'];
if(!
in_array($c,$d))
$d[] = $c;
$_SESSION['b'] = $d;

echo 
count($_SESSION['b'])."<br>";
echo 
$_SESSION['a'];
Результаты не утешительны. Разброс без цикла
52/100
с циклом
59/100
что при такой погрешности одно и то же. Стоит ли говорить, что при увеличении числа попыток разброс увеличивается... Так что
>А замените rand() на microtime() и всё. Уязвимость уйдет.
вряд ли... Всё равно получается, что без ограничения числа попыток никуда не дется.

  Ответить  
 
 автор: BinLaden   (21.01.2009 в 16:34)   письмо автору
 
   для: Николай2357   (21.01.2009 в 15:58)
 

Николай, какой гениальный код. А что он делает?

  Ответить  
 
 автор: Николай2357   (21.01.2009 в 17:49)   письмо автору
 
   для: BinLaden   (21.01.2009 в 16:34)
 

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

  Ответить  
 
 автор: Николай2357   (21.01.2009 в 17:50)   письмо автору
 
   для: BinLaden   (21.01.2009 в 16:34)
 

-

  Ответить  
 
 автор: Николай2357   (21.01.2009 в 17:50)   письмо автору
 
   для: BinLaden   (21.01.2009 в 16:34)
 

-

  Ответить  
 
 автор: Trianon   (21.01.2009 в 17:58)   письмо автору
 
   для: Николай2357   (21.01.2009 в 17:50)
 

дату-время в Unix-формате, уже предлагавшуюся здесь альтернативой, вполне можно и спрогнозировать.
Что до microtime() - задача понятна, но всё ж сперва может поглядеть, что возвращает эта функция, а потом уже писать код?

  Ответить  
 
 автор: Николай2357   (21.01.2009 в 18:19)   письмо автору
 
   для: Trianon   (21.01.2009 в 17:58)
 

Каюсь, грешен... Единичку забыл. Но результат не многим лучше С рефрешем - минута работы - 24 совпадения.

  Ответить  
 
 автор: Trianon   (21.01.2009 в 18:21)   письмо автору
 
   для: Николай2357   (21.01.2009 в 18:19)
 

Вы не учитываете время на прохождение запроса от клиента на сервер.
не факт, что оно будет таким стабильным
Но в принципе, Вы правы.
Почему я и написал, что сильно много случайных бит из этого источника не выжать.

  Ответить  
 
 автор: Николай2357   (21.01.2009 в 17:55)   письмо автору
 
   для: BinLaden   (21.01.2009 в 16:34)
 

Форум сегодня веселит не на шутку...

  Ответить  
 
 автор: Trianon   (21.01.2009 в 12:19)   письмо автору
 
   для: Axxil   (21.01.2009 в 10:53)
 

Переводчику этой статьи нужно выдернуть ... подставить по вкусу.
Я так понимаю, что строка "2-4. первое слагаемое (double) microtime() будет равно 0, либо 1, а второе — " в исходном смысле звучала как-то так:
2-4. первый множитель (double) microtime() находится в промежутке от нуля до единицы, а второй -

Такие ляпы серьезно подрывают доверие ко всему материалу. А жаль.

  Ответить  
 
 автор: Axxil   (21.01.2009 в 12:36)   письмо автору
 
   для: Trianon   (21.01.2009 в 12:19)
 

Это да... :(

Такие ненаучно-популярные издания как "Хакер" читают, в основном, брутально настроенные дети, так как и издаётся он для детей (не удивительно, раз издатель "геймланд"). А дети, как известно, в тонкости вникать не любят. Им надо готовый рецепт, который можно скопипастить. Поэтому особенно с переводами и не заморачиваются. Дети всё равно визжат от восторга.

Те кто действительно интересуется предметом сразу же идёт читать оригинал.

PS. Вообще, качество перевода у нас, к сожалению, в большинстве случаев ниже плинтуса. Так как профессионалов мало. А те кто переводят зачастую вообще не врубаются в то что переводят. Поэтому если хочешь быть в курсе событий, просто физически необходимо учить английский.

  Ответить  
 
 автор: Николай2357   (20.01.2009 в 21:04)   письмо автору
 
   для: serjinio   (20.01.2009 в 20:51)
 

Вот это делается проще:
<?
//$id = mysql_result(mysql_query("SELECT LAST_INSERT_ID()", $db), 0);
$id mysql_insert_id();
А вообще лично я ничего из этого не понял. Уникальности кода нет, вероятность подбора осталась...

  Ответить  
 
 автор: serjinio   (20.01.2009 в 21:13)   письмо автору
 
   для: Николай2357   (20.01.2009 в 21:04)
 

Добавил сравнение вверху..

  Ответить  
 
 автор: AcidTrash   (20.01.2009 в 22:22)   письмо автору
 
   для: serjinio   (20.01.2009 в 21:13)
 

Ключ генерируется случайным образом, не зависимо от всяких id, email и тд. Тобишь в генерации ключа эти параметры не учавствуют. При регистрации аккаунта, все записывается в бд и в поле для ключа записывается абсолютно составленный(рандомно) ключ(хешированный, возможно не один раз). А при активации сравнение идет по большому счету с ним.

  Ответить  
 
 автор: Николай2357   (20.01.2009 в 22:35)   письмо автору
 
   для: AcidTrash   (20.01.2009 в 22:22)
 

>Ключ генерируется случайным образом, не зависимо от всяких id, email и тд.
Вот тут хоть и ничтожно маленький, но все же элемент случайного совподения присутствует. Для этого и id, из за этого и сыр-бор.

  Ответить  
 
 автор: AcidTrash   (20.01.2009 в 22:44)   письмо автору
 
   для: Николай2357   (20.01.2009 в 22:35)
 

Вот тут хоть и ничтожно маленький, но все же элемент случайного совподения присутствует. Для этого и id, из за этого и сыр-бор.
Включить в составляющую рандома, например реальное время в UNIX - формате.

  Ответить  
 
 автор: Николай2357   (20.01.2009 в 23:40)   письмо автору
 
   для: serjinio   (20.01.2009 в 21:13)
 

А про автора и забыли совсем... Резюме. Вот четыре варианта генерации ключа.

Первый предложенный.
<?
$code 
md5($email.rand());


Недостатки:
1. Первый параметр ($email) за ранее известен спамеру, который попытается подобрать код активации
2. Этическая составляющая (вынос, хоть и сильно запрятанныой но все же, личной информации).

Второй:
<?
$code 
md5($id.rand());


Недостатки:
1. Вероятность подбора остается, хотя и меньше чем в первом варианте.

Третий:
<?
$code 
md5(date('U').rand()); 


Недостатки:
1. Вероятность подбора так же остается, так как время генерации кода можно плюс минус вычислить.
2. Если совсем придраться, то этот вариант еще и более ресурсоёмкий.

Собственно Ваш.
Недостатки:
1. Вероятность подбора остается, хоть и ничтожно мала.
2. Еще более ресурсоёмкий.
3. Решение неоптимально с точки зрения величины кода.
4. Самый большой недостаток - отсутствие уникальности и, как следствие, вынос на обзор информации - id.

Выводы.

1. Если использовать первые три варианта, то лучше воспользоваться функцией mt_rand();
<?
$code 
md5($id.mt_rand(5,15));

2. Для более эффективной защиты ограничить количество попыток активации.

Хотя это попахивает параноей, но мелочей не бывает, лучше сразу всё предусмотреть.
ИМХО.

  Ответить  
 
 автор: serjinio   (21.01.2009 в 01:25)   письмо автору
 
   для: Николай2357   (20.01.2009 в 23:40)
 

Вы пока тут спорили,я кое-что изменил..
переделал ф-цию ,на более стабильную

<?/* Функция получения Соли */
function G_s($n,&$keyy
{
$ch 'abcdefghijklmnopqrstuvwxyzABCDEFGHI JKLMNOPQRSTUVWXYZ1234567890';
$c strlen($ch) - 1;
while (
strlen($keyy) < $n){
$keyy .= $ch[rand(0,$c)];
}
return 
$keyy;
}
$keyy '';
G_s(5,$keyy);
echo 
'<br>G_s-+-'.$keyy;

$key $keyy.$md_p;

поменял

//$md_p = md5(md5($p));
на
$md_p = md5(sha1($p));

Выкинул с сылки ID получилось типа
.php?key=hFpIf6ddc6b3660d35b640095d068c339cc 7f

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


<?
if (isset($_GET['key'])){ 
echo 
'
Введте свой логин выбранный при регистрации .
<form action="'
.$_SERVER['PHP_SELF'].'" method="post">
<input name="login" type="text" size="37" />
<input name="key" type="hidden" value="'
.trim($_GET['key']).'" />
<input name="ok" type="submit" value="Подтвердить !" id="ok" />
</form>'
;
}
if (isset(
$_POST['ok']))

/* Устанавливаем соединение с БД */
include_once ('../config.php');//сonnect BD
/* Формируем SQL-запрос */
$SQL=mysql_query("SELECT `u_log`,`u_salt`,`u_pass`
FROM `users` 
WHERE `u_log`='"
.trim($_POST['login'])."'",$db);
$rw mysql_fetch_assoc($SQL);
if ((
$rw['u_salt'].$rw['u_pass']) == (trim($_POST['key'])))
echo 
'<br>Ну и ну...Имя настоящее ...! 
делаем дальше проверки.. 
подтвержден ли данный логин ..
не истёкли срок активации ....
если все ОК пишем в базу..
если нет удаляем его из базы и пусть идет по новой... !<br>'
;
}

писал на скорую руку без проверок вх. переменных..ну как идея???

  Ответить  
 
 автор: Николай2357   (21.01.2009 в 08:29)   письмо автору
 
   для: serjinio   (21.01.2009 в 01:25)
 

Ну давайте опять всё по порядку.
Во первых, что бы получить случайную строку из пяти символов, не обязательно столько телодвижений. Всё гораздо проще:
<?
$ch 
'abcdefghijklmnopqrstuvwxyzABCDEFGHI JKLMNOPQRSTUVWXYZ1234567890';
echo 
substr(str_shuffle($ch),58);

Во вторых, это практически не активация учетной записи, а временный пароль.
Идея не плоха, к тому же это не велосипед.
Лично мне всё таки больше импонирует система автоматической активации, что бы прошел по ссылке из письма, и в дамках.

  Ответить  
 
 автор: serjinio   (21.01.2009 в 11:31)   письмо автору
 
   для: Николай2357   (21.01.2009 в 08:29)
 

Согласен,сейчас подумаю как все-таки сделать одной ссылкой

  Ответить  
 
 автор: serjinio   (22.01.2009 в 01:58)   письмо автору
 
   для: serjinio   (21.01.2009 в 11:31)
 

Ну вот добрался до комьютера...
вариант активации одной ссылкой с одним параметром....
<?
/* Соль */
// воспользовался кодом Николая....
$r_keysubstr(str_shuffle('abcdef0123456789'),11);// Создадим код "Соли" того-же вида, что и md5-хэш 
/* В базе данных у нас будет храниться md5-хеш пароля */
$p  =$_POST['pass'];
$md_p md5(sha1($p));

mysql_query("INSERT INTO `users` (`u_log`,`u_pass`,`u_salt`,  ............VALUES ( '$r_key',......'$md_p')",$db);
if (
$new == 'true')
{
/* Составляем "Ключ" для активации */
$u_key $md_p.$r_key;
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Получаем ссылку на активацию
//  .php?key='.$u_key.'" target="_blank">АКТИВИРОВАТЬ !</a>
//  .php?key=c72f5359811af711f29b1fac7150042fed3 72
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Активируем.....

if (isset($_GET['key']))
{
/* Устанавливаем соединение с БД */
include_once ('../config.php');//сonnect BD
// Вырезаем соль...
$saltsubstr(trim(htmlspecialchars($_GET['key'],ENT_QUOTES,'UTF-8')),32);  // ed372

/* Формируем SQL-запрос */
$SQL=mysql_query("SELECT `u_log`,`u_salt`,`u_pass`,`u_activat`
FROM `users` 
WHERE `u_salt`='
$salt'  AND `u_activat` = 0 ",$db);
if (
mysql_num_rows($SQL) > )
{
$rw mysql_fetch_assoc($SQL);

echo 
'<br>Есть такой юзер..'.$rw['u_log'].' ! делаем дальше проверки.. 
был ли уже активирован данный логин ..
не истёкли срок активации ....
если все ОК пишем в базу..
если нет удаляем его из базы и пусть идет по новой... !<br>'
;
}


Длину соли можно сделать любую,вставить ее можно и в начало и в конец и хоть в середину .
она все равно выглядит как и код md5.....как фантазия работает.....
вроде работает..утром еще нормально протестирую...
..самое главное идея.. что скажите ..какие могут быть подводные камни...

  Ответить  
 
 автор: Николай2357   (22.01.2009 в 02:38)   письмо автору
 
   для: serjinio   (22.01.2009 в 01:58)
 

>какие могут быть подводные камни...
Вернее было бы сказать - где тут вода, и есть ли она под камнями....
Если завтра будет время, я перепишу Ваш код, это проще будет, чем поэтапно объяснять.

  Ответить  
 
 автор: Николай2357   (22.01.2009 в 13:48)   письмо автору
 
   для: serjinio   (22.01.2009 в 01:58)
 

Ну вот, я добрался до компа.
Ваши основные ошибки:
1. Вы пытаетесь усложнить жизнь хакеру, спрятав за "непроницаемую" стену пароль юзера. Скажите - зачем? Ведь суть задачи дать возможность активировать запись только тому, кто знает ключ к активации, а пароль юзер знает лучше Вас, и в ответном письме он ему совсем не нужен. Чего нельзя сказать о злоумышленнике, перехватившем это письмо каким нибудь хитрым трояном. Задача заключается в двух главных моментах.
а) Исключить возможность активации записи методом подбора или расшифровки кода.
б) Идентифицировать пользователя по этому самому коду.
По первому пункту. Есть два пути - генерация случайного кода, что оказалось не так уж и просто, и ограничение числа попыток активации. Я склоняюсь ко второму, но если хотите первый - пожалуйста.
Что бы потерялся смысл расшифровки, нужно сгенерировать действительно случайную строку, которую нельзя дешифровать, вычислив некоторые параметры. Лучшим способом, как выяснилось, является генерацуия на основе не псевдослучайных параметров, а на действительно случайных. Раз уж муссировался вопрос о функции microtime(), то вот так можно сгенерировать случайную строку, похожую на хэш:
<?
// Массив можно заполнить статически, просто жалко места и лень.
$arr_num range("0","9");
$arr_let range("a","f");

$arr array_merge($arr_num,$arr_let);
$arr array_merge($arr,$arr_let);
$arr array_merge($arr,$arr_num);
$arr array_merge($arr,$arr_let);
$arr array_merge($arr,$arr_let);
$arr array_merge($arr,$arr_let);
$arr array_merge($arr,$arr);

$rand microtime(1);
for(
$i 0$i 32$i++)
{
$key .= $arr[(round(($rand 1000 floor($rand 1000)),2) * 100 )];
$rand microtime(1);
}
echo 
$key;
Но эта процедура не даст гарантии уникального кода, а для чистоты эксперимента он должен быть уникальным. По этому нужен параметр, который не повторится ни при каких обстоятельствах. Идеальным является id записи. А так как смысла расшифровки кода нет, то можно процедуру упростить.

<?
mysql_query
("INSERT INTO `users`..."
$id =  mysql_insert_id();
$arr_num range("0","9");
$arr_let range("a","z");

$arr array_merge($arr_num,$arr_let);
$arr array_merge($arr,$arr);
$arr array_merge($arr,$arr_let);
$arr[] = "a";

$rand microtime(1);
for(
$i 0$i 10$i++)
{
$key .= $arr[(round(($rand 1000 floor($rand 1000)),2) * 100 )];
$rand microtime(1);
}


$r_keymd5($id.$key);
mysql_query("UPDATE....... (...`r_key`,  ............VALUES ( ...'$r_key',....')",
// Отправляем письмо
В результате мы имеем уникальный и не поддающийся подбору хэш, по которому и можно идентифицировать юзера:
<?
$key 
= isset($_GET['key']):$_GET['key']?null;
if(
$key)
{
$key = (get_magic_quotes_gpc())?mysql_escape_string(stripslashes($key)):mysql_escape_string($key);
$SQL=mysql_query("SELECT `u_log`,`u_salt`,`u_pass`,`u_activat` 
FROM `users`  
WHERE `r_key`='
$key'  ",$db);

if (
mysql_num_rows($SQL) > 

$rw mysql_fetch_assoc($SQL); 

echo 
'<br>Есть такой юзер..'.$rw['u_log'].' ! делаем дальше проверки..  
был ли уже активирован данный логин .. 
не истёкли срок активации .... 
если все ОК пишем в базу.. 
если нет удаляем его из базы и пусть идет по новой... !<br>'

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

  Ответить  
 
 автор: Trianon   (22.01.2009 в 16:21)   письмо автору
 
   для: Николай2357   (22.01.2009 в 13:48)
 

>Раз уж муссировался вопрос о функции microtime(),

В аспекте разового вызова, но никак не повторения в цикле.
Понятно, что никакой случайной составляющей повторные вызовы не привнесут.

  Ответить  
 
 автор: Николай2357   (22.01.2009 в 17:09)   письмо автору
 
   для: Trianon   (22.01.2009 в 16:21)
 

Почему? я проверял, разница есть и вполне существенная. Две последних цифры очень даже прилично скачут.

  Ответить  
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования