V5334. OWASP. Possible server-side request forgery. Potentially tainted data in the URL is used to access a remote resource.
Анализатор обнаружил обращение к удалённому ресурсу без проверки предоставленного пользователем URL-адреса. Использование непроверенных внешних данных для формирования адреса может стать причиной возникновения Server-Side Request Forgery.
Уязвимости такого типа относятся к категории рисков OWASP Top 10 Application Security Risks 2021:
Приведём пример:
public static class UrlController {
private final String BASE_URL = "http://localhost/";
protected void connect(HttpServletRequest req) throws IOException {
String filter = req.getParameter("filter");
URL url = new URL(BASE_URL + filter);
url.openConnection(); // <=
//....
}
}
В данном примере переменная filter может содержать заражённые данные, так как они приходят из внешнего источника и участвуют в формировании запроса, отправляемого от имени сервера на ресурс, адрес которого записан в переменной BASE_URL.
Таким образом, злоумышленник получает возможность совершать вредоносные действия, отправляя запросы к ресурсам, прямой доступ к которым у него отсутствует.
Злоумышленник может записать в переменную filter следующий текст:
admin/delete?username=testSSRF
Тогда итоговый запрос будет иметь следующий вид:
http://localhost/admin/delete?username=testSSRF
При выполнении запроса с таким адресом злоумышленник может удалить пользователя.
Также стоит заметить, что при борьбе с SSRF не стоит использовать запрещённый список или регулярные выражения. Злоумышленник может легко обойти эти ограничения:
- Перенаправление — злоумышленник может создать внешний ресурс, который в качестве ответа перенаправляет на другой URL.
- Альтернативные представления:
http://2130706433/ = http://127.0.0.1
http://0x7f000001/ = http://127.0.0.1
Пример борьбы с SSRF с использованием проверки предоставленных данных:
public static class UrlController {
private final String BASE_URL;
private final List<URL> whitelist;
protected void connect(HttpServletRequest req) throws IOException {
URL url = new URL(BASE_URL + req.getParameter("filter"));
if (whiteList.contains(url)) { // <=
url.openConnection();
//....
}
}
}
Также можно использовать специальные URL-кодировщики, которые экранируют запрос. Например, пользователь может передать следующую строку как параметр:
../admin/secure-info
Код, который формирует запрос на сторонний ресурс, выглядит следующим образом:
private final static String INTERNAL_URL = "http://localhost/service/";
protected void connect(HttpServletRequest req) throws IOException {
String filter = req.getParameter("filter");
URL url = new URL(INTERNAL_URL + filter);
url.openConnection(); // <=
//....
}
В случае, если символ ../ никак не экранируется, итоговый запрос на сторонний ресурс принимает вид:
http://localhost/admin/secure-info
Обращаясь по данному запросу, злоумышленник может выполнять различные действия на стороннем ресурсе, например, узнать техническое оснащение сервера, количество пользователей и прочую приватную информацию.
Чтобы защититься от таких атак, следует экранировать запрос пользователя. Пример безопасного кода:
private final static String INTERNAL_URL = "http://localhost/service/";
protected void connect(HttpServletRequest req) throws IOException {
String filter = req.getParameter("filter");
String encodedFilter = URLEncoder.encode(filter, "UTF_8"); // <=
URL url = new URL(INTERNAL_URL + encodedFilter);
url.openConnection();
//....
}
Выявляемые диагностикой ошибки классифицируются согласно ГОСТ Р 71207–2024 как критические и относятся к типу: Ошибки непроверенного использования чувствительных данных (ввода пользователя, файлов, сети и пр.). |
Данная диагностика классифицируется как:
|