Pull to refresh

Comments 54

Абсолютно ничего нового.

Не согласен! А как же вот это в статье!? ->
проверяйте дважды все данные

Теперь всегда буду делать так:
if (empty($post_data)) { echo 'hacker?'; } if (empty($post_data)) { echo 'hacker?'; }
Все буду дважды проверять… :)
Я думаю вы придираетесь к словам, т.к. в контексте смысл выражения понятен.
oENDark, Вы что, это же шутка…
Полностью с Вами согласен, потому и привел этот шутейный код, докопавшись до слов ТС о том, что все нужно проверять дважды :)
Новые ошибки в русском языке.
А, не. Старые.
с генерированными символами, то можете не беспокоиться (пример: 7NVmE10SaJ.php)
Привет ненастроенный robots.txt. Не забывайте, что браузеры тоже следят за вашими перемещениями и передают данные куда надо.
(кроме windows конечно, там само ядро сплошная дыра).
Ума не хватило, чтобы настроить?

Да и сами советы в статье стары как мир.
Я уже давно и забыл про коварный mysql_real_escape_string. Пользуйтесь PDO.
Кстати интересно, что PDO страдает той же проблемой что и addslashes() при использовании некоторых мультибайтовых кодировок (т.е. некорректно экранирует символы и дает провести инъекцию):

<?php
// argv[1] - mysql charset
// argv[2] - id for select
$db = new PDO("mysql:host=localhost;dbname=testdb", "root", "", array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES ' . $argv[1]));
$statement = $db->prepare("SELECT * FROM lists WHERE id = ?");
$statement->execute(array($argv[2]));
echo "Returned rows: ", $statement->rowCount(), "\n";
?>


vos@ctfsu ~/t $ php pdo_test.php utf8 1
Returned rows: 1
vos@ctfsu ~/t $ php pdo_test.php utf8 -1
Returned rows: 0
vos@ctfsu ~/t $ php pdo_test.php utf8 "1'||1#"
Returned rows: 1
vos@ctfsu ~/t $ php pdo_test.php gbk "1'||1#"
Returned rows: 1
vos@ctfsu ~/t $ php pdo_test.php gbk `echo -ne "1\xbf'||1#"`
Returned rows: 12


Пример обхода addslashes() взят из этой статьи.

Похоже, PDO эмулирует prepared statements силами PHP, вместо настоящих препейров в MySQL.
А если это:

$statement = $db->prepare(«SELECT * FROM lists WHERE id = ?»);
$statement->execute(array($argv[2]));

Заменить на:

$statement = $db->prepare(«SELECT * FROM lists WHERE id = :id»);
$statement->bindValue(':id', $argv[2], PDO::PARAM_INT);
$statement->execute();

?
Чёткая типизация в таких случаях — выход, но имеется ввиду, что и PDO не является 100% гарантией безопасности.
Спасет, до тех пор пока не понадобится строковый параметр в запросе :-)
> Похоже, PDO эмулирует prepared statements силами PHP, вместо настоящих препейров в MySQL.

так и есть. что несколько странно. но понятно почему nd c pdo прироста скорости не дает(даже наоборот)
Не надо писать свой движок. Возьмите готовый фреймворк.
И я не пойму в чем проблема с файлами?
Просто давать файлам сгенерированое имя и под отдельным расшерением.
Ну и стараться не использовать подобное.

<?php
header('Content-type: ...');
echo file_get_contents('myfile.txt');

