﻿# 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: 

* [A10:2021 – Server\-Side Request Forgery \(SSRF\)](https://owasp.org/Top10/A10_2021-Server-Side_Request_Forgery_%28SSRF%29/)

Приведём пример:

```cpp
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` следующий текст: 

```cpp
admin/delete?username=testSSRF
```

Тогда итоговый запрос будет иметь следующий вид: 

```cpp
http://localhost/admin/delete?username=testSSRF
```

При выполнении запроса с таким адресом злоумышленник может удалить пользователя\.

Также стоит заметить, что при борьбе с SSRF не стоит использовать запрещённый список или регулярные выражения\. Злоумышленник может легко обойти эти ограничения:

* Перенаправление — злоумышленник может создать внешний ресурс, который в качестве ответа перенаправляет на другой URL\.
* Альтернативные представления:  

```cpp
http://2130706433/ = http://127.0.0.1 
http://0x7f000001/ = http://127.0.0.1
```

Пример борьбы с SSRF с использованием проверки предоставленных данных: 

```cpp
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\-кодировщики, которые экранируют запрос\. Например, пользователь может передать следующую строку как параметр:

```cpp
../admin/secure-info
```

Код, который формирует запрос на сторонний ресурс, выглядит следующим образом:

```cpp
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();                       // <=
  //....
}
```

В случае, если символ `../` никак не экранируется, итоговый запрос на сторонний ресурс принимает вид:

```cpp
http://localhost/admin/secure-info
```

Обращаясь по данному запросу, злоумышленник может выполнять различные действия на стороннем ресурсе, например, узнать техническое оснащение сервера, количество пользователей и прочую приватную информацию\. 

Чтобы защититься от таких атак, следует экранировать запрос пользователя\. Пример безопасного кода: 

```cpp
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();
  //....
}
```