본문 바로가기

프론트엔드

env 파일의 보안 취약점과 api key 유출에 대비하기

  • 프로젝트: SNU FESTIVAL
  • 키워드: .env, react environment variables, security, chrome devtools sources, firebase auth, firestore
  • 상황
    1. 프로젝트에서 로그인 기능은 firebase auth 의 google login 을 사용하고 있고, 데이터 CRUD는 firestore 를 사용하고 있다.
    2. CRA 환경에서 firebase api key 값을 .env 파일에 분리하여 저장하고있다.
    3. .env 파일이 보안을 위해 사용한다고 알려져있지만, 개발자 도구 source를 통해 충분히 노출될 가능성이 있다.
      env에 명시한 value가 그대로 노출되는 모습
      이를 막기 위해선 백엔드의 도움이 필요하지만, SNU FESTIVAL 프로젝트는 1인 개발이므로 firebase 의 보안 기능을 최대한으로 이용해 악용을 막고자했다.
  • 해결방법
    1. firebase login을 승인된 도메인에서만 허용한다.
      승인된 도메인 설정
    2. firestore rule 에서 firebase auth 인증이 되어있는 사용자만 데이터를 조작할 수 있도록 설정한다.
      즉 firebase 인증은 승인된 도메인에서만 가능하고, 인증이 되어야지만 데이터를 조작할 수 있기 때문에, api key가 유출되어도 데이터 접근은 막을 수 있다.
      firestore rule의 일부
      위의 사진은 특정 collection에 대해 로그인된 유저만 새로운 문서를 만들 수 있고, 본인이 만든 문서만 read, update 할 수 있도록 설정한 예시이다.
  • 한 걸음 더
    1. 카카오톡 로그인/공유하기 기능을 사용할 때에도 비슷한 과정을 거친다. 사이트 도메인에 등록된 곳에서만 해당 기능이 정상 작동한다.
      승인된 도메인 등록
    2. 네이버 map 을 사용할 때에도 비슷한 과정을 거친다.
      secret key 가 노출되더라도 승인된 도메인에서만 naver api 를 사용할 수 있다.

  • 두 걸음 더
    • 상황
      • api key 이외에 SNU FESTIVAL 프로젝트에서 숨겨야하는 값이 또 있었다.
      • 미궁게임(https://snu-festival.web.app/activity/mini/riddle)의 정답을 숨겨야하는데, 정답을 코드에 하드코딩하면  난독화를 한다고 하더라도 chrome devtools source 어딘가에 정답이 노출될 것이다.
      • 정답을 외부(서버, firebase 등)에 저장한 뒤 GET 요청으로 받아올 수 있겠지만, 미궁게임의 짧은 정답 'string' 만을 위해 네트워크를 추가적으로 사용하고 싶지는 않았다.
    • 해결방법
      • 비밀번호를 DB에 저장하는 것과 같은 원리로 js-sha256 라이브러리를 이용하여 정답의 hash값을 구한다.
      • hash값만 프로젝트 코드에 하드코딩한다.
          const answers = [
          '07436abdfc015b3d6e7f6236e4817639b24bfb77e68adfb779ace94e8d08c047',
          '4ea140588150773ce3aace786aeef7f4049ce100fa649c94fbbddb960f1da942',
          'a27db16581bce5f90e4e7d08e10f861d0c6986a01d80babea22f6af4e5774ff1',
        ];
      • 미궁게임 정답 입력창에서 사용자가 정답을 입력하면, 해당 문자열의 hash값을 구한 뒤 answers의 hash값과 비교한다.
  • 의의
    1. 프론트엔드단에서 중요한 값을 완벽하게 숨기는 것은 어렵지만, key가 노출되어도 악용할 수 없도록 잘 대응해두자.
    2. hash를 이용하여 퀴즈의 정답을 숨기는 로직을 간단하게 구현할 수 있었다.