Извините за прямоту, но у вас каша в голове.
По пунктам:
— Форма без хороших проверок ничего не стоит — ерунда, не надо ничего проверять, нужно экранировать вывод в браузер (rtfm htmlspecialchars).
— «Можно защитить свой движок только в том случае, если у тебя нет ни одной формы для загрузки файлов», «Узнайте о содержимом все» — ерунда, не нужно запрещать закачивать файлы и не нужно ничего проверять (размер и длину/ширину картинок, разумеется, нужно), главное запретить выполнение произвольных php-скриптов (и не только php, если у вас более сложный environment) из директорий, куда вы складываете upload, кейворды для гугления: «php_flag engine off», ".htaccess", «DocumentRoot».
— «Он может как-минимум двумя способами открыть настройки и там посмотреть сохраненные пароли, второе через отладчик поменять тип поля с password на text.» — ничего не даст, кроме того, что он сможет залогиниться под вами (если при логине вы ставили галочку «запомнить меня») — от этого вы не защититесь. Пароль он в любом случае не узнает.
— «Тут все так же как и с админкой, нельзя давать возможность попасть в phpmyadmin» — само по себе наличие phpmyadmin в прямом доступе угрозы не несет. Нужно лишь чтобы оно было запаролировано (лучше http-basic-auth, если вы не доверяете встроенным функциям) и, конечно же, не надо давать root-доступ к БД — хотя это опционально.
— Админка 7NVmE10SaJ.php — это называется security through obscurity и само по себе защитой не является. С другой стороны, если у вас уже все нормально защищено, то опять же этот пункт не нужен.
— Пароли. «С недавних времен я начал использовать такую связку для создания пароля md5($secret_key. $password. $salt);» — рекомендую еще усложнить, генерируйте еще и вторую динамическую соль и кладите её в БД рядом с паролем.
— Сессии. «Первое, что нужно помнить, не храните ID сессии в открытом виде, а еще лучше, храните его в БД» — нет причин не хранить ID в открытом виде, а совет хранить сессию в БД в общем виде вреден, полезен только в некоторых случаях, например, когда нужно распараллелить работу скриптов на несколько серверов.
— «Куки нужны для хранение данных браузером, зачастую многие хранят в куках id сессии, чего делать не рекомендую, особенно в открытом виде.» — уверен что именно так хранить ID сессии и нужно, ничего шифровать и проверять не нужно. Разве что могу порекомендовать проверять IP, чтобы данные одной и той же сессии можно было грузить только с одного и того же IP.
— «кроме windows конечно, там само ядро сплошная дыра» — извините, но это бред.
Я все понял. Линукс — решето, а виндовс — бублик.
рекомендую еще усложнить, генерируйте еще и вторую динамическую соль и кладите её в БД рядом с паролем.
Так первая соль и так рядом с паролем лежит, какой смысл от второй такой же?
Разве что могу порекомендовать проверять IP, чтобы данные одной и той же сессии можно было грузить только с одного и того же IP.
Так ip можно подделать и будет у тебя и сид и ip такой же.
Как IP подделать? На Вас теперь спец. службы ведут охоту.
Вы ошибаетесь. Не возможно спуфить TCP подключение из-за 3-Way Handshake.
Даже если такой пакет пройдет роутеры, наты, файрволы, то юзер все равно не сможет получить на него ответ, поэтому в контексте php-секьюрити данной проблемы не существует. (Поправьте если я не прав.)

«Так ip можно подделать и будет у тебя и сид и ip такой же.»
Сессионный идентификатор — информация секретная, подделать затруднительно (читайте «нельзя»). Можно выкрасть, против этого можно применять проверку IP.
«Так первая соль и так рядом с паролем лежит, какой смысл от второй такой же?»
Первая соль константная, лежит в скрипте, вторая — динамическая, лежит в БД. Первая мало полезна, но дополнительных затрат практически никаких, так что почему бы и нет.
md5($secret_key. $password. $salt) так секрет кей это и есть, так которая лежит в скрипте, а соль (динамическая) лежит в бд
> недавно задался идеей написать PHP движок для своих нужд
Примерно треть статьи я пытался понять, зачем понадобился собственный PHP-движок, пока мне не открылось, что речь о фреймворке.
Вот жеж каша у вас в голове…
Однако, спасибо — поржал.
Ясное дело, что это должен быть линукс.

Приверженцам FreeBSD, кстати — не ясное.
> Самый просто способ, как от этого избавиться, это использовать — mysql_real_escape_string
Самый лучший способ от этого избавиться это использовать вещи вроде ORM или PDO как выше сказали.
Забавно что вы при этом говорите > Старайтесь использовать MVC

> (кроме windows конечно, там само ядро сплошная дыра)
Спорю, вы никогда не сидели на серверной винде.

> Если что-то храните в куках, то шифруйте, а тем более проверяйте, потому что тут как и с формами, нельзя доверять тому что пришло
В чем проблема проверить на схожесть с md5 хэшем и уже затем лезть в базу?

> если это картинка, то ширина, высота
Если это картинка, то ее еще и пересоздать через GD надо, мало ли дряни которой туда напихали.
1. Для новичков MVC проще понять чем ORM и PDO.
2. Вы правы не сидел, в статье уже извинился.
3. Возможно, но я предпочитаю в куках просто id записи в бд, а там уже её вертеть как угодно
4. Это тоже вернно
Что лучше Opera или Windows?
О.о Это вообще к чему вопрос?
Вы путаете архитектурные паттерны с парадигмами доступа к данным
«Самый лучший способ от этого избавиться это использовать вещи вроде ORM или PDO как выше сказали.
Забавно что вы при этом говорите > Старайтесь использовать MVC»

Это ответ на комментарий, я вообще говорю что новичку программисту гараздо проще разобраться с MVC, чем лезть в дебри с доступами к данным. Для них надо для начала с обычными запросами разобраться, чтобы потом было проще понять работу с ORM или PDO
Хех, прийдётся покапитанить.

