Никогда не применять контроль доступа на стороне клиента
Описание
Контроль доступа на стороне клиента — это практика, при которой проверки прав доступа выполняются в коде, исполняемом на клиенте (например, в JavaScript). Это может привести к серьезным уязвимостям, так как злоумышленники могут легко обойти такие проверки, изменяя код или манипулируя запросами.
Почему это важно
- Безопасность данных: Если контроль доступа осуществляется на стороне клиента, злоумышленники могут получить доступ к данным или функциям, к которым у них нет прав, что может привести к утечке конфиденциальной информации.
- Устойчивость к манипуляциям: Проверки на стороне клиента могут быть изменены или удалены, что делает систему уязвимой для атак.
- Надежность системы: Полагание на клиентские проверки может привести к непредсказуемому поведению системы и снижению ее надежности.
Способы реализации с примерами
Проверка прав доступа на сервере: Все проверки прав доступа должны выполняться на сервере. Сервер должен проверять, имеет ли пользователь право на выполнение запрашиваемого действия.
Пример:
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route('/api/resource', methods=['GET'])
def get_resource():
user_id = request.args.get('user_id')
resource_id = request.args.get('resource_id')
if not has_access(user_id, resource_id): # Проверка прав доступа на сервере
return jsonify({'error': 'Access denied'}), 403
return jsonify({'data': 'This is the resource data'})
Удаление клиентских проверок: Убедитесь, что в клиентском коде нет проверок прав доступа. Все проверки должны быть сосредоточены на сервере.
Пример:
// Уязвимый код на стороне клиента
if (userHasAccess) {
fetch('/api/resource')
.then(response => response.json())
.then(data => console.log(data));
} else {
console.log('Access denied');
}
Безопасный код:
// Удаление проверки на стороне клиента
fetch('/api/resource')
.then(response => {
if (!response.ok) {
throw new Error('Access denied');
}
return response.json();
})
.then(data => console.log(data));
Логирование и мониторинг: Ведите логи всех запросов к защищенным ресурсам и проверяйте их на наличие подозрительной активности.
Пример:
import logging
logging.basicConfig(level=logging.INFO)
@app.route('/api/resource', methods=['GET'])
def get_resource():
user_id = request.args.get('user_id')
resource_id = request.args.get('resource_id')
if not has_access(user_id, resource_id):
logging.warning(f"Unauthorized access attempt by user {user_id} to resource {resource_id}")
return jsonify({'error': 'Access denied'}), 403
return jsonify({'data': 'This is the resource data'})
Примеры уязвимого кода
// Пример уязвимого кода на стороне клиента
function fetchResource() {
if (userIsAdmin) { // Проверка на стороне клиента
fetch('/api/resource')
.then(response => response.json())
.then(data => console.log(data));
} else {
console.log('Access denied');
}
}
Проблема: В этом коде проверка прав доступа осуществляется на стороне клиента, что делает систему уязвимой для обхода.
Причины, к которым может привести несоблюдение требования
- Несанкционированный доступ: Злоумышленники могут обойти проверки на стороне клиента и получить доступ к защищенным ресурсам.
- Утечка данных: Если контроль доступа не реализован на сервере, это может привести к утечке конфиденциальной информации.
- Проблемы с безопасностью: Полагание на клиентские проверки увеличивает риск атак и снижает общую безопасность системы.
Рекомендации
- Всегда выполняйте проверки прав доступа на сервере, а не на стороне клиента.
- Удаляйте все проверки доступа из клиентского кода.
- Используйте механизмы логирования и мониторинга для отслеживания попыток несанкционированного доступа.
- Обучайте разработчиков важности контроля доступа на сервере и рисков, связанных с клиентскими проверками.