ANTICHAT.XYZ    VIDEO.ANTICHAT.XYZ    НОВЫЕ СООБЩЕНИЯ    ФОРУМ  
Баннер 1   Баннер 2
Antichat снова доступен.
Форум Antichat (Античат) возвращается и снова открыт для пользователей. Здесь обсуждаются безопасность, программирование, технологии и многое другое. Сообщество снова собирается вместе.
Новый адрес: forum.antichat.xyz
Вернуться   Форум АНТИЧАТ > Безопасность и Уязвимости > Уязвимости
   
Ответ
 
Опции темы Поиск в этой теме Опции просмотра

Роковые ошибки Php. Часть вторая.
  #1  
Старый 28.12.2007, 00:57
Аватар для Elekt
Elekt
Banned
Регистрация: 05.12.2005
Сообщений: 982
Провел на форуме:
4839935

Репутация: 1202


Отправить сообщение для Elekt с помощью ICQ
По умолчанию Роковые ошибки Php. Часть вторая.



Статья является продолжением к первой части: _http://forum.antichat.ru/thread54355.html

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

=======================================


Роковые ошибки PHP. Часть вторая.

Небезопасное Web-программирование.


[ Вступление ]

Поиск уязвимостей медленно но верно переходит на новую качественную ступень - исследование платформы/интерпретатора, изучение особеностей работы критичных для безопасности функций, пограничные состояния, переполнения буфера.
Старые элементарные баги неумолимо изживают себя. www.hardened-PHP.net ярко показал современный уровень дыр и эксплоитов.
И происходит своего рода естественный отбор - либо ты учишься чемуто-то новому, либо уходишь... Я покажу Вам, как остаться.


В первой части тебя ознакомили с распространенными уязвимостями.
Расскажу тебе об особенностях PHP, которые обязан знать каждый уважающий себя багоискатель.
В купе с первой частью ты сможешь не только расковырять пачку двигов, но и осознать - век PHP багов отнюдь не 20й век.
Все только начинается, тебе повезло быть здесь и сейчас. Учимся думать и все получится, ибо мозг - наш главный инструмент.


[ index.php?GLOBALS[file]=hehe! ]

Бага медленно уходит в историю. Существует немало эксплоитов под неё, например, от небезызвестного rgod'a.
В достаточно устаревших версиях PHP < = 4.3.10 и PHP <= 5.0.5 есть возможность определить переменную через массив GLOBALS,
используя запрос вида:

php.ini: register_globals=ON

/index.php?GLOBALS[foobar]=blaaa


Смотрим на результат: print_r($GLOBALS);
А поскольку суперглобальный массив GLOBALS проецируется на все переменные: print_r($foobar);


[ import_request_variables('GPC') - EVIL OVERWRITE ]

В первой части ты уже читал про неё, но опишу интересную особенность 'аццкой' перезаписи.
'GPC' (GET/POST/COOKIE) в аргументе функции означает порядок, следуя которому будут переписаны переменные.
Тоесть в данном случае - GPC - сначала перепишутся значения из GET, потом из POST и только после из COOKIE.
Как ты думаешь, что выдаст данный код?

/index.php?a=111
POST: a=222
COOKIE: a=333;


PHP код:
    import_request_variables('GPC');
    print 
