Javascript-форум (https://javascript.ru/forum/)
-   Серверные языки и технологии (https://javascript.ru/forum/server/)
-   -   Безопасность в PHP (https://javascript.ru/forum/server/27761-bezopasnost-v-php.html)

Diego 23.04.2012 23:25

Безопасность в PHP
 
Уже довольно долго ищу в интернете на эту тему, но в основном пишут статьи про иньекции и xss
Дайте, пожалуйста, ссылки на более полные статьи по безопасности php. Я пишу свою CMS, не хотелось бы чтобы ее взломали в первый же день после запуска сайта :-?

devote 23.04.2012 23:42

пишите аккуратно, проверяйте переменные, используйте встроенные возможности экранирования переменных, в мускуль не суйте значения как это делают многие "`hehe`='$lala'" пишите так как требуется, не юзайте eval и тогда вас сложно будет сломать.

Serg_pnz 23.04.2012 23:45

Принцип один: не доверяйте данным, пришедшим с клиента и будет Вам ЩАСТЬЕ!
Т.е. если ожидается число - intval, строка - хм... ну заслешить кавычки, убрать теги, потереть неожидаемые символы, к примеру $ & #
Не делать eval в скриптах...
Как-то так.

Diego 24.04.2012 00:53

Спасибо за советы! :)

Если с eval в php всё ясно, то почему многие не советуют использовать eval в javascript? Тут уж в любом случае ясно, какие данные придут в скрипт. Конечно если не допускать совсем очевидных ошибок и вставлять в eval вывод нефильтрованых данных от пользователя.

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

devote 24.04.2012 00:59

Цитата:

Сообщение от Diego
то почему многие не советуют использовать eval в javascript?

потому что eval в JavaScript безопасен, но многие этого не понимают, услышали проблемы в серверной стороне и боятся юзать его теперь везде, но он не может навредить данным на сервере, это уже проблемы пользователя а не владельца сайта, если юзер ходит по порно сайтам и ловит всякую тварь, то тут никакое переставание использования eval'a не поможет. А для сервера eval критично, так как это может навредить данным на сервере или серверу.

micscr 24.04.2012 08:27

Что значит не использовать eval на сервере? Для пользовательских данных не использовать, для админских использовать.

Diego, твою цмс вряд ли кто то прям так ринется сразу ломать, только если ты очевидно не наплужил с тем же xss. PDO юзаешь?
Насчет безопасности глянь тут.
еще сразу что в голову пришло:
1) тексты пых скриптов пиши без завершающего ?>
2) csrf.
3) Пользовательские формы помечай маркером, что это форма сайта.
4) Прогугли про общую доступность файлов сессий на виртуальных хостингах, соответственно авторизацию продумай.

B@rmaley.e><e 24.04.2012 09:52

Плюсую про PDO. Все запросы делать только с prepared statements'ами.

Diego 24.04.2012 13:48

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

Касательно авторизации - не использую сессии, ставлю две cookie, один с ID пользователя, второй со случайным набором символов, который меняется с каждой авторизацией. Эти символы привязываются к пользователю и его IP, то есть при краже куки злоумышленник всё равно не сможет зайти - его IP отличается от того, что записан в БД. Единственный минус - с изменением IP происходит разлогин, как можно этого избежать? Есть ли другие безопасные способы авторизации?
PS:про этот способ узнал на хабрахабре: http://habrahabr.ru/post/13726/

micscr 24.04.2012 14:35

Цитата:

Сообщение от Diego (Сообщение 170928)
PDO не использую, никогда с ним не сталкивался. Посмотрел в вики, через это дополнение проходят все запросы в бд, то есть он автоматически фильтрует все входные данные?

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

Странная у тебя цмс, где ты сессии не используешь. :-?

devote 24.04.2012 14:52

Цитата:

Сообщение от micscr
1) тексты пых скриптов пиши без завершающего ?>

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

Цитата:

Сообщение от micscr
Странная у тебя цмс, где ты сессии не используешь.

