XSS 공격 이슈 (Postman으로 CSRF 토큰 적용하는 법)

이슈

누군가 자사 서비스의 메일 발송 기능을 이용해 수 분간 500통 이상의 메일을 발송했다. 메일 내용에는 XSS 공격으로 추측되는 javascript 코드가 포함되어 있었다.

 

response.write(9365865*9010919)

원인

Spring Securiy를 통해 CSRF 토큰을 설정했지만, API 테스트 툴 등으로 뚫리는 것을 확인했다.

경과 및 해결

당시 공격을 통해 DB에 들어왔던 데이터는 컬럼 중 반드시 하나의 스크립트를 포함하고 있었다. 그 외에 컬럼에는 무작위 영문 조합과 testing@example.com 이라는 이메일 데이터가 있었다.

 

이메일은 모두 인증이 되지않고 실존하지 않는 이메일로 확인되었다. 즉, 메일 발송이 가능한 페이지에 설정해두었던 Mail Validator를 거치지 않고 Form 을 Submit 한 것이다.

 

단 스크립트 코드는 서버 내에서 적용된 XSS 필터에 의해서 간접표현식으로 대체되어 서버에 영향을 주지는 못했다.

 

"+response.write(9365865*9010919)+"

 

우선 공격자는 1명인 것으로 추측 됨으로 엑세스 로그에서 해당 IP를 찾아, 톰캣 서버 설정에서 해당 IP를 차단해놓았고 그 이후로 공격은 시도되지 않았다.

~/tomcat/conf 경로의 server.xml 파일에서 <HOST></HOST> 태그 내에 아래와 같이 차단할 IP를 삽입한다.

<Valve className="org.apache.catalina.valves.RemoteAddrValve" deny="차단대상ip기재"/>

 

이후 뚫리는 원인 파악 및 방지를 위해 똑같은 공격을 재현해보았다. 무료 API 테스트 툴인 Postman 을 사용하여 테스트했다.

사진1. Postman 테스트 화면 - 최초 요청
사진2. Postman 테스트 화면 - 같은 토큰 값으로 두 번째 요청

 

테스트할 URL과 알맞은 파라미터 값을 모두 입력한 뒤, 사진1과 같이 Header에 X-XSRF-TOKEN 항목을 추가하고, 공격하고자 하는 웹 사이트의 소스 보기를 통해 토큰 값을 구해서 입력하면 사진1 하단과 같이 403에러가 발생한다.

 

Could not verify the provided CSRF token because your session was not found.

 

사진1의 에러 내역을 보면 세션을 찾을 수 없기 때문에 CSRF 토큰을 확인할 수 없다고 나온다. 하지만 여기서 Header Cookie 란에 최초에는 없었던 또 다른 csrf 토큰 값이 생긴 것을 알 수 있다. 이후 토큰 값을 변경하지 않고 그대로 다시 신청하면 사진2와 같이 에러 로그가 달라진 것을 확인할 수 있다.

 

Invalid CSRF Token '15e3ada0-97c6-46a4-a6db-c8150ff32fed' was found on the request parameter '_csrf' or header 'X-XSRF-TOKEN

 

사진2의 에러 내역을 살펴보면 이전의 내역과 달리 csrf 토큰 값이 맞지 않는 다고 뜬다.

 

사진3. Postman 테스트 화면 - 쿠키 내 CSRF 토큰으로 요청

 

하지만 사진3과 같이 최초 요청 이후 생긴 쿠키 내 CSRF 토큰 값으로 수정하여 요청하면 설정해두었던 성공 메시지를 확인할 수 있다.


작성했던 위 내용과 같이 CSRF 토큰을 설정해도 API 테스트 툴로도 토큰을 인증받을 수 있고, 클라이언트에 설정해두었던 메일 인증을 우회하며 수분간 버튼 클릭만으로 수 많은 요청을 보내 메일 시스템을 과부화 시킬 수 있었다.

임시 방편으로 톰캣에서 해당 IP를 차단해두었지만 Proxy 등 IP를 우회하거나 변경해서 접근한다면 계속 같은 공격을 할 수 있으니 다른 방법을 생각해보았다.

 

첫째로 급하게 클라이언트 단에서만 사용했던 Mail Validator API를 서버 단에도 적용시켰다. 공격자가 입력했던 메일 모두 @example.com 이라는 인증되지 않은 메일이었기 때문이다. 1차로 클라이언트 단 Mail Validator에서 메일 인증을 하고, 2차로 서버 단에서 메일 인증을 한번 더 시도하여 인증되지 않은 메일은 컨트롤러 단에서 차단하였다.

 

하지만 이후 구글 가계정 등 인증 가능한 메일로 같은 공격을 시도한다면, 똑같은 공격이 가능하므로 메일 발송 기능이 
포함된 페이지에 캡챠를 추가할 예정이다.