$a
Код вернет '333'. Если было бы 'CGP' , то ответ был бы '222'. И аналогично.
Используя данную особенность, можно виртуозно обходить фильтры защиты.
Реальный пример уязвимого кода 'самой наисекурной' SLAED CMS 3.x ( мой привет автору +) ):
PHP код:
    if (isset($_GET['name']) || isset($_POST['name'])) {
        
$name trim(isset($_POST['name']) ? $_POST['name'] : $_GET['name']);
        if (
preg_match("/[^a-zA-Z0-9_]/"$name)) {
            
Header("Location: index.php");
            exit;
        }
    ....................................
        
// Register globals On
        
if ($old_modules == 1) {
            if (!
ini_get("register_globals")) @import_request_variables('GPC');
        }
    ....................................
        if (
file_exists("modules/$name/".$file.".php")) {
            include(
"modules/$name/".$file.".php"); 
Посмотрите внимательно, $name проверяется только в GET и POST. Тогда указав в COOKIE произвольное значение $name, мы получим локальный инклуд:

/index.php?name=FAQ&file=index
cookie: name=../../.././etc/passwd%00



[ parse_str() OVERWRITE ]

Достаточно новый баг(скорее фича) - parse_str() без второго параметра позволяет аналогично extract() или import_request_variable()
переопределить глобальный переменные, в том числе и служебные как _SERVER , _SESSION , _ENV, GLOBALS

/index.php?_SERVER[REMOTE_ADDR]=antichat

PHP код:
    parse_str($_SERVER['QUERY_STRING']);
    
print_r($_SERVER); 
Особенность использования: для перезаписи произвольных массивов второй аргумент parse_str() будет переписан значениями первого.
Для нас важно отсутствие второго аргумента, иначе перепишется только сам второй аргумент - parse_str($_SERVER['QUERY_STRING'],$query_str)


[ $$, &$ - жесткие и символические ссылки ]

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

/index.php?_SERVER[REMOTE_ADDR]=antichat.ru&_SESSION[auth]=bugaga!

PHP код:
    while(list($key,$val)=each($_GET))
     { 
       $
$key=$val
     }
    echo 
$_SERVER['REMOTE_ADDR'];
    if(isset(
$_SESSION)) {echo $_SESSION['auth'];} 
Подробное описание сабжа: http://www.php.su/learnphp/?re

А теперь бонус - помимо сказанного, благодаря тому что уязвимость глобализирует переменные - открывается возможность использовать UNSET атаку
даже при выключенном register_globals! Причем ни import_request_variables('GPC') , ни extract() такого же эффекта не дают.


[ ini_set(), ini_get() ]

Использование ini_set() позволяет изменять некоторые значения опций конфигурации.
Во-первых, далеко не все значения могут быть изменены из текущего скрипта.
Ознакомься с полным списком здесь http://php.su/functions/?ini_set и обрати внимание на "Определение констант PHP_INI_*' (внизу).
Только опции с PHP_INI_ALL флагом могут быть изменены через ini_set().

А во-вторых, некоторые хостеры не жалуют ini_set(), ini_get() и запрещают их, тем самым делая свой хостинг менее привлекательным
для размещения всякой гадости, вроде веб-ботов, парсеров\грабберов, анонимайзеров и прочей 'нежити', которым для комфортной работы требуется
изменять стандартные настройки PHP, вроде "max_execution_time","default_socket_timeout" и тд.

Но такой расклад получается далеко не на пользу легальным программам, особенно, если их безопасность строится, опираясь на ini_set().
Тогда, например, @ini_set( "register_globals", "0" ); @ini_set( "magic_quotes_gpc", "1" ); используемые в скрипте не изменят настроек и
движок может стать легкой мишенью.

Тоже касается и ini_get(), так как в случае его запрета может быть нарушена логика защитного механизма.
Как пример из практики - последний громкий эксплоит под PunBB.


[ ereg() poison NULL-byte ]

Использование ereg() и её производных (ereg_replace(),mb_ereg_match()) опасно тем,
что ereg() не является бинарно-совместимой функцией, тоесть воспринимает NULL-байт за конец строки и прекращает обработку, что дает возможность обойти фильтр.

/index.php?page=%00../../../../../../../etc/passwd%00blaa
PHP код:
    if(ereg('/',$_GET['page'])){die('Include detected!');}
    include(
getcwd().trim($_GET['page']).'.html'); 
/index.php?page=%00<script>alert(/antichat.ru/)</script>
PHP код:
    if(ereg('<',$_GET['page'])){die('XSS detected!');}
    echo 
$_GET['page']; 
eregi() имеет аналогичную уязвимость, но в одной из версий PHP её пропатчили.
Поскольку ereg() юзают где только возможно, здесь поле непаханное для всех типов атак.


[ $_SERVER[HTTP_X] ]

Дыры в http-заголовах занимают в моем скромном рейтинге почетное первое место.
Это настоящий клад для багоискателей. Сколько двигов тут полегло - уже и не сосчитать.
Уважаемые девелоперы! Продолжайте и далее доверять всем входящим http-данным! =))
И без работы ни вы ни мы не останемся...
Достаточно вспомнить последний публичный эксплоит под IPB_2.16
Если хорошо порыться на милворме, можно найти от XSS и SQL-inj до выполнения кода(!).
Наиболее часто используемые заголовки - user-agent, referer, accept-language, client-ip, x-forwarded-for, x-real-ip

