Skip to main content

V13.2.3 RESTful Web Service

Requirement:#

Verify that RESTful web services that utilize cookies are protected from Cross-Site Request Forgery via the use of at least one or more of the following: double submit cookie pattern, CSRF nonces, or Origin request header checks.

Explanation:#

Cross-Site Request Forgery (CSRF) - это атака, при которой злоумышленник обманом заставляет жертву выполнять нежелательные действия в веб-приложении, в котором жертва аутентифицирована. В контексте веб-служб RESTful атаки CSRF могут быть запущены путем обмана браузеров пользователей, заставляющих их выполнять запросы от их имени без их ведома или согласия. Чтобы предотвратить такие атаки, ASVS предлагает реализовать один или несколько из следующих методов:

1 Double Submit Cookie Pattern: этот метод включает отправку случайно сгенерированного уникального токена в виде файла cookie вместе с каждым запросом. Это же значение токена также включается в параметры запроса. Затем серверный компонент сравнивает маркер из файла cookie с маркером в параметрах запроса, чтобы проверить подлинность запроса. 1 CSRF Nonce: Nonce означает «число, используемое один раз». При таком подходе для каждого пользовательского сеанса или запроса генерируется уникальное непредсказуемое значение (nonce). Одноразовый номер встроен в запрос, как правило, в виде скрытого поля формы или дополнительного заголовка. Компонент на стороне сервера проверяет полученный одноразовый номер, чтобы убедиться, что запрос является законным и не является атакой. 1 Origin Request Header Checks: заголовок запроса источника содержит источник (домен), из которого отправляется запрос. Проверяя заголовок Origin, серверный компонент может гарантировать, что запросы принимаются только от определенных доверенных доменов, предотвращая запросы, исходящие от вредоносных веб-сайтов.

Remediation:#

Для защиты от CSRF-атак в RESTful веб-службах, использующих файлы cookie, требование ASVS предполагает использование по крайней мере одной или нескольких из следующих техник:

Double Submit Cookie Pattern: Создайте уникальный токен для каждого сеанса пользователя и включите его в файл cookie и в параметры запроса. На стороне сервера сравните токен из куки с токеном в параметрах запроса, чтобы убедиться в подлинности запроса.

Пример реализации с использованием языка программирования Java: Double Submit Cookie Pattern

public void doPost(HttpServletRequest request, HttpServletResponse response) {
String csrfToken = generateCSRFToken(); // Generate a secret value
Cookie cookie = new Cookie("CSRFToken", csrfToken);
response.addCookie(cookie); // Set the cookie in the response
String formHTML = "<form method='POST'>" +
"<input type='hidden' name='csrf_token' value='" + csrfToken + "' />" +
"<input type='text' name='data' />" +
"<input type='submit' value='Submit' />" +
"</form>";
response.getWriter().write(formHTML); // Render the form in the response
}
public void doSubmit(HttpServletRequest request, HttpServletResponse response) {
String csrfToken = request.getParameter("csrf_token");
Cookie[] cookies = request.getCookies();
String csrfCookie = null;
if (cookies != null) {
for (Cookie cookie : cookies) {
if (cookie.getName().equals("CSRFToken")) {
csrfCookie = cookie.getValue(); // Get the CSRF token from the cookie
}
}
}
if (csrfToken.equals(csrfCookie)) {
// Process the form data
} else {
// Reject the request
}
}

CSRF Nonces: Создайте уникальный одноразовый номер для каждой пользовательской сессии или запроса и вставьте его в запрос либо в виде скрытого поля формы, либо в виде дополнительного заголовка. Проверьте полученный одноразовый номер на стороне сервера, чтобы убедиться в легитимности запроса.

Пример кода, реализующий технику CSRF Nonces с использованием языка PHP: CSRF Nonces

<?php
session_start();
function generateCSRFToken() {
return bin2hex(random_bytes(32)); // Generate a random token
}
function getCSRFToken() {
if (!isset($_SESSION['CSRFToken'])) {
$_SESSION['CSRFToken'] = generateCSRFToken(); // Store the token in the session
}
return $_SESSION['CSRFToken'];
}
function validateCSRFToken($token) {
return hash_equals(getCSRFToken(), $token); // Verify the token matches the one in the session
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$csrfToken = $_POST['csrf_token'];
if (validateCSRFToken($csrfToken)) {
// Process the form data
} else {
// Reject the request
}
}
$csrfToken = getCSRFToken();
$formHTML = "<form method='POST'>" .
"<input type='hidden' name='csrf_token' value='" . $csrfToken . "' />" .
"<input type='text' name='

Origin Request Header Checks: Настройте компонент на стороне сервера, чтобы он проверял заголовок запроса Origin и принимал запросы только от определенных доверенных доменов. Отклонять запросы, исходящие не из этих доверенных доменов. Origin Request Header Checks

from flask import Flask, request, jsonify
app = Flask(__name__)
# Whitelist of trusted domains
allowed_origins = ['https://example.com', 'https://api.example.com']
# Check if the request's Origin header matches the whitelist
def validate_origin():
origin = request.headers.get('Origin')
if origin in allowed_origins:
# Request is coming from a trusted domain
return True
else:
# Request is not from a trusted domain, reject it
return False
# Example route handling function
@app.route('/api/endpoint', methods=['POST'])
def handle_request():
if validate_origin():
# Process the request since it is coming from a trusted domain
# Your code logic here
return jsonify({'message': 'Request processed successfully.'}), 200
else:
# Reject the request as it is from an untrusted domain
return jsonify({'error': 'Invalid request origin.'}), 403
if __name__ == '__main__':
app.run()