시큐어 코딩과 개발보안 도구
보안약점 범주와 정적·동적 분석, 도구 결과의 한계를 구분합니다.
1. 보안약점과 취약점
- 보안약점(Weakness): 설계나 코드에 존재하는 잘못된 패턴 또는 결함 유형
- 취약점(Vulnerability): 특정 제품·버전·설정에서 실제 악용 가능한 구체적 결함
입력을 SQL 문자열에 직접 결합하는 것은 보안약점이다. 실제 위험은 외부 노출 경로, DB 권한과 다른 통제에 따라 달라지지만, 현재 즉시 악용되지 않는다고 안전한 코딩 방식이 되는 것은 아니다.
2. 일곱 보안약점 범주
| 범주 | 핵심 질문 | 대표 예 |
|---|---|---|
| 입력데이터 검증 및 표현 | 외부 값을 올바른 형식과 문맥으로 처리하는가? | SQLi, XSS, 경로·명령 삽입 |
| 보안 기능 | 인증·인가·암호·비밀정보를 안전하게 구현하는가? | 권한검사 누락, 하드코딩 비밀 |
| 시간 및 상태 | 동시성·순서·상태 변화가 안전한가? | Race Condition, TOCTOU |
| 오류처리 | 실패 시 정보와 상태를 안전하게 처리하는가? | 상세 오류 노출, 예외 무시 |
| 코드오류 | 경계·타입·산술·자원을 안전하게 다루는가? | Overflow, Index 오류, Resource Leak |
| 캡슐화 | 내부 데이터와 상태를 최소한으로 공개하는가? | 민감정보 노출, 공유 상태 오염 |
| API 오용 | API의 계약·기본값·실패 동작을 이해하는가? | 위험 함수, Return Value 무시 |
하나의 결함은 여러 범주에 걸칠 수 있다. 분류 이름보다 어느 신뢰 경계에서 어떤 보안 속성이 깨졌는지 판단하는 것이 중요하다.
3. 입력데이터 검증 및 표현
안전한 흐름은 다음과 같다.
정식 Parser로 구조 해석
↓
Type·길이·범위·허용 값 검증
↓
업무 규칙·사용자 권한 검증
↓
해석기별 안전한 API 사용
↓
출력 문맥에 맞는 표현
핵심 원칙:
- Allow-list를 우선한다.
- Decode·정규화 후 검증한다.
- SQL은 매개변수 Binding을 사용한다.
- HTML은 문맥별 출력 인코딩을 적용한다.
- 경로·명령·URL은 구조적으로 분리하고 제한한다.
- 클라이언트-side 검증만으로 서버 측 검증을 대신하지 않는다.
4. 시간 및 상태
여러 요청이 동시에 같은 상태를 읽고 갱신하면 Race Condition이 발생할 수 있다.
잔액 확인 → 출금
재고 확인 → 주문
권한 확인 → 파일 열기
검사와 사용 사이에 상태가 바뀌는 문제를 TOCTOU(Time-of-check to Time-of-use)라고 한다.
대표 대응:
- Transaction과 Atomic Operation
- 적절한 Lock 또는 조건부 갱신
- Unique Constraint
- 동일 요청의 중복 처리를 막는 식별자
- 서버가 관리하는 상태 전이 규칙
단순히 코드 실행 순서를 읽는 것만으로 동시 실행 상황의 안전성을 판단하면 안 된다.
5. API 오용
안전한 API를 선택하고 계약을 정확히 이해한다.
- 위험한 문자열 실행 함수 대신 구조화된 API 사용
- Certificate 검증을 끄는 옵션 사용 금지
- Timeout과 최대 크기 설정
- Return Value와 오류 확인
- 매개변수 순서·단위·기본값 확인
- 폐기되거나 취약한 API를 최신 대체 API로 변경
6. 개발보안 도구
| 도구 | 분석 대상·시점 | 강점 | 한계 |
|---|---|---|---|
| SAST | 소스·Bytecode, 실행 전 | 코드 흐름과 위험 패턴을 빠르게 탐색 | 실행 환경·업무 문맥을 완전히 알기 어려움 |
| DAST | 실행 중인 Web/API | 실제 응답과 배포 설정을 확인 | 코드 내부 원인과 미노출 경로를 놓칠 수 있음 |
| IAST | 실행 중 애플리케이션 내부 계측 | 실행 경로와 코드 위치를 함께 관찰 | Agent·시험 범위 의존 |
| SCA | 외부 Library·Package | 알려진 구성요소 취약점과 버전 식별 | 실제 도달 가능성과 업무 영향은 별도 판단 |
| 비밀값 Scan | 소스·History·Artifact | 노출된 Key·토큰 패턴 탐지 | 발견 후 교체·폐기가 별도로 필요 |
| Fuzzing | 반복·변형 입력 | Crash·예외·경계값 오류 발견 | 업무 권한과 논리 오류는 잘 찾지 못할 수 있음 |
6.1 SAST와 DAST 차이
- SAST는 실행 전 코드를 분석해 위험 흐름을 찾는다.
- DAST는 실행 중인 서비스에 요청을 보내 실제 동작을 관찰한다.
- 둘은 관찰 대상이 다르므로 서로 대체하지 않는다.
6.2 SCA와 비밀값 Scan
SCA는 외부 구성요소의 버전과 알려진 취약점을 확인한다. 비밀값 Scan은 코드·Commit History·Artifact에 노출된 Credential을 찾는다. 비밀값을 파일에서 삭제했더라도 이미 노출됐다면 반드시 교체해야 한다.
6.3 Fuzzing
Fuzzing은 예상하지 않은 입력을 반복해 Crash, Hang, Assertion 실패, 과도한 자원 사용을 찾는다. 입력 형식·크기·상태 순서를 다양하게 시험하되, 인증·인가 같은 업무 의미는 별도 시험가 필요하다.
7. 도구 결과를 해석하는 방법
자동화 도구에는 False Positive와 False Negative가 존재한다.
도구의 탐지 결과 확인
↓
외부 입력 도달 가능성 확인
↓
현재 권한·설정·환경에서 영향 판단
↓
근본 원인 수정
↓
회귀 Test 추가
경고를 모두 무시하거나, 모든 경고를 동일 우선순위로 차단하는 방식 모두 적절하지 않다. 위험과 실제 경로를 기준으로 판단한다.
개념 확인 문제
문제를 누르면 바로 아래에서 정답과 해설을 확인할 수 있습니다.
01SAST와 DAST는 무엇을 대상으로 분석하는가?
SAST는 실행 전 코드·바이트코드 등의 구조와 흐름을, DAST는 실행 중인 서비스의 요청·응답을 분석한다. 서로 관찰할 수 있는 범위가 다르다.
02재고를 확인한 뒤 차감하기 전에 다른 요청이 값을 바꾸는 문제는 무엇인가?
검사와 사용 사이의 상태 변화인 TOCTOU 유형의 경쟁 상태다. 적절한 트랜잭션·원자 연산·잠금·조건부 갱신 등으로 확인과 처리를 안전하게 연결한다.