Вообще сейчас очень модно отсылать данные, помещая их в HTTP-заголовки.
Такой способ часто используется при выполнении команд в эксплоитах(так называемый интерактивный шелл).
Как пример - последний публичный эксплоит под punBB - $_SERVER['HTTP_SHELL']
Но модно не потому, что круто. А потому что очень удобно.
~ простота посылки и приема средствами php,perl,etc..
~ отсутствие логирования, в отличии от _POST (mod_security)
~ пока не существует IDS, фиксирующей передачу левых данных в произвольных http-заголовках


[ magic_quotes_gpc - ? ]

Практически каждый из нас слышал о 'магических' ковычках и их роли в SQL-injection. Но мало кто задумывался, что означает 'gpc'.
Если мы обратимся к определению, то там ясно сказано - 'magic_quotes_gpc=ON' автоматически слеширует _GET/_POST/_COOKIE - (gpc) + _REQUEST.
А остальное - никто не слеширует, как то $_FILES, $_ENV, $_SERVER, $_SESSION...
Теперь вспомните предыдущий пункт. Да, юзер-агент, реферер лежат в _SERVER и magic_quotes'ом не обрабатываются.
А значит, если программер не позаботился о фильтре, то репутация продукта висит на волоске.

Кроме того, многие защиты основываясь на 'if(get_magic_quotes_gpc())..' используют add~ или stripslashes.
Поскольку такой подход применяется ко всем переменным подряд, а является корректным лишь для GET/POST/COOKIE/REQUEST,
то при magic_quotes=ON приложение становится подверженным SQL-inj в не GPC-массивах.
PHP код:
    if (!get_magic_quotes_gpc())
     {
      function 
addslashes_deep($value
       {
         
$value is_array($value) ? array_map('addslashes_deep'$value) : addslashes($value);
         return 
$value;
       }
      
$_SERVER array_map('addslashes_deep'$_SERVER);
     } 
Ну, как пример, пусть magic_quotes=ON, тогда User-Agent не подвергается addslashes.


[ intval(), (int) ]

У intval() есть интересная особенность - она возвращает TRUE если первой в аргументе содержится хотя бы одна цифра.
И у разработчиков тоже есть интересная особенность =)) -- они периодически используют intval()/(int) в логичесих условиях,
допуская непростительные ошибки.
Ведь наличие цифр в строке вовсе не гарантирует отсутствие других символов.

Пример:

/index.php?id=1'"qwerty
PHP код:
    $id=$_GET['id'];
    if(
intval($id) && (int)$id)
     {
      
sql_query("select $id from table_name");
     }
     else die(
'Id not integer!'); 
Несмотря на кажущуюся незначительность баги, встречается она в диком тырнете достаточно регулярно.
Для безопасного сравнения используйте is_numeric()


[ a == 'a' and a === 'a' ]

PHP не проверяет равенство типов при двойном равно (==), автоматически приводя их к строковому.
Для верного сравнения данных разных типов применяется тройное равно (===).
Неправильное использование двойного равно, например, в авторизации, == может обернуться уязвимостью.

