[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"work:secret-key:ko":3},[4,16],{"type":5,"items":6},"toc",[7,11,14],{"id":8,"level":9,"title":10},"숨어있는-api-key-어떻게-찾아내지",2,"숨어있는 API Key, 어떻게 찾아내지?",{"id":12,"level":9,"title":13},"검사-절차를-도입하자","검사 절차를 도입하자",{"id":15,"level":9,"title":15},"회고",{"type":17,"html":18},"html","\u003Cp>전임자에게 인수인계를 받은 페이지에 신규 요구사항을 개발하려고 하다가 코드 한 줄을우연히 찾게 되었습니다.\u003C\u002Fp>\n\u003Cp>잘못 본건가 싶었습니다.\u003C\u002Fp>\n\u003Cp>설마 하는 마음으로 브라우저 개발자 도구를 확인해 봤는데, 아주 잘 보이더군요.\u003C\u002Fp>\n\u003Cpre class=\"shiki github-light\" style=\"background-color:#fff;color:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">$.\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1\">ajax\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">({\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">  url: \u003C\u002Fspan>\u003Cspan style=\"color:#032F62\">'https:\u002F\u002Fsome-api.com\u002Fitems\u002Frecommendations'\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">  data: \u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\">JSON\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">.\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1\">stringify\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">(data),\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6F42C1\">  beforeSend\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">: \u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\">function\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">(\u003C\u002Fspan>\u003Cspan style=\"color:#E36209\">xhr\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">){xhr.\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1\">setRequestHeader\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">(\u003C\u002Fspan>\u003Cspan style=\"color:#032F62\">'x-api-key'\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">, \u003C\u002Fspan>\u003Cspan style=\"color:#032F62\">'k8nSt...'\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">)},\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">  ...\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">})\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>곧바로 키를 폐기하고 서버로 로직을 이관하는 핫픽스를 진행했습니다.\u003C\u002Fp>\n\u003Cp>이후 사용 기록을 보니 남용된 것으로 의심가는 흔적은 없었지만, 오래된 JSP 페이지에 노출되고 있던 터라 정확한 유출여부는 확인하기 어려웠습니다.\u003C\u002Fp>\n\u003Cp>이번에는 운이 좋아 발견할 수 있었지만, 다른 페이지에도 같은 문제가 있을 수 있어 관련 레포지토리를 빠르게 전수조사하기로 했습니다.\u003C\u002Fp>\n\u003Ch2 id=\"숨어있는-api-key-어떻게-찾아내지\">숨어있는 API Key, 어떻게 찾아내지?\u003C\u002Fh2>\n\u003Cp>API Key는 공격자가 유추하는 것을 방지하기 위해 대체로 길고 다양한 문자가 불규칙하게 섞여 있습니다.\u003C\u002Fp>\n\u003Cp>\u003Cimg src=\"__WORK_ASSET__api-key-created.webp\" alt=\"\" loading=\"lazy\">\u003C\u002Fp>\n\u003Cp>문자열이 얼마나 불규칙한지는 Shannon 엔트로피를 통해 수치화할 수 있는데요.\u003C\u002Fp>\n\u003Cp>예를 들어 아래 두 문자열의 엔트로피를 계산해 보면, 첫 번째 문자열의 값이 더 높게 측정됩니다.\u003C\u002Fp>\n\u003Cpre class=\"shiki github-light\" style=\"background-color:#fff;color:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">### Shannon 엔트로피 값 비교\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6F42C1\">1.\u003C\u002Fspan>\u003Cspan style=\"color:#032F62\"> A0D28bba7b1287ff432d0b\u003C\u002Fspan>\u003Cspan style=\"color:#032F62\"> :\u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\"> 3.5161\u003C\u002Fspan>\u003Cspan style=\"color:#6A737D\"> # 불규칙하게 섞인 문자열\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6F42C1\">2.\u003C\u002Fspan>\u003Cspan style=\"color:#032F62\"> aaaaaaabbbbbbbbccccccc\u003C\u002Fspan>\u003Cspan style=\"color:#032F62\"> :\u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\"> 1.5820\u003C\u002Fspan>\u003Cspan style=\"color:#6A737D\"> # 소문자 3개를 반복해서 사용\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>첫 번째 문자열은 두 번째 문자열보다 사용된 문자의 종류가 많고, 각 문자의 출현 빈도도 상대적으로 분산되어 있기 때문입니다.\u003C\u002Fp>\n\u003Cp>하지만 Shannon 엔트로피 값이 높다고 무조건 API Key라고 단정지을 수는 없습니다.\u003C\u002Fp>\n\u003Cp>이를테면 UUID도 상당히 높은 엔트로피를 가지고 있습니다.\u003C\u002Fp>\n\u003Cpre class=\"shiki github-light\" style=\"background-color:#fff;color:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6F42C1\">c1b100db-f254-493f-8b53-f0fcab2437d0:\u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\"> 3.7391\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>따라서 엔트로피 값 만으로 API Key 여부를 판별하기는 어렵습니다. 하지만 의심이 가는 문자열 후보를 좁혀주는데에는 충분히 활용될 수 있을 것 같습니다.\u003C\u002Fp>\n\u003Cp>간단한 점검을 위해 소스코드 내 문자열들의 엔트로피 값을 계산하여 보고서 형태로 출력해 주는 스크립트를 만들었습니다. 10개의 레포지토리에서 의심이 가는 문자열을 100개정도 추출했고, 외부에 노출되어있는 Key를 1개 더 발견하여 조치할 수 있었습니다.\u003C\u002Fp>\n\u003Cpre class=\"shiki github-light\" style=\"background-color:#fff;color:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#032F62\">=================\u003C\u002Fspan>\u003Cspan style=\"color:#032F62\"> 탐지된\u003C\u002Fspan>\u003Cspan style=\"color:#032F62\"> 문자열\u003C\u002Fspan>\u003Cspan style=\"color:#032F62\"> 목록\u003C\u002Fspan>\u003Cspan style=\"color:#032F62\"> 예시\u003C\u002Fspan>\u003Cspan style=\"color:#032F62\"> ================\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6F42C1\">EXAMPLE-KEY-8bba7b1287ff432d0b7777532f52fd59ef75cc56d3818b8ed5a8d06\u003C\u002Fspan>\u003Cspan style=\"color:#032F62\"> :\u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\"> 4.3197\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6F42C1\">5b8621ee0cf2475f66709a5d\u003C\u002Fspan>\u003Cspan style=\"color:#032F62\"> :\u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\"> 3.7721\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6F42C1\">eventEntry1Remark\u003C\u002Fspan>\u003Cspan style=\"color:#032F62\"> :\u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\"> 3.4548\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6F42C1\">1842692849310691\u003C\u002Fspan>\u003Cspan style=\"color:#032F62\"> :\u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\"> 2.9056\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6F42C1\">P2018043031858\u003C\u002Fspan>\u003Cspan style=\"color:#032F62\"> :\u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\"> 2.8424\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#005CC5\">...\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\u003Ch2 id=\"검사-절차를-도입하자\">검사 절차를 도입하자\u003C\u002Fh2>\n\u003Cp>이번에 만든 스크립트는 관련 레포지토리를 빠르게 전수조사하기 위한 임시성 도구였습니다.\u003C\u002Fp>\n\u003Cp>당시에 마침 SonarQube를 활용한 정적분석 체계 도입을 검토하고 있었고, SonarQube에도 \u003Ca href=\"https:\u002F\u002Fwww.sonarsource.com\u002Fresources\u002Flibrary\u002Fdetect-secrets-in-the-ide-with-sonarlint\u002F\" target=\"_blank\" rel=\"noreferrer\">Secret 검사 기능\u003C\u002Fa>이 있었습니다. 따라서 스크립트를 별도로 운영하기보다 기존 빌드 흐름에 해당 검사 절차를 포함시키기로 했습니다.\u003C\u002Fp>\n\u003Cp>빌드 과정에서 소스에 대한 정적 분석을 수행하고, 내부 기준을 넘는 이슈가 발견되면 Quality Gate와 빌드가 실패하도록 구성했습니다. 앞으로 같은 유형의 문제가 발생하면 운영 환경에 반영되기 전에 발견하고 조치하는 데에 도움이 될 테죠.\u003C\u002Fp>\n\u003Cp>\u003Cimg src=\"__WORK_ASSET__image.webp\" alt=\"\" loading=\"lazy\">\u003C\u002Fp>\n\u003Ch2 id=\"회고\">회고\u003C\u002Fh2>\n\u003Cp>처음 API Key를 발견했을 때는 당장 눈앞의 문제를 없애는 것만 생각했습니다. 하지만 같은 문제가 재발하지 않도록 새로운 검사 절차를 정착시키는 것은 별개의 문제였습니다.\u003C\u002Fp>\n\u003Cp>엔터프라이즈급 환경에서 안정적으로 오랜 기간 운영이 가능할지 검토하고, 새로운 절차의 필요성에 대해 팀원들을 설득하는 등 신경써야 할 부분이 많았습니다.특히 SonarQube는 모두에게 생소한 도구였기 때문에 바뀐 배포 흐름과 Quality Gate 적용값을 상세히 설명했습니다. 장애 상황에서 필요한 재기동 절차까지 문서로 남겨, 팀 내 지식으로 정착시키는 데에 초점을 두었습니다.\u003C\u002Fp>\n\u003Cp>당장 잘 동작하면 된 것 아닌가 싶을 수도 있지만, 도입한 당사자가 없어도 구축된 시스템은 오랜 기간 잘 돌아가야 하니까요. 회사 입장에서 유지보수가 불가능한 시스템은 운영 리스크가 됩니다. 무언가를 새롭게 만들거나 도입하는 일에는 그에 대한 책임도 따라오는 것 같습니다.\u003C\u002Fp>\n\u003Cp>긴 글 읽어주셔서 감사합니다.\u003C\u002Fp>\n"]