да я о том же... чем стандартные PHP'шные сессии не угодили, понять сложно.

Diego 24.04.2012 15:12

Цитата:

Сообщение от micscr (Сообщение 170939)
Странная у тебя цмс, где ты сессии не используешь. :-?

Не люблю кашу в ссылках. Да и хранить переменные в сессии мне особо не надо, пока не встречалось таких задач в которых жизненно важно использовать сессии.
В любом случае сессии будут работать через куки, тогда зачем вообще включать сессии если можно использовать куки для идентификации пользователя. Сессии не будут работать через куки только если куки отключены, а они отключены по данным разных статистик от 0.5 до 3% пользователей, которые знали на что идут, когда отключали эти самые куки :)
Но я полностью не отрицаю вариант авторизации с сессиями, просто пока удобнее работать с куками, может в будущем все таки перейду на сессии.

Но вопрос не в этом. Сейчас у меня сайт на укозе(собственно, именно из-за этого и пишу cms), и пользователи часто жалются что им надо каждый день логинится заново. А IP, потому как динамический, будет каждый день менятся и разлогинивать пользователя, поэтому я сейчас думаю над тем, как иными способами закрепить профиль пользователя за конкретным компом. Пока думаю "метить" пользователя, согласно этой статье http://javascript.ru/unsorted/id , по крайней мере заголовки много полезных данных содержат.
И напрашивается вопрос - как держать логин пользователя безопасным способом без привязки к IP?

Цитата:

Сообщение от devote (Сообщение 170943)
А еще не забывать о том что многие редакторы любят совать BOM который тоже иногда приводит к ошибкам.

Ну это совсем уж детские ошибки(всмысле, сохранить в неправильной кодировке). Тем более во многих редакторах можно сразу при создании документа менять кодировку, например в Notepad++

devote 24.04.2012 15:33

Цитата:

Сообщение от Diego
Тем более во многих редакторах можно сразу при создании документа менять кодировку, например в Notepad++

речь не о кодировке.. Редакторы добавляют BOM в тех случаях если вы файл сохраняете в кодировке UTF-8 что чаще всего на сегоднящний день все и используют.

devote 24.04.2012 16:02

Если таблица юзера в БД примерно такая:

