웹 애플리케이션에는 수많은 데이터가 움직입니다. 클라이언트와 서버가 주고 받는 데이터에는 분명 사용자에게 민감한 정보도 포함되어 있습니다. 예를 들어 주민번호, 전화번호, 계좌정보, 여권 정보등이 포함된 데이터가 공격자에 의해 탈취당한다면 어떻게 될까요? 웹 서비스의 신뢰도 추락은 물론, 사용자들은 경제적인 피해까지 입게 됩니다.
따라서 웹 개발에서 보안은 필수사항이라고 할 수 있습니다. 웹 서비스 공격자들이 가장 많이 사용하는 방법으로 알려져있는 방법으로는 크게 3가지가 있습니다.
- SQL Injection : 개발자가 의도하지 않은 SQL문을 임의로 삽입해 데이터를 탈취하는 공격
- XSS : 의도하지 않은 자바스크립트문을 실행시켜 데이터를 탈취
- CSRF : ?
CSRF(Cross Site Request Forgery)란?
CSRF는 다른 오리진에서 유저가 보내는 요청을 조작하는 공격 방법을 의미합니다. 예를 들어 이메일 링크를 클릭하면 내 계좌에서 돈이 빠져나가는 방법은 모바일 에서 자주 등장하는 보안 사고 입니다. CSRF의 특징으로는 공격자는 Response에는 접근이 불가능합니다. 사용자의 Request만 조작해 해커가 원하는 결과를 얻는 방법입니다. 이 이유는 다른 오리진(CORS) 설정이 되어 있지 않은 해커는 Response를 받을 수 없기 때문입니다.
CSRF 조건
① 쿠키를 사용한 로그인
유저는 로그인을 할 때 쿠키에 사용자 정보를 담고 있어야 합니다. 즉, 서버는 쿠키를 확인해서 사용자가 누구인지 특정가능해야 합니다.
② 예측가능한 요청 Parameter
클라이언트가 서버에 보내는 요청에는 예측 가능한 Parameter가 존재해야 합니다. Request를 보낼 때 포함되는 Parameter에 해커가 알 수 있는 정보를 담아 보내는 구조에서 CSRF 공격에 취약하다고 합니다. 예를 들어 은행업무를 보는 클라이언트가 이미 로그인을 한 상태에서 이체를 하는 단계에서 다시 로그인을 해라는 응답이 오면 해커가 작성한 CSRF 공격은 작동하지 않게 됩니다.
CSRF 작동 방식
GET 요청 공격
만약 사용자가 아래 URI를 통해 이체를 한다고 가정합니다. koreabank에서 100000원을 username에게 보내는 URI입니다. 사용자는 이미 로그인을 한 상태로 세션이 생성된 상태고, 로그인 정보는 cookie에 저장되어 있는 상황입니다.
여기서 우리가 메일이나 모바일 SMS로 많이 받아왔던 익숙한 URI 링크가 등장합니다. 이 링크를 확인해보면 account에 우리가 보낼 대상의 계좌번호가 아닌 공격자의 계좌가 심어져 있습니다. 이대로 링크를 클릭하면 koreabank에 공격자계좌로 10만원을 보내는 쿼리가 실행될 것입니다.
POST 요청 공격
다음으로 비밀번호가 강제로 변경되는 상황을 가정해봅니다. 비밀번호를 변경할 때는 request.body에 변경하고자 하는 비밀번호 정보를 태워서 서버에 요청하게 됩니다.
사용자는 특정 웹 사이트에 접속합니다. 이 사이트는 이미 해커가 koreabank에 로그인이 되어 있고, cookie에 사용자 정보를 가지고 있는 유저들을 대상으로 비밀번호를 임의로 변경하기 위해 작성된 사이트 입니다. 사용자가 접속하는 순간 웹 사이트에 심겨진 Javascript가 실행되고, koreabank에 비밀번호를 임의로 변경해버리는 POST 요청을 날립니다.
CSRF 공격 방어
CSRF 공격을 방어하기 위해서는 2가지 방법이 있습니다.
① CSRF 토큰
서버에서는 유저의 브라우저와 웹 앱에만 CSRF 공격을 보호하기 위한 임의의 토큰 문자열을 전송합니다. 이 후 토큰 문자열의 조합으로 완성된 요청에 대해서만 서버는 리소스를 응답하게 됩니다.
② same-site cookie
서버에서는 cosrs 옵션에서 같은 도메인에서만 쿠키와 세션을 사용하도록 설정하게 됩니다. 만약 다른 site에서 cookie를 사용하도록 하는 요청이 들어오면 서버는 이를 거절하게 됩니다.
'Programming' 카테고리의 다른 글
[WebSocket] 웹 소켓(Web Socket) 이란? (0) | 2022.07.18 |
---|---|
[Node.js] PNG to webp Converter 구현하기 (0) | 2022.06.19 |
[Database] sequelize node.js mysql example 간단 예제 (0) | 2022.06.12 |
[Docker] Node.js Dockerfile로 배포 하는 방법 (0) | 2022.06.12 |
[Docker] 도커 사용하는 이유? (0) | 2022.06.10 |
댓글