PHP код:
    $aaa 123456;
    
    if( 
'123456' ==  $aaa ){echo '<br>ok!';}else{echo '<br>no.';}
    if( 
'123456' === $aaa ){echo '<br>ok!';}else{echo '<br>no.';} 
ok!
no.

Как пример - этой уязвимости был подвержен phpBB 2.0.8
Однако, такая бага далеко не уникальна и встречается в других продуктах по сей день


[ string or integer ? ]

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

Пример:

PHP код:
    $id="8' or 1=1/*";
    if(isset(
$id) && $id )
     {
      
query("select name from table where id='$id'");
     } 
Дружественность PHP к кодеру порой губительна.


[ %2527 => %27 => ' , %2522 => %22 => " ]

Двойное урл-кодирование параметра в купе с urldecode() дает возможность обойти magic_quotes/фильтры и выполнить произвольные SQL-команды.
Здесь %25 - урл-символ знака процента '%'. Таким образом после преобразования мы получаем незаэкранированную ковычку.
Пример уязвимого кода:

/index.php?login=hack%2527+or+1=1+limit+1/*

PHP код:
    $login=addslashes($_GET['login']);
    
mysql_query("SELECT id from users where name='".urldecode($login)."'"); 
Часто можно встретить в обработке кукисов, _SERVER['QUERY_STRING'].
Подобный баг был в ранних версиях phpBB и давал совместно с preg_replace(//e) выполнение произвольного кода.


[ base64_encode/base64_decode ]

Кодирование данных в base64 виде - также излюбленный приём вебмастеров.
Ну и как следствие - в закодированном виде слеширования конечно же не происходит и может возникнуть условие для SQL-inj.
Пример уязвимого кода:

PHP код:
$pass=base64_decode(addslashes($_COOKIE['password']));
    
mysql_query=("SELECT id from table where pass='$pass'"); 
Из практики - всем известный PHPNUKE долгое время страдал такой болезнью.


[ index.php?a[]=antichat ]

Не спешите пропускать абзац - вас ждет не только раскрытие пути...
Зачастую данные извлекаются из глобальных массивов без проверки параметра, массив он или строка(число).
И здесь можно получить от раскрытия пути до обхода проверок.
А теперь вспомните, функцию, которая чаще всего работает с глобальными массивами - addslashes() ! ага? пахнет жаренным.
Это уже действительно серьезно. Многие проверки в движках давятся при неожиданной встрече с массивом.
Пример безопасной проверки, используя рекурсивный самовызов:
PHP код:
    if (!get_magic_quotes_gpc())
     {
      function 
addslashes_deep($value
       {
         
$value is_array($value) ? array_map('addslashes_deep'$value) : addslashes($value);
         return 
$value;
       }
      
$_GET array_map('addslashes_deep'$_GET);
      
$_POST array_map('addslashes_deep'$_POST);
      
$_COOKIE array_map('addslashes_deep'$_COOKIE);
      
$_REQUEST array_map('addslashes_deep'$_REQUEST);
     } 
О ошибках: от нотиса до варнига - тут уже в зависимости от самой функции.
Например, array_key_exists() выдаст "Warning: array_key_exists()..."
Полный список уязвимых функций еще предстоит составить...


[ preg_replace() with /e ]

Достаточно известный способ выполнить команды там, где нельзя, но очень хочется =)
При использовании /e(~e) модификатора в регулярке - пхп код, содержащийся во втором аргументе, выполнится...

/index.php?match=123456&search=phpinfo();

PHP код:
    preg_replace("/345/e",$_GET['search'],$_GET['match']); 
Однако, даже если модификатор /e отсутствует - мы при возможности можем внедрить его, обрубив регулярку NULL-байтом.
Баг достаточно известный - эксплоит под phpbb=2.0.17 как раз на нем и был основан.
Пример:

/index.php?match=123456&search=phpinfo();&modifi=34 5/e%00

PHP код:
    preg_replace('/'.$_GET['modifi'].'/',$_GET['search'],$_GET['match']); 
Именно preg_replace() ищут в первую очередь после eval(), желая найти выполнение произвольного PHP-кода.


[ Динамическое определение переменных ]

Иногда перед кодером встает необходимость динамически определить переменную, когда задается произвольно не только значение, но и её имя.
Например, данные получают из БД, конфига, темплэйта или напрямую от пользователей, а после проходят эту операцию.
Опасность заключается в том, что при отсутствии должной фильтрации атакующий получает веб-шелл на сервере.
Пример уязвимого кода:

/index.php?value=;phpinfo();

PHP код:
      $new "antichat"
      
$value $_GET['value']; 
      eval(
"\$new = \$value;"); 
Красивое и эффективное выполнение команд.

Но и без эвала, это несет угрозу неконтролируемой глобализации произвольных переменных, как например здесь:

/index.php?var=auth&val=OK;

PHP код:
      $auth='NO';
      
$new $_GET['var']; 
      ${ 
$new } = $_GET['val'];
      echo 
$auth

[ create_function() ]

Создание функций как частный случай обратного вызова функций - один из самых красивых способов выполнения произвольного кода.
Рассмотрим пример на create_function():

/index.php?a=phpinfo();


PHP код:
    $a=$_GET['a'];
    
$new create_function('$x'"return $a;"); 
    
$new(''); 
Как видите, благодаря тому, что мы можем влиять на возвращаемый результат - возможно выполнение произвольного кода.
Практическое нахождение такой уязвимости обусловлено высоким уровнем удачи вашего юнита +) , а так же редкой криворукостью кодера.
Как пример - нашумевший эксплоит Шанкара для выполнения произвольных php-команд в TikiWiki.


[ header("Location: ... die(); ]

Поставив перенаправление, программист порой забывает добавить после него exit() или die(). Таким образом, код продолжает выполняться.
Используя любую http-тулзу(AccessDiver,intruder,inetcrack), отключив java-script в браузере(если редирект выполнен на яве)
или к примеру эксплоит на PHP - атакующий увидит результат.
Подобная ситация - серьезная брешь в безопасности,ведь редирект часто используют при неверной авторизации или в механизмах обработки ошибок.

Пример безопасного кода:

PHP код:
    header("Location: htpp://antichat.ru");
    die() or exit(); 
Мне извеcтны по крайней мере два весьма популярных движка, страдающих такой болезнью.


[ EOF ]

С точки зрения кодера, многих из описанных уязвимостей вообще не существует, поскольку копаться в тонкостях PHP - неблагодарная а самое главное - не оплачиваемая работа. Потому у Нас всегда будет преимущество и лишний козырь. Эти баги были. И будут. Вне зависимости от того, сколько раз про это напишут и скажут.

Описанным уязвимостям подвержены многие и многие продукты. И именно Нам еще и еще раз выпадает честь и удовольствие это подтвердить =)
Чем мы вскоре и займемся, но это уже совсем другая история...



Последний раз редактировалось Elekt; 01.04.2008 в 14:47..
 
Ответить с цитированием

  #2  
Старый 29.12.2007, 00:07
Аватар для Tem
Tem
Banned
Регистрация: 05.10.2005
Сообщений: 965
Провел на форуме:
5888800

Репутация: 547


Отправить сообщение для Tem с помощью ICQ
По умолчанию

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

P.S Elekt отлично просто супер, статья очень понравилась, давай продолжение таких статей.
 
Ответить с цитированием

  #3  
Старый 29.12.2007, 02:53
Аватар для fucker"ok
fucker"ok
Познавший АНТИЧАТ
Регистрация: 21.11.2004
Сообщений: 1,137
Провел на форуме:
2487541

Репутация: 761


По умолчанию

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

  #4  
Старый 29.12.2007, 07:50
Аватар для nerezus
nerezus
Pagan Heart
Регистрация: 12.08.2004
Сообщений: 3,791
Провел на форуме:
6490435

Репутация: 2290


Отправить сообщение для nerezus с помощью ICQ
По умолчанию

многие пункты типа "intval" и "urldecode после addslashes" ,addslashes_deep - вообще бред. В документации ясно все про это написано. А последняя функция - вообще непонятно что.
 
Ответить с цитированием

  #5  
Старый 29.12.2007, 10:15
Аватар для Tem
Tem
Banned
Регистрация: 05.10.2005
Сообщений: 965
Провел на форуме:
5888800

Репутация: 547


Отправить сообщение для Tem с помощью ICQ
По умолчанию

Соглашусь с nerezus что там можна делать с headr() ? чёта тожа непонял.
 
Ответить с цитированием

  #6  
Старый 29.12.2007, 12:07
Аватар для _Great_
_Great_
Флудер
Регистрация: 27.12.2005
Сообщений: 2,372
Провел на форуме:
5339610

Репутация: 4360


Отправить сообщение для _Great_ с помощью ICQ
По умолчанию

про Header не понял.

Цитата:
Сообщение от nerezus  
многие пункты типа "intval" и "urldecode после addslashes" ,addslashes_deep - вообще бред. В документации ясно все про это написано. А последняя функция - вообще непонятно что.
Эхх кто бы ее еще читал..
 
Ответить с цитированием

  #7  
Старый 29.12.2007, 17:45
Аватар для ShAnKaR
ShAnKaR
Пачка маргарина
Регистрация: 14.07.2005
Сообщений: 964
Провел на форуме:
4646474

Репутация: 1424


Отправить сообщение для ShAnKaR с помощью ICQ
По умолчанию

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

  #8  
Старый 29.12.2007, 18:31
Аватар для madnet
madnet
Умиротворенн
Регистрация: 09.12.2004
Сообщений: 996
Провел на форуме:
2386719

Репутация: 1384


Отправить сообщение для madnet с помощью ICQ
По умолчанию

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

http://madnet.name - madnet - blog | homepage (Мысли, релизы, скрипты, софт)

http://antichat.ru - Лучший сайт по безопасности
irc.antichat.ru:7771 #antichat - общение online
ГАРАНТ ФОРУМА
 
Ответить с цитированием

  #9  
Старый 29.12.2007, 20:39
Аватар для guest3297
guest3297
Banned
Регистрация: 27.06.2006
Сообщений: 1,614
Провел на форуме:
3887520

Репутация: 2996


По умолчанию

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

  #10  
Старый 29.12.2007, 20:42
Аватар для •••™NO FEAR™•••
•••™NO FEAR™•••
Постоянный
Регистрация: 08.08.2005
Сообщений: 782
Провел на форуме:
6573706

Репутация: 1419


По умолчанию

Цитата:
журнал Х не стоит таких мыслей и такой Pr ачату не нужен, все разработки, подобные этой, должны оставаться внутри закрытых комунити.
полностью согласен +1
Ну а Элект молодец.
 
Ответить с цитированием
Ответ



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Books PHP FRAGNATIC PHP, PERL, MySQL, JavaScript 186 21.02.2010 02:41
Безопасность в Php, Часть Iii k00p3r Чужие Статьи 0 11.07.2005 19:02
Пишем Php код, устойчивый к ошибкам k00p3r Чужие Статьи 0 10.07.2005 22:34
Защищаем Php. Шаг за шагом. k00p3r Чужие Статьи 0 13.06.2005 11:31
Аудит аутентификации на Web-сайтах. Часть вторая k00p3r Чужие Статьи 0 13.06.2005 11:20



Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
 


Быстрый переход




ANTICHAT.XYZ