세션 탈취해서 로그인하기(세션 하이재킹) feat. 쿠키와 세션 실습
HttpSession session = request.getSession();
자바에서 클라이언트의 세션을 얻기 위해 위의 코드를 많이 사용한다.
세션이 존재하지 않으면 초기에는 WAS 컨테이너에서 Session Id를 발급해준다.
그리고 Session Id를 클라이언트 환경에 쿠키로 저장하게 한다.
그래서 위의 코드로 사용자마다 세션 값을 구분해서 넘길 수 있는 이유는 클라이언트 컴퓨터에 있는 쿠키에 저장된 Session Id를 식별자로 사용하기 때문이다.
쿠키에 있는 Session Id 값을 서버에 던지면 서버는 해당값이 세션 저장소에 있는지 확인하고 세션을 넘겨주기 때문이다.
그럼 이렇게 생각할 수 있다.
쿠키의 세션 아이디를 다른 컴퓨터에 저장하면 로그인이 될까?
결론만 말하자면 가능하다.
로그인이 가능한 웹사이트에서 로그인 후에 JSESSIONID(톰캣 서버가 부여해준 세션 쿠키 ID)를 로그인 된 Session Id로 바꿔치기 해주면 Id, Password 없이 로그인이 된다.
그럼 보안이 너무 취약한 것 아니야? 라고 생각할 수도 있다.
하지만 이 방식으로 로그인이 가능해지려면 웹사이트가 SSL이 적용되어있지 않은 Http 사이트여야한다.
요즘 대부분의 사이트는 Https로 SSL을 사용하기 때문에 이러한 문제는 발생하지 않는다.
SSL이 적용이 되면 송수신자는 공개키-비밀키 암호화 방식을 통해서 Session Id를 전달받기 때문에 송수신자가 일치하지 않으면 로그인을 시켜주지 않는다.
이로인해 중간자 공격, 세션 하이재킹, 스니핑 공격 등으로부터 안전해진다.
쿠키에 세션 값을 보관해서 로그인을 할거면 그냥 쿠키로만 로그인 기능을 만들어도 되지 않아?
쿠키로만 로그인 기능을 만들면 보안 위험이 크게 존재한다.
누구나 다 아는 대표적인 사례의 하나는 공유 PC 접근이다. 공유 PC에 아이디와 패스워드가 쿠키 형태로 저장되어있으면 해당 PC에서 쿠키를 누구나 볼 수 있고 해당 정보를 통해 언제 어디서든 로그인이 가능하기 때문이다.
더불어 쿠키로 만든 로그인 보안 문제로는 XSS 공격, 스니핑 공격도 포함되지만 SSL을 이용하지 않은 세션 쿠키 로그인 방식 에서도 해당 보안 문제는 발생하기 때문에 생략했다.
차라리 쿠키를 안쓰고 서버가 사용자를 기억해서 Session을 부여해주는 방법은 없을까?
없다. 서버가 사용자를 기억하기 위해서 사용자에게 Cookie를 발급해주는 것이다.
그게 아니라면 마땅히 사용자마다 식별할 수 있는 매개체가 없기 때문이다.
HTTP는 무상태성(Stateless)이라는 특징을 갖고있다.
서버는 클라이언트의 상태를 보존하고 있지 않는다라는 뜻이다.
그래서 세션 로그인 방식은 완벽한 무상태성은 아니다.
서버에서 사용자의 식별자를 구분하기 위해 메모리에 Session ID를 비교하기 때문에 무상태성이라고 볼 수 없기 때문이다.
그렇기 때문에 나온 기술이 JWT다. 무상태성을 추구하려면 JWT 방식을 이용하는데 클라이언트와 서버간의 로그인 통신을 암호화(공개키-비밀키) 방식을 이용해서 서버는 사용자의 상태를 아예 저장하지 않는 방식으로 구현이 가능하다.