CREATE TABLE IF NOT EXISTS `users` (
  `id` int(15) NOT NULL AUTO_INCREMENT,

   // логин пользователя
  `username` varchar(255) NOT NULL,
   // пароль пользователя в md5 формате
  `password` varchar(32) NOT NULL,
   // некий md5 хеш для проверки авторизации юзера
  `passkey` varchar(32) NOT NULL,

   // NULL если не заблокирован, иначе время в формате unix timestamp указывающую дату блокировки
  `blocked` int(15) unsigned DEFAULT NULL,

   // NULL если не активирован аккаунт, иначе время в формате unix timestamp указывающую дату активации
  `activated` int(15) unsigned DEFAULT NULL,

  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


То можно сделать примерно такой вариант:
function check_user_auth() {

	if ( isset( $_COOKIE['ruirm'] ) ) {

		$sql_result = mysql_query( "SELECT COUNT(*) FROM `users` ".
				"WHERE md5(CONCAT(`passkey`, md5(`id`), md5(`username`), md5(`password`)))='".
				mysql_real_escape_string( $_COOKIE['ruirm'] )."' ".
				"AND ISNULL(`blocked`) ".
				"AND NOT ISNULL(`activated`);"
		);

		if ( mysql_num_rows( $sql_result ) > 0 ) {

			SetCookie( "ruirm", $_COOKIE['ruirm'], time() + 60*60*24*30*12*5 );

			return true;

		} else {
			SetCookie( "ruirm", '', time() + 60*60*24*30*12*5 );
		}
	}

	return false;
}

if ( check_user_auth() ) {
	echo "Пользователь авторизован!";
} else {
	echo "Пользователь не авторизован!";
}
Но без использования сессий, это критично для БД.

После авторизации в куку значение ruirm генерить так:
SetCookie("ruirm",
	md5( $user['passkey']. // текущее значение passkey из БД
	md5( $user['id'] ). // Id пользователя в БД
	md5( $user['username'] ). // логин пользователя
	md5( $user['password'] ) ), // хешпароль пользователя в БД
	time() + 60*60*24*30*12*5  // сохраним на пять лет :)
);
где переменная $user содержит данные пользователя из БД

Если пользователь сменит пароль, во всех браузерах где он был авторизован слетит авторизация, так же можно добавить у пользователя в аккаунте кнопочку, "Выйти из всех браузеров" после нажатия на которую меняем passkey на какой-нить другой. Генерация этого passkey может быть любая, на ваш вкус. Но менять ее может лишь юзер который жмакнул кнопку "Выйти из всех браузеров". Или сервак может сменить например при блокировании юзера что бы он вылетел со всех браузеров и т.д.

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

Раед 24.04.2012 16:31

Много вы тут про сессии говорите. А можно ссылку - глянуть, что это и как реализуется

micscr 24.04.2012 17:23

Цитата:

Сообщение от devote
Уж неужто вычитали где-то что это влияет на безопасность?

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

Diego 24.04.2012 17:23

Цитата:

Сообщение от devote (Сообщение 170961)
$sql_result = mysql_query( "SELECT COUNT(*) FROM `users` ".
"WHERE md5(CONCAT(`passkey`, md5(`id`), md5(`username`), md5(`password`)))='".
mysql_real_escape_string( $_COOKIE['ruirm'] )."' ".
"AND ISNULL(`blocked`) ".
"AND NOT ISNULL(`activated`);"
);

то есть как ответ из бд вернутся не данные, а количество строк, в которых сумма хешей совпадает данным из куки?
Цитата:

Сообщение от devote (Сообщение 170961)
Если юзать сессии, то тогда не нужно будет постоянно обращаться в БД, а лишь один раз в случае если в сессии нет инфы об авторизации юзера.

тогда буду использовать сессии :)

Цитата:

Сообщение от devote (Сообщение 170961)
Генерация этого passkey может быть любая, на ваш вкус.

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

Цитата:

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

http://www.php.su/articles/?cat=examples&page=070

micscr 24.04.2012 17:24

сессии

micscr 24.04.2012 17:30

Цитата:

Сообщение от Diego
Не люблю кашу в ссылках

А такая ссылка и не нужна. Сессии через куки работают, а автоподстановку в адреса и формы(получаются некрасивые адреса) обычно не включают.

Раед 24.04.2012 17:52

Цитата:

Сообщение от micscr
сессии

Спасибо, почитал

devote 24.04.2012 17:57

Цитата:

Сообщение от Diego
значит, что всю безопасность обеспечивает passkey?

Нет конечно, он лишь подтверждает то что юзер когда-то залогинелся. А если злоумышленник узнает passkey то он ему совершенно ничего не даст, так как помимо этого нужно знать и пароль пользователя и логин пользователя и ID пользователя в БД.. потому как все это связано между собой и любое изменение этих параметров приведет к тому что юзер вылетит из сайта, со своего аккаунта и ему придется авторизоваться снова.

Цитата:

Сообщение от Diego
то есть как ответ из бд вернутся не данные, а количество строк, в которых сумма хешей совпадает данным из куки?

Да, но хеш код уникален, поэтому всегда будет возвращаться лишь одна строка если совпадение найдено, либо не одной если не найдено.

Цитата:

Сообщение от Diego
Если у злоумышленника сгенерированый по данным его компа passkey не совпадет с passkey пользователя, то защита работает?

не переживайте через эту систему ему вечность ломать придется вас

Diego 24.04.2012 18:09

Цитата:

Сообщение от devote (Сообщение 171005)
не переживайте через эту систему ему вечность ломать придется вас

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

Спасибо за метод, дополню свою CMS с учетом ваших советов!


Часовой пояс GMT +3, время: 20:08.