Проверка происхождения в веб-сокетах Java для предотвращения CSRF

Я программно развертываю конечную точку Java Websocket (JSR356 3.1) и хочу, чтобы она проверяла значение заголовка запроса Origin, чтобы смягчить атаки CSRF, и принимала только запросы рукопожатия, чьи значения заголовков Host и Origin совпадают.

Мне кажется, что путь - переопределить метод:

ServerEndpointConfig.Configurator.checkOrigin(String originHeaderValue)< /а>

(реализация, предоставляемая Tomcat 8, всегда возвращает true), но проблема, которую я вижу, заключается в том, что этот метод имеет только один параметр, и мне не хватает значения заголовка хоста для сравнения этого значения.

Кроме того, этот класс не предлагает никакого метода, возвращающего эту информацию, поэтому я считаю этот метод бесполезным, если только вы не сравниваете значение заголовка источника с ранее известным значением хоста или набором значений, но это также не имеет никакого смысла, поскольку мое приложение можно было увидеть под разными, изменяющимися именами хостов или IP-адресами.

Я рассматриваю возможность выполнения этой проверки внутри реализации modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response), где я могу прочитать все значения заголовков, но я почти уверен, что что-то неправильно понимаю.

Итак, мой вопрос:

Каков правильный способ выполнить эту проверку?

Спасибо, Начо


person idelvall    schedule 14.02.2016    source источник
comment
да, это не кажется правильным; API должен был предоставить приложению возможность отклонить или принять рукопожатие.   -  person ZhongYu    schedule 15.02.2016
comment
Спасибо @bayou.io, боюсь, что да. Я просто пометил вопрос tyrus, надеясь, что эксперт JSR сможет его прочитать.   -  person idelvall    schedule 15.02.2016


Ответы (1)


Немного покопавшись в проблеме, я пришел к выводу, что Websocket API (JSR-356) предназначен для выполнения проверки происхождения по «белому списку», ряду предопределенных разрешенных источников (как вы можете видеть в этот пример из Weblogic):

 ...
 import javax.websocket.server.ServerEndpointConfig;

 public class MyConfigurator extends ServerEndpointConfig.Configurator {
 ...  
     private static final String ORIGIN = "http://www.example.com:7001";

     @Override
    public boolean checkOrigin(String originHeaderValue) {
        return ORIGIN.equals(originHeaderValue)   
    }
 }
 ... 

но, к сожалению, этот API не предусматривает возможность реализации проверки заголовка Host vs Origin.

В качестве обходного пути для тех поставщиков услуг, которые размещают конечную точку веб-сокета за стеком сервлета (например, Tomcat, где механизм веб-сокета запускается фильтром сервлета org.apache.tomcat.websocket.server.WsFilter), вы можете создать внешний фильтр, который обеспечивает локальный доступ к запросу для потока, чтобы используйте его в методе checkOrigin(), чтобы получить значение заголовка Host.

Это заставляет меня задаться вопросом, почему этот тип проверки не предпочтительнее решения белого списка, и только что нашел этот интересный пост: Заголовки Origin и Host для запросов одного домена

person idelvall    schedule 15.02.2016