Q.레거시 코드에서 문자열로 조합된 쿼리를 발견했다. 어떤 순서로 조치하겠습니까?
전부 고치기 전에 피해 범위를 좁히는 조치를 먼저 넣습니다.
| 순서 | 조치 | 이유 |
|---|
| 1 | 사용자 입력이 닿는 경로부터 찾는다 | 내부 상수만 조합한 쿼리는 급하지 않다 |
| 2 | DB 계정 권한을 줄인다 | 뚫려도 읽기만, 필요한 테이블만 |
| 3 | 오류 메시지를 감춘다 | 쿼리와 스키마 노출을 막는다 |
| 4 | 위험한 경로를 바인딩으로 바꾼다 | 값 자리를 완전히 막는다 |
| 5 | 식별자 자리는 허용 목록으로 | 컬럼명과 정렬 방향은 바인딩이 안 된다 |
| 6 | 정적 분석을 CI 에 넣는다 | 재발을 막는다 |
1번을 먼저 하는 이유는 레거시가 크면 전수 수정에 시간이 걸리고, 그동안 노출이 계속되기 때문입니다. 2번과 3번은 코드를 거의 안 건드리고 당일 적용할 수 있습니다.
흔한 실수: 전부 한 번에 바꾸겠다고 답하는 것. 규모가 크면 배포 위험이 커지고 그 사이 방치됩니다. 완화와 수정을 나누어 말하는 것이 실무 판단입니다.
Q.정렬 컬럼을 사용자가 고르는 목록 API는 왜 파라미터 바인딩만으로 안전해지지 않나요?
바인딩은 값 자리에만 쓸 수 있고 정렬 대상은 값이 아니라 쿼리 구조의 일부이기 때문입니다.
SELECT * FROM products WHERE category = ? -- 값. 바인딩 된다
ORDER BY ? -- 식별자. 되지 않는다
DB는 실행 계획을 세우기 전에 어떤 컬럼으로 정렬할지 알아야 합니다. 값은 나중에 채워도 되지만 구조는 미리 확정돼야 합니다.
그래서 허용 목록으로 처리합니다.
| 목록 | 내용 |
|---|
| 허용 컬럼 | name, price, created 를 각각 실제 컬럼명에 대응시킨다 |
| 허용 방향 | asc 와 desc 만 받아 ASC, DESC 로 바꾼다 |
| 목록에 없으면 | 기본값으로 대체하거나 400 으로 거부한다 |
흔한 실수: 컬럼명을 이스케이프하거나 특수문자만 걸러 통과시키는 것. 우회 가능성이 남습니다. 입력을 통과시키지 않고 미리 정한 값으로 바꿔치기하는 것이 안전합니다.
Q.ORM을 쓰면 SQL 인젝션이 원천 차단된다고 볼 수 있나요?
아닙니다. ORM은 기본 경로를 안전하게 만들어 주지만 빠져나가는 통로가 있습니다.
| 통로 | 예 |
|---|
| 원시 쿼리 | createNativeQuery, raw, $queryRaw 로 문자열을 조합 |
| 식별자 지정 | 정렬 컬럼, 테이블명을 동적으로 넣는 API |
| 조건 조립 문법 | 일부 ORM 의 where 문자열 표현식 |
| 함수와 연산자 이름 | 집계 함수나 연산자를 문자열로 받는 경우 |
ORM 을 쓰는 팀에서 사고가 나는 자리는 대개 성능 튜닝이나 복잡한 통계 쿼리 때문에 원시 쿼리로 내려간 곳입니다.
흔한 실수: ORM 도입을 대책으로 답하고 끝내는 것. 원시 쿼리 사용 지점을 목록으로 관리하고 그 부분만 정적 분석이나 리뷰로 지키는 것이 실제 대책입니다. 그리고 ORM 은 인젝션과 별개로 접근 제어를 해주지 않습니다.
Q.인젝션이 이미 발생했다고 가정할 때, 피해를 줄이기 위한 설계 장치는 무엇이 있나요?
방어가 뚫린 뒤에도 피해를 줄이는 장치를 미리 둡니다.
| 장치 | 줄이는 피해 |
|---|
| DB 계정 권한 최소화 | 읽기 전용 계정이면 데이터 변조와 삭제를 막는다 |
| 테이블과 컬럼 단위 권한 | 결제 정보 테이블에 접근 자체를 막는다 |
| 민감 컬럼 암호화 | 덤프가 나가도 평문을 얻지 못한다 |
| 쿼리 로그와 이상 탐지 | 평소와 다른 대량 조회를 잡는다 |
| 응답 크기 제한과 호출 한도 | 한 번에 전체를 빼가는 것을 늦춘다 |
| 오류 메시지 은닉 | 스키마 파악을 어렵게 한다 |
핵심 발상은 뚫린다는 가정 아래 설계하는 것입니다. 애플리케이션이 필요한 최소 권한만 가지면 인젝션의 결과가 "그 계정이 할 수 있는 일"로 제한됩니다.
흔한 실수: 방어 하나로 끝났다고 보는 것. 바인딩을 했더라도 라이브러리 취약점이나 놓친 경로가 있을 수 있어, 피해 축소 장치가 함께 있어야 합니다.
먼저 스스로 답해보고 아래 답변과 견줘보세요. 막히는 부분은 문제로 확인할 수 있어요.
읽었으면 문제로 확인해보세요
보안 문제를 풀면 틀린 문제가 자동으로 노트에 쌓입니다. 가입 없이 5문제를 먼저 풀어볼 수도 있어요.