go.php и XSS уязвимость. Истинная причина ее проявления

Думаю все помнят уязвимость, которая была обнаружена в файле go.php и позволяла выполнять произвольный JavaScript код в браузере пользователя. Давайте посмотрим, из-за чего она проявлялась.

Код файла go.php:

...
function reset_url($url) {
	$value = str_replace ( "http://", "", $url );
	$value = str_replace ( "https://", "", $value );
	$value = str_replace ( "www.", "", $value );
	$value = explode ( "/", $value );
	$value = reset ( $value );
	return $value;
}

$url = @rawurldecode ( $_GET['url'] ); //Получаем url и декодируем его
$url = @base64_decode ( $url ); //Выполняем декодинг из base64
$url = @str_replace ( "&", "&", $url ); 

$_SERVER['HTTP_REFERER'] = reset_url ( $_SERVER['HTTP_REFERER'] );
$_SERVER['HTTP_HOST'] = reset_url ( $_SERVER['HTTP_HOST'] );

if (($_SERVER['HTTP_HOST'] != $_SERVER['HTTP_REFERER']) OR $url == "") { //Сравнение реферера и хоста (запрет на ссылку на данный файл с других ресурсов)
	@header ( 'Location: /index.php' );
	die ( "Access denied!!!<br /><br />Please visit <a href=\"/index.php\">{$_SERVER['HTTP_HOST']}</a>" );
}

if ( $config['charset'] == "windows-1251" ) {

	if( function_exists( 'mb_convert_encoding' ) ) {
	
		$url = mb_convert_encoding( $url, "UTF-8", "windows-1251" );
	
	} elseif( function_exists( 'iconv' ) ) {
	
		$url = iconv( "windows-1251", "UTF-8", $url );
	
	}

}

@header ( 'Location: ' . $url ); //Перенаправление 

die ( "Link Redirect:<br /><br />Please click <a href=\"{$url}\">here.</a>" ); //Прерывание работы скрипта с показом ссылки URL
…

Выглядит код довольно безобидно, если бы не одно НО. Думаю все помнят про атаку типа HTTP Response Splitting. В старых версиях PHP она осуществлялась с помощью внедрения символов \r\n в функцию header() и была довольно распространена. Затем разработчики PHP пофиксили эту функцию и теперь когда в параметр данной функции попадают символы \r\n, то она вываливается с предупреждением и отказывается работать, при этом выполнение самого скрипта продолжается. Учитывая эти особенности работы функции header(), взглянем еще раз на код выше. В этом коде видно, что URL напрямую попадает в функцию header(), а затем выводится в HTML тег <a> функции die(). Если мы передадим в функцию header() символ \n, то она вывалится с ошибкой, но выполнение самого скрипта продолжится. Так как URL не проходит фильтрацию вообще, то мы сможем передать любой JS код и выполнить его.

Давайте попробуем передать следующий код в base64:

\n"><script>alert(1);</script><a href=“http://test.com

Результат работы:

Рис. 1. Отправка специально сформированного запроса.
Рис. 2. HTML код страницы go.php.

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

  • строку "Link Redirect:<br><br>Please click <a href="\{$url}\">here.</a>" заменить на "Link Redirect". Впринципе больше ничего менять не нужно, так как мы убрали вывод данных, но если хочется, то смотрим на пункт ниже;
  • после строки $url = @str_replace ( "&amp;", "&amp;", $url ); дописать следующую строку: $url = str_replace(array("\r","\n"), "", $url); . В результате функция header() будет работать как нужно.

Поделиться ссылкой:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

XHTML: В комментариях можно использовать теги | <a href="" title=""> | <abbr title=""> | <acronym title=""> | <b> | <blockquote cite=""> | <cite> | <code> | <del datetime=""> | <em> | <i> | <q cite=""> | <s> | <strike> | <strong> | <pre><code class="language-"> |.
Gravatars: Хотите чтобы был свой аватар в комментариях? Зайдите на Gravatar и зарегистрируйтесь.
Spam: Различные антиспам плагины могут быть активированы.

Всего: 0 комментов в 3 сниппетах.