홈택스 취약점 신고기: 오픈 리다이렉트부터 CVE·CWE까지

동료 SH님이 일하다가 홈택스 앱에서 이상한 동작을 하나 발견했습니다. “이거 신고해야 하는 거 아니야?” 했더니, 본인은 이런 귀찮은 건 안 한다고 하더군요. 그래서 제가 대신 해 보기로 했습니다.

준비하다 보니 “이런 건 어디에 어떻게 신고하지”, “CVE는 들어봤는데 CWE는 뭐지” 같은 걸 찾아보게 됐고, 알게 된 것들을 정리해 둡니다.

어떤 취약점이었나

홈택스는 웹 링크로 앱의 특정 화면을 열어 주는 앱링크(app link)를 씁니다. 문자나 알림의 링크를 누르면 홈택스 도메인을 거쳐 손택스 앱이 열리는 구조인데, 그 링크는 대략 이렇게 생겼습니다.

https://m.sefd.hometax.go.kr/appLink/?linkUrl=<이동할 주소>

linkUrl에 담긴 주소를 앱이 그대로 웹뷰에 띄웁니다. 문제는 이 값이 국세청 도메인인지 제대로 검증하지 않는다는 점이었습니다. linkUrl에 외부 주소를 넣어 보면, 손택스 앱이 정상적으로 열리면서 그 안에 전혀 상관없는 외부 사이트가 그대로 떴습니다.

이런 걸 오픈 리다이렉트(open redirect)라고 부릅니다. 신뢰받는 도메인이 검증 없이 사용자를 아무 데로나 보내 주는 취약점입니다. 하나만 놓고 보면 “그래서 뭐?” 싶지만, 무서운 건 피싱과 만났을 때입니다.

세금·환급 같은 미끼는 피싱에서 늘 잘 먹힙니다. 거기에 “정부 도메인 링크 + 정부 앱 화면”이라는 외피까지 붙으면, 평소 조심하던 사람도 넘어갈 만합니다. 반면 막는 방법은 그리 복잡하지 않습니다. linkUrl을 파싱해 스킴이 HTTPS인지, 호스트가 허용된 국세청 도메인 목록(화이트리스트)에 있는지 확인하고, 아니면 열지 않도록 막으면 됩니다.

국세청 ‘개선완료’ 답변국민신문고를 통한 국세청의 개선완료 답변

국민신문고로 접수한 뒤 받은 국세청의 ‘개선완료’ 답변. 담당자 실명·연락처는 가렸습니다.

보안 취약점은 어디에 신고하나

막상 접수하려니 창구부터 헷갈렸습니다. 이번에 알아본 창구는 크게 세 곳입니다.

정리하면, 공공·정부 기관의 서비스 문제라면 그 기관에 닿는 경로(국민신문고·NCSC)를, 널리 배포되는 제품의 취약점이라면 KISA를 쓰면 됩니다. 민간 서비스라면 해당 업체의 공식 보안 신고 채널을 먼저 확인하는 게 맞습니다. 참고로 저는 NCSC와 국민신문고 두 곳에 모두 넣었는데, ‘개선완료’ 회신은 국민신문고(처리기관 국세청)를 통해 돌아왔습니다.

CVE와 CWE

신고서를 쓰다 보니 근거를 대야 했고, 그러다 CVE와 CWE를 처음으로 구분하게 됐습니다. SI 프로젝트를 할 때 고객사에 컨테이너 이미지를 넘기기 전 Trivy로 취약점을 검사하곤 해서 CVE는 익숙했지만, CWE는 이번에 처음 제대로 들여다봤습니다.

CVE(Common Vulnerabilities and Exposures)는 특정 제품·버전에서 발견된 개별 취약점 하나하나에 붙는 고유 번호입니다. 예를 들어 Log4Shell에는 CVE-2021-44228이라는 번호가 붙어 있습니다. “이 문 하나가 열려 있었다”는 사건 번호에 가깝습니다.

CWE(Common Weakness Enumeration)는 취약점을 유형별로 정리한 분류 사전입니다. 이번에 신고한 오픈 리다이렉트는 CWE-601에 해당합니다. 개별 사건이 아니라 “문을 안 잠그는 실수”라는 분류에 가깝습니다.

그래서 하나의 CVE(구체적 사건)에는 보통 하나 이상의 CWE(원인 유형)가 태깅됩니다. 반대로 제가 신고한 건은 CWE-601 유형이긴 해도 CVE 번호는 붙지 않았습니다. CVE는 주로 배포·판매되는 소프트웨어 제품에 발급되다 보니, 특정 기관이 운영하는 이런 서비스 건에는 잘 붙지 않습니다.

실제로 오픈 리다이렉트(CWE-601)로 분류된 CVE로는 Directus의 CVE-2024-28239, caddy-security의 CVE-2024-21497 같은 사례가 있습니다. 같은 유형(CWE)에 이렇게 여러 사례(CVE)가 달리는 구조를 그림으로 보면 이렇습니다.

CWE-601(오픈 리다이렉트) 하나에 여러 CVE가 달리는 관계도. 실제 예시 CVE-2024-28239, CVE-2024-21497과, CVE가 하나도 없는 이번 홈택스 건

CWE-601(오픈 리다이렉트) 같은 ‘유형’ 하나에는 여러 CVE(개별 ‘사례’)가 달립니다. 이번 홈택스 건처럼 CVE 번호가 붙지 않은 취약점도 같은 유형에 속하고요(1 : 0..N). 심각도는 CVSS 점수로 따로 가늠합니다.

찾아보니 이런 분류·평가 체계가 더 있었습니다.

CVE·CWE·CVSS만 구분해도 “어떤 유형의 실수로(CWE) 어디서 터졌고(CVE) 얼마나 위험한지(CVSS)“라는 큰 틀이 잡힙니다.

마무리

대단한 걸 찾은 것도, 제가 찾은 것도 아닙니다. 동료가 무심코 발견한 걸 대신 신고했을 뿐입니다. 그래도 “이상하다” 싶은 걸 그냥 지나치지 않고 제대로 된 창구로 흘려보내는 걸 한 번 해 두니, 다음엔 덜 망설일 것 같습니다. 제가 만드는 서비스에서 링크를 받아 어딘가로 보내는 코드를 짤 때도 목적지 검증 한 번을 꼭 떠올리게 될 것 같고요. 그리고 뭔가 미심쩍은 게 보이면 그냥 넘기지 않고, 늘 쓰던 도구에 더해 AI에게도 한번 봐 달라고 맡겨 볼 생각입니다.

여담으로, 아쉽게도 보상금 같은 건 없었습니다. 국세청에서 ‘개선완료’ 회신 한 통이 전부였죠. 뭐, 바라고 한 일은 아니었으니 그걸로 됐습니다.