침투 테스트
고친 사람 github-actions[bot]
침투 테스트는 우리 시스템에서 뚫리는 곳을 공격자보다 먼저 찾아냅니다. 허락을 받은 점검자가 공격자처럼 시험해 봅니다. 보안 전문가가 정해진 기간과 범위 안에서 직접 살핍니다. 자동 도구가 못 보는 설계의 빈틈이 이렇게 드러납니다. 찾은 것은 고칠 방향과 함께 보고서로 돌아옵니다.
쉽고 빠른 이해
침투 테스트는 공격자의 눈으로 우리 서비스를 시험해 뚫리는 곳을 찾아 줍니다. 예를 들어 일반 사용자로 로그인한 요청이 관리자 기능에 닿는지를 확인합니다.
이게 없으면 취약점을 진짜 공격자가 먼저 찾습니다. 코드를 쓴 사람은 자기 설계의 가정을 의심하기 어렵습니다. 자동 도구는 이미 알려진 결함의 모양만 찾습니다.
어떻게 도나:
- 무엇을 언제까지 시험할지 문서로 먼저 합의합니다
- 점검자가 그 범위 안에서 공격자의 방법으로 시험합니다
- 찾은 취약점을 고칠 방향과 함께 보고합니다. 고친 뒤에는 다시 확인합니다
새 서비스를 내놓기 전이나 큰 구조 변경 뒤에 합니다. 사람이 며칠에서 몇 주를 들이므로 자주 하기는 어렵습니다.
결과는 점검한 그때, 그 범위에만 들어맞습니다. 아무것도 안 나왔다고 안전하다는 뜻은 아닙니다.
상세
새 건물의 보안이 궁금한 건물주가 점검원을 부릅니다. 점검원은 잠긴 문과 창문을 하나씩 직접 밀어 봅니다. 열리는 문을 찾아도 안에 들어가 물건을 가져오지 않습니다. 어느 문이 어떻게 열렸는지 적어 건물주에게 건넵니다.
침투 테스트가 소프트웨어에 하는 일이 이것입니다.
침투 테스트는 시스템을 가진 조직의 허락을 받아, 공격자가 쓸 법한 방법으로 그 시스템을 시험하는 보안 점검입니다. 목적은 안에 들어가는 것이 아니라 들어갈 수 있다는 것을 확인해 알리는 것입니다. 그래야 그 조직이 진짜 공격보다 먼저 고칠 수 있습니다.
점검이 찾는 것은 취약점입니다. 공격에 쓰일 수 있는 결함을 이렇게 부릅니다. 예를 들어 일반 사용자로 로그인한 요청이 관리자만 써야 하는 API(Application Programming Interface, 프로그램끼리 부르는 창구)에 닿는다면 그것이 취약점입니다. 그 요청은 거기까지 가면 안 됩니다.
영어로는 penetration testing 입니다. 줄여서 펜테스트라고도 부릅니다. 국내 실무에서는 모의 해킹이라는 말을 같은 뜻으로 자주 씁니다.
허락과 범위가 가르는 선
같은 행동이라도 허락이 있으면 점검입니다. 허락이 없으면 공격입니다. 남의 시스템에 허락 없이 들어가는 일은 대부분의 나라에서 범죄로 다룹니다. 그래서 침투 테스트는 서면 합의부터 합니다.
합의 문서에는 무엇을 시험해도 되는지가 적힙니다. 대상 서버와 도메인 목록, 시험 기간과 시간대, 해서는 안 되는 행동, 문제가 생겼을 때 연락할 사람이 들어갑니다. 목록에 없는 시스템은 아무리 가까이 붙어 있어도 건드리지 않습니다.
해서는 안 되는 행동의 대표가 서비스를 멈추게 하는 시험입니다. 운영 중인 서비스를 점검한다면 사용자에게 피해가 가지 않게 시험의 세기를 미리 정합니다. 운영과 같은 모양으로 따로 띄운 스테이징 환경을 대상으로 삼기도 합니다.
이런 점검이 따로 필요한 까닭
취약점은 대개 설계에 깔린 가정에서 생깁니다. 「이 API 는 우리 앱만 부른다」, 「화면에 버튼이 없으면 사용자는 그 기능을 못 쓴다」 같은 가정입니다. 서버는 요청이 어떤 화면에서 왔는지 가려내지 못합니다. 누구든 요청을 직접 만들어 보낼 수 있습니다. 화면이 숨긴 기능에도 그 요청은 닿습니다.
코드를 쓴 사람은 이 가정을 의심하기 어렵습니다. 자기가 만든 흐름대로 쓰일 것이라고 여깁니다. 테스트도 그 흐름을 따라 짭니다. 침투 테스트는 설계에 참여하지 않은 사람이 그 흐름을 벗어나 보는 점검입니다.
자동 도구와도 보는 것이 다릅니다. 정적 분석이나 취약점 스캐너 같은 도구는 이미 알려진 결함의 모양을 찾습니다. 「이 주문은 주문한 사람만 열어야 한다」 같은 업무 규칙은 도구가 모릅니다. 권한의 경계나 업무 흐름의 틈은 서비스를 이해한 사람이 기능을 엮어 볼 때 드러납니다.
점검이 흘러가는 순서
합의부터 재점검까지, 의뢰한 조직과 점검자가 무엇을 주고받는지 차례로 봅니다. 그림의 대상 시스템은 합의 문서에 적힌 서버와 서비스입니다.
sequenceDiagram
participant 조직 as 의뢰한 조직
participant 점검자
participant 대상 as 대상 시스템
조직->>점검자: 범위 · 기간 · 금지 행동 합의
점검자->>대상: 합의한 범위 안에서 시험
Note over 점검자,대상: 취약점이 성립하는 것까지만 확인하고 멈춘다
점검자->>조직: 보고서
조직->>대상: 고친 코드 배포
점검자->>대상: 재점검
점검자->>조직: 고쳐졌는지 확인 결과
점검자는 취약점을 찾으면 그것이 성립한다는 것까지만 확인합니다. 남의 데이터가 열린다는 것을 한 번 보였으면 더 모으지 않습니다. 이렇게 성립을 보이는 최소한의 확인을 개념 증명이라고 합니다. 영어 이름의 줄임말인 PoC(Proof of Concept)로도 부릅니다.
심각한 취약점은 보고서를 기다리지 않고 바로 알립니다. 운영 서비스에 큰 취약점이 열려 있다면 점검이 끝날 때까지 몇 주를 둘 수 없기 때문입니다. 합의 문서에 적어 둔 연락처가 이때 쓰입니다.
보고서를 받은 조직이 고친 코드를 배포하면 점검자가 같은 항목을 다시 시험합니다. 이 재점검이 끝나야 그 항목이 닫힙니다. 고쳤다고 적는 것과 막혔다는 것을 확인하는 것은 다른 일이기 때문입니다.
점검자가 받는 정보의 양
같은 침투 테스트라도 점검자에게 무엇을 쥐여 주느냐가 갈립니다. 이 양에 따라 흉내 내는 상대가 달라집니다.
| 방식 | 점검자가 받는 것 | 흉내 내는 상대 | 대가 |
|---|---|---|---|
| 블랙박스 | 서비스 주소만 | 아무것도 모르는 바깥 사람 | 안쪽을 짐작하느라 기간의 상당 부분을 쓴다 |
| 그레이박스 | 일반 사용자 계정과 간단한 설명 | 가입한 사용자 · 계정을 뺏긴 사용자 | 두 방식의 중간 |
| 화이트박스 | 소스 코드와 설계 문서 | 내부 사정을 아는 사람 | 가장 깊이 보지만 건넬 자료를 준비해야 한다 |
표의 세 방식은 블랙박스 테스트, 그레이박스 테스트, 화이트박스 테스트라고 부릅니다. 셋은 점검자가 시작할 때 무엇을 아느냐로만 갈립니다. 기간이 같다면 많이 알수록 더 깊은 곳까지 봅니다. 모르는 채로 시작하면 바깥 공격자에 가까운 그림을 얻는 대신 안쪽을 덜 봅니다.
백엔드 서비스에서는 로그인한 사용자끼리의 권한 경계가 자주 문제가 됩니다. 그래서 그레이박스 방식을 많이 씁니다. 이때 역할이 다른 계정을 여럿 건넵니다. 일반 사용자 계정 둘과 관리자 계정 하나가 있으면 「남의 것」과 「윗사람의 것」에 닿는지를 함께 볼 수 있습니다.
보고서를 받은 개발자가 하는 일
보고서는 찾은 취약점마다 네 가지를 적습니다. 어디서 났는지, 어떤 조건에서 다시 나타나는지, 얼마나 위험한지, 어떻게 고치면 되는지입니다.
위험도는 흔히 CVSS(Common Vulnerability Scoring System, 공통 취약점 점수 체계) 같은 점수로 매깁니다. 공격하기 얼마나 쉬운지와 뚫렸을 때 무엇을 잃는지를 따져 숫자 하나로 모은 값입니다. 고칠 순서를 정할 때 이 숫자를 먼저 봅니다.
받은 개발자는 먼저 적힌 조건으로 문제를 재현해 봅니다. 재현이 돼야 고친 뒤에 막혔는지도 확인할 수 있습니다. 재현이 안 되면 점검자에게 조건을 되묻습니다.
고칠 때는 그 한 곳만 막지 않습니다. 한 API 에서 요청한 사용자가 그 데이터의 주인인지 확인하는 코드가 빠졌다면, 같은 방식으로 짠 다른 API 도 빠졌을 수 있습니다. 같은 꼴의 코드를 전부 찾아 고칩니다. 확인하는 코드는 한 곳에 모아 둡니다. 그러면 다음에 새로 만드는 API 가 확인을 빠뜨릴 일이 줄어듭니다.
점검에서 자주 드러나는 설계의 틈
보고서에 되풀이해 오르는 취약점은 몇 가지 설계 습관에서 나옵니다. 개발자가 미리 막아 둘 수 있는 것들입니다. 아래 표는 틈을 부르는 설계와 막는 원칙을 짝지었습니다.
| 드러나는 틈 | 그 틈을 부르는 설계 | 막는 원칙 |
|---|---|---|
| 남의 데이터가 열린다 | 요청에 담긴 번호만 보고 데이터를 내준다 | 서버가 요청마다 주인과 권한을 확인한다 |
| 입력이 쿼리에 섞인다 | 사용자 입력을 문자열로 이어 붙여 쿼리를 만든다 | 입력을 값으로만 넘긴다 |
| 관리 기능이 밖으로 열린다 | 내부에서만 쓰니 안전하다고 여긴다 | 밖에 열 것만 열고 나머지는 인증 뒤에 둔다 |
| 개발용 설정이 운영에 남는다 | 기본 비밀번호와 디버그 모드를 손대지 않고 배포한다 | 운영 설정을 따로 두고 배포 전에 점검한다 |
| 낡은 라이브러리가 남는다 | 의존성 버전을 올리지 않는다 | 알려진 취약점이 있는 버전을 빌드에서 걸러 낸다 |
첫 줄은 접근 제어가 빠진 경우입니다. 누가 무엇을 할 수 있는지 가르는 확인을 접근 제어라고 합니다. 화면에서 버튼을 숨기는 것은 접근 제어가 아닙니다. 서버가 요청을 받을 때마다 「이 사용자가 이 데이터의 주인인가」를 따져야 합니다.
둘째 줄은 입력이 문자열로 SQL(Structured Query Language) 쿼리에 섞이는 경우입니다. 이렇게 섞이면 데이터베이스는 어디까지가 값이고 어디부터가 명령인지 가르지 못합니다. 입력에 명령을 숨겨 데이터베이스가 실행하게 만드는 공격을 SQL 인젝션이라 합니다.
값을 채울 칸을 비워 둔 쿼리를 먼저 보냅니다. 값은 따로 넘깁니다. 그러면 이 섞임이 생기지 않습니다. 이런 쿼리를 프리페어드 스테이트먼트라고 합니다.
셋째 줄은 밖에서 닿을 수 있는 입구를 줄이는 문제입니다. 바깥에서 요청을 보낼 수 있는 주소와 기능 전체를 공격 표면이라고 부릅니다. 입구가 적을수록 점검할 곳도, 뚫릴 곳도 줄어듭니다.
넷째와 다섯째 줄은 코드가 아니라 배포에서 생깁니다. 넷째 줄은 배포 전에 운영 설정을 점검하는 절차로 거릅니다. 다섯째 줄은 의존성 스캔이 빌드마다 잡아 줍니다. 의존성 스캔은 쓰는 라이브러리의 버전을 알려진 취약점 목록과 맞춰 보는 검사입니다.
이런 결함은 사람을 들여 찾기에 아깝습니다. 배포 전 점검과 자동 도구로 미리 치워 두면 침투 테스트가 더 깊은 곳을 봅니다.
옆 활동과 가르는 선
보안 점검 활동은 이름이 비슷해서 자주 섞입니다. 누가 하는지와 무엇을 보는지로 가르면 이렇습니다.
| 활동 | 누가 하나 | 무엇을 보나 | 무엇이 나오나 |
|---|---|---|---|
| 취약점 스캔 | 자동 도구 | 알려진 결함 목록과 맞춰 본다 | 넓고 얕은 경고 목록 |
| 침투 테스트 | 계약한 전문가 | 합의한 범위 전부를 기능을 엮어 가며 본다 | 성립을 확인한 취약점과 고칠 방향 |
| 레드 팀 | 전문가 팀 | 정한 목표 하나에 닿을 수 있나 | 방어하는 쪽이 알아채고 대응하는지 |
| 버그 바운티 | 불특정 다수의 참가자 | 참가자가 고른 곳 | 찾은 건마다 보상하는 신고 |
취약점 스캔과 침투 테스트는 사람의 판단이 들어가느냐로 갈립니다. 스캔은 도구가 목록과 맞춰 보고 경고를 냅니다. 그 경고가 진짜 통하는지 확인하고 기능을 엮어 보는 일은 사람이 합니다.
레드 팀은 범위를 훑는 대신 목표 하나를 정합니다. 그리고 지키는 쪽인 블루 팀에게 대개 미리 알리지 않습니다. 시험하는 것이 시스템의 취약점만이 아니라 조직이 공격을 알아채고 막아 내는 능력이기 때문입니다.
동적 분석과도 겹쳐 보입니다. 동적 분석은 돌고 있는 프로그램에 도구로 입력을 넣어 보며 결함을 찾는 검사입니다. 침투 테스트도 그런 도구를 씁니다. 그리고 그 위에 사람의 판단을 얹습니다.
점검 시기와 결과가 말해 주지 않는 것
침투 테스트는 대개 새 서비스를 내놓기 전과 큰 구조 변경 뒤에 합니다. 로그인 방식을 바꿨거나 외부에 새 API 를 열었다면 그 부분을 다시 봅니다. 규제가 요구하기도 합니다. 카드 결제 정보를 다루는 곳에 적용되는 PCI DSS(Payment Card Industry Data Security Standard, 카드 결제 데이터 보안 표준)는 정기적인 침투 테스트를 요구합니다.
한 번의 점검에는 사람이 며칠에서 몇 주를 들입니다. 그래서 배포할 때마다 돌리는 자동 검사처럼 자주 할 수 없습니다. 그 사이에 바뀐 코드는 다음 점검 때까지 사람의 눈을 거치지 않습니다.
결과는 점검한 그때, 합의한 범위에 대한 것입니다. 범위 밖의 시스템은 보지 않았습니다. 기간 안에 모든 경로를 다 밟지도 못합니다. 그래서 「찾은 것이 없다」는 「이 기간에 이 범위에서 못 찾았다」로 읽어야 합니다.
다른 활동과 겹쳐 씁니다. 설계할 때는 위협 모델링으로 벌어질 공격을 미리 따져 봅니다. 코드를 쓸 때는 정적 분석이, 빌드할 때는 의존성 스캔이 거릅니다. 침투 테스트는 그 뒤에 정말 막혔는지를 사람이 확인하는 단계입니다.
관련 항목
침투 테스트가 찾아내는 취약점
취약점 · 접근 제어 · 권한 상승 · IDOR · SQL 인젝션 · 교차 사이트 스크립팅 · 크로스 사이트 요청 위조 · 보안 설정 오류 · 인증 우회
침투 테스트와 나란히 쓰는 보안 점검 방법
취약점 스캔 · 취약점 스캐너 · 정적 분석 · 동적 분석 · 퍼징 · 보안 코드 리뷰 · 위협 모델링 · 버그 바운티
침투 테스트와 헷갈리는 이웃 활동
레드 팀 · 블루 팀 · 퍼플 팀 · 보안 감사 · 취약점 점검
점검자가 받는 정보에 따른 시험 방식
블랙박스 테스트 · 그레이박스 테스트 · 화이트박스 테스트
침투 테스트 결과를 적고 매기는 잣대
CVSS · CWE · CVE · PoC · 리스크 · OWASP Top 10
침투 테스트를 요구하거나 안내하는 표준과 단체
OWASP · OWASP WSTG · PCI DSS · PTES · NIST SP 800-115
침투 테스트가 드러낸 틈을 막는 설계 원칙과 장치
최소 권한 · 인증 · 인가 · 입력 검증 · 프리페어드 스테이트먼트 · 공격 표면 · 의존성 스캔 · 시크릿 관리
침투 테스트를 품는 보안 개발 체계
스테이징 환경 · 시큐어 코딩 · DevSecOps · 시프트 레프트 · 보안 엔지니어링 · 취약점 관리 · API
다른 이름: penetration testing · penetration test · 펜테스트 · 모의 해킹