Весь сыр-бор из-за того, что Вы озвучив архитектурный подход, проигнорировали «хорошие практики» доступа к данным. Которые новичку понять на самом деле проще, чем выучить SQL и, что самое главное, не забыть обработку входящих данных.
ORM тоже ахитектурные рпаттерны как и MVC.
Если мы говорим о Object-relational mapping — То всё же это паттерн доступа к данным, а не построения приложения вцелом.
У Фаулера в одной книге об архитектуре приложений описаны :)
А ещё одним шрифтом, и в абривиатурах по три буквы. Заглавных. И всё же — стоит ведь вдумываться в смысл обьекта обсуждения :)
Новичку проще разобраться с MVC, где модели реализованы с ORM (паттерны ActiveRecord или DataMapper обычно), поскольку для этого ему не надо изучать SQL и реализовывать связь Model <-> DB самому. Да и если с нуля учить, то PDO или mysqli ничем особо не сложнее mysql.
> Если это картинка, то ее еще и пересоздать через GD надо, мало ли дряни которой туда напихали.
А Вы пробовали через GD прогнать картинку хотя бы 2000 на 2000?
попробуйте, чтобы потом не давать таких вредных советов.
Обычно на публичных сайтах картинки меньшего размера, естественно если вам нужен хайрез нужно применять фоновую обработку.
Вопрос не в том публичный сайт, или не публичный,
а в том, что грузит пользователь.

Использование Gd для обработки изображений можно использовать только в образовательных целях. И никак не в боевых условиях.

Проблемы GD лежат в области того что,
1) Он выполняется в контексте php скрипта который его использует. т.е. использует ровно те ресурсы которые отведены на выполнение скрипта
2) При обработке изображений GD старается загрузить все изображение в память целиком.
3) Крайне не стабильная работа GD с битыми файлами.

Для обработки изображений нужно использовать что-то вроде imagemigick а.
Странные советы про безопасность, ни слова про https и cookie HttpOnly+secure, использование дырявого md5.
если вы будете использовать админку с генерированными символами, то можете не беспокоиться (пример: 7NVmE10SaJ.php)

Мсье поразмыслил и решил, что при авторизации ещё можно выдавать уведомление о неправильном пароле (хотя пароль правильный) и отправлять на почту одноразовый урл, где опять же будет форма авторизации, за которой уже будет нормальная админка.
Масса движков имеют красивую авторизацию входа в админку через ввод имени и пароля на сайте. Т.е. идешь на адрес вроде адрес-сайта.tld/wp-admin.php, вводишь имя и пароль на самой странице, и входишь.

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

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

5 минут возни (включая гугление, куда и что прописать в своем сервере), и +1 левел защиты. И куда легче включить хотя бы такую проверку, чем устроить аудит всего кода движка.

Это я все к чему: в жизни часто приходится жить с тем движком, что уже есть. И тогда даже подручные средства оказываются дороже рассуждений о том, как некриворуко писать код :)
Тут вопрос — от кого Вы защищаетесь. Если Вы маленькая фирмочка — то Вы неуловимый джо. И «взламывать» вас будет троян, укравший у разработчика ftp логин/пароль (Кстати, защиты от этого пункта я в статье не увидел).

Если Вы — более крупная фирма, то через кого-то из сотрудников адрес админки будет узнан.

Кстати, есть одно решение, тоже в статье не указанное — ограничение доступа в админку по IP адресу.
Ваша правда. Это все тоже «дешевые, но хорошие меры», о чем я и писал. Туда же относим отказ от FTP, ssh-авторизацию по ключам, и прочие милые радости, включая knocker-а.

А уж кто ломает — может, кому то не нужен ваш сайт, но нужен сервер? Ботнету, для DDOS-а какого, да мало ли, может, skynet на php окажется написан? :)
>>Ясное дело, что это должен быть линукс. На счет защищенности не знаю, но если у человека руки растут откуда надо, то настроить можно любой >>сервер.
>> Из слов людей понятно, что и виндос можно настроить, так что решение за вами.
>>Если кого обидел с виндосом, извините, но мне не приходилось с ним работать, мнение высказал опираясь на отзывы знакомых.

Вот что Вы хотели этим сказать? Чёрный чай c сахаром слаще чем зелёный, но люди говорят что и в зелёный можно сахар положить.

Кстати, а по остальным пунктам — тоже по отзывам знакомых?
Либо я что-то не понимаю в этой жизни, либо… если пост называется «Проверяем PHP движок на прочность» должен быть о проверке PHP движка, а не о древних канонах безопасности вперемешку с кучей надуманных утверждений и стереотипов…
ТС считает что аудитория хабра только командую строку освоила?..

Правило 1. Никогда не доверяй данным пришедшим извне (от пользователя, из БД, с ФС и т.п.)
Правило 2. Никогда не доверяй защите security through obscurity
Sign up to leave a comment.

Articles