AST로 인증 빠진 엔드포인트를 적발해보자
관리 API가 무인증인 것을 코드를 읽다가 발견했다. 게이트는 그때도 초록불이었다. 자동으로 잡으려고 만든 첫 판은 오탐이 아니라 미탐 기계였다
AST로 인증 빠진 엔드포인트를 적발해보자
AST로 인증 빠진 엔드포인트를 적발해보자
코드를 읽다가 관리용 API에 인증이 안 걸려 있는 것을 발견했다. 테스트는 전부 통과 중이었다. 사람 눈에만 보이는 결함을 기계가 보게 만들고 싶었다.
1. 서론 (Introduction)
- 문제/상황 (Problem): 데이터를 바꾸는 엔드포인트에 인증 의존성이 빠져 있었다. 기능 테스트는 인증을 붙인 상태로만 호출하므로 전부 초록불이었고, 결함은 리뷰 중에 우연히 나왔다.
- 목적 (Purpose): 변경 엔드포인트에 인증이 걸려 있는지를 소스 구조에서 직접 확인해, 리뷰에 의존하던 발견을 반복 가능한 검사로 바꾼다.
- 대상 (Target Audience): 라우터가 늘어나면서 인증 누락을 눈으로 좇고 있는 개발자.
2. 방법 및 과정 (Methods & Process)
배경 조사 및 데이터 (Data Collection): 인증이 걸리는 경로가 하나가 아니라서, 통과 조건을 세 가지로 정리해야 했다.
통과 조건 확인 방법 놓치기 쉬운 지점 라우터 전체에 인증 등록 코드에서 확인 모듈 이름을 적어두면 등록이 바뀌어도 모른다 데코레이터에 직접 인증 데코레이터 인자 검사 의존성 이름이 바뀌면 못 찾음 의도적 공개 경로 화이트리스트 대조 목록이 조용히 늘어남 - 접근 방법 (Approach Methods):
- [방법 1]: 소스를
ast로 파싱해 POST·PUT·DELETE·PATCH 데코레이터가 붙은 함수를 찾는다. 문자열 검색이 아니라 구문 트리를 보므로 주석이나 문자열 안의 비슷한 코드에 속지 않는다. - [방법 2]: 라우터 전체 인증 여부를 등록 코드에서 역산한다. 임포트 구문으로 별칭과 모듈을 잇고, 그 별칭이 인증 의존성과 함께 등록됐을 때만 인정한다.
- [방법 1]: 소스를
- 분석 및 해결 프로세스 (Analysis Flow):
- 도구/기술: 표준 라이브러리
ast만 사용. 웹 프레임워크를 설치하지 않고 소스 문자열을 그대로 파싱한다. - 주요 단계: 등록 코드 파싱해 인증된 라우터 집합 도출 $\rightarrow$ 각 모듈에서 변경 라우트 수집 $\rightarrow$ 세 조건 중 하나도 만족 못 하면 적발.
- 결과 도출 및 검증: 정상 상태에서는 두 방식 모두 무인증 라우트 1건을 똑같이 잡았다. 그다음 등록 코드에서 인증 의존성만 지웠다. 모듈 이름을 하드코딩한 방식은 여전히 1건만 잡아, 새로 무인증이 된
POST /api/v1/agent/targets를 통과시켰다. 역산 방식은 2건을 잡아 그걸 걸러냈다.
- 도구/기술: 표준 라이브러리
3. 결과 (Results)
- 분석 결과 요약: 리뷰로만 발견되던 결함을 종료 코드가 있는 검사로 옮겼다. 다만 이 검사가 못 보는 구멍을 같이 적어뒀다 — GET으로 상태를 바꾸는 엔드포인트는 메서드 기준 스캔 밖이다. 비콘처럼 GET으로 기록을 남기는 경로가 실제로 있어서, 이건 검사 대상이 아니라 화이트리스트와 리뷰로 다룬다.
4. 인사이트 및 액션 (Insights & Action)
- 인사이트 (Insight): 첫 판은 라우터 전체에 인증이 걸린 모듈 이름을 그냥 적어뒀다. 짧고 잘 도는 것처럼 보였는데, 등록에서 인증을 빼는 순간 그 모듈의 모든 변경 라우트가 조용히 통과한다. 오탐이 나면 시끄러워서 고치게 되지만, 미탐은 아무 일도 일어나지 않아서 검사기가 일하고 있다고 착각하게 만든다. 검사기를 만들 때는 “무엇을 잡는가”보다 “가드를 없앴을 때 실제로 빨간불이 되는가”를 먼저 확인해야 한다.
- 실행 방안 (Action Plan): 새 검사기를 붙일 때 그 검사가 막으려는 결함을 일부러 하나 만들어 넣고, 검사기가 실제로 실패하는지부터 본다. 통과만 확인하면 아무것도 검사하지 않는 검사기와 구분되지 않는다.
- 한 줄 결론 (Key Takeaway): 하드코딩한 예외 목록은 오탐이 아니라 미탐을 만든다. 예외는 적어두지 말고 코드에서 역산한다. 샘플 코드
- 다음 스텝 (Next Step): 지금은 인증 의존성의 이름을 하나로 고정해 찾고 있다. 의존성이 여러 개로 늘거나 이름이 바뀌면 그대로 미탐이 되므로, 이름 목록 자체를 등록 코드에서 뽑아내는 방향이 남아 있다.
This post is licensed under CC BY 4.0 by the author.