SQL 인젝션 방어 전략: OWASP와 CISA 권고사항 활용하기
작성자: 니콜 홀든 2024년 4월 29일
SQL 인젝션: 위험성과 사례의 공통점
2024년 3월, CISA는 SQL 인젝션(SQLi)과 관련된 다음과 같은 권고문을 발표했습니다: “디자인부터 안전: 소프트웨어에서 SQL 인젝션 취약점 제거“. SQL 인젝션은 데이터베이스 관리자와 개발자가 방어해야 할 가장 널리 퍼져 있고, 파괴적인 취약점 유형 중 하나입니다. CISA에 따르면, “SQL 인젝션 취약점은 사용자 입력을 SQL 명령에 직접 삽입함으로써 공격자가 임의의 쿼리를 실행할 수 있도록 하는 것이다. 이는 소프트웨어 개발자가 보안 모범 사례를 따르지 않아 데이터베이스 쿼리와 사용자 제공 데이터를 혼합하기 때문에 발생한다”고 합니다.
SQL 인젝션이 악용되면, 공격자는 민감한 데이터에 무단 접근하거나 데이터베이스 내용을 수정하며, 심지어는 서버에서 임의의 명령을 실행할 수도 있습니다. 성공적인 SQL 인젝션 공격의 결과는 고객 정보의 유출, 금전적 손실, 평판 훼손, 규제적 제재와 같은 치명적인 결과를 초래할 수 있습니다. SQL 인젝션은 데이터 유출, 시스템 파괴 등 심각한 결과를 초래할 수 있는 강력한 보안 위협으로, 주요 위험성은 다음과 같습니다:
1. 민감한 데이터 유출 및 인증 우회
공격자는 SQL 인젝션을 통해 사용자 이름이나 비밀번호 등 민감한 개인정보 데이터를 탈취할 수 있으며, 로그인 시스템을 우회하여 별다른 인증 없이 관리자 권한을 획득할 수 있습니다.
2. 데이터베이스 조작
공격자는 SQL 인젝션을 통해 데이터를 삽입, 수정, 삭제하거나 전체 데이터베이스를 삭제할 수도 있습니다.
3. 시스템 명령 실행
일부 데이터베이스는 SQL 인젝션을 통해 운영 체제 명령어를 실행할 수 있는 취약점이 존재하기 때문에 공격자가 이를 통해 악성 코드를 설치하거나 시스템 파일을 삭제하는 등의 명령을 실행할 수 있습니다.
실제 사례
2017년 미국의 신용평가 회사인 Equifax는 SQL 인젝션 취약점을 공격받아 1억 4,300만 명의 고객 데이터를 유출 당했고, 2014년 Yahoo는 SQL 인젝션 공격으로 인해 약 5억 개의 사용자 계정이 노출되는 대규모 데이터 유출 사고를 겪었습니다.
SQL 인젝션 사례의 공통점
1. 대부분의 공격은 입력값 검증 부족이나 보안 설정 미비로 인해 발생함
2. 금융, 교육, IT 등 다양한 산업 분야에서 발생하며, 민감한 데이터 유출로 이어짐
3. 피해 규모가 크며 기업 평판과 재정적 손실에 심각한 영향을 미침
SQL 인젝션은 여전히 많은 조직에 심각한 위협으로 작용하고 있습니다. 이를 방지하기 위해 입력값 검증, 준비된 명령문, 최소 권한 원칙 등의 방어 전략을 반드시 적용해야 합니다.
SQL 인젝션: 효과적인 방어 전략
다행히도, 이러한 공격 유형을 방어하기 위한 확립된 모범 사례를 적용할 수 있습니다. CISA 권고사항뿐만 아니라 **OWASP(Open Web Application Security Project)**도 SQL 인젝션 방지를 위한 지속적으로 업데이트된 지침을 제공합니다. 입력 검증, 신뢰할 수 없는 데이터 이스케이핑, 준비된 명령문 사용, 저장 프로시저 및 코드 리뷰 등은 SQLi와 그로 인한 손상을 방지하는 데 도움이 될 수 있습니다. 또한 최소 권한 원칙을 적용하여 데이터베이스 요청을 보내는 서비스 계정이나 애플리케이션의 권한을 제한하면 SQLi 공격이 발생했을 때 영향을 줄일 수 있습니다.
EDB(Postgres Advanced Server, EPAS)를 사용하는 고객은 SQL Protect와 Privilege Analysis 같은 도구를 활용하여 위의 모범 사례와 결합해 SQL 인젝션 방어를 강화할 수 있습니다.
입력 검증
입력 검증은 SQL 인젝션 방지를 위한 주요 방법이 되어선 안 되지만, 데이터 흐름 초기 단계에서 위험을 줄이는 데 기여할 수 있습니다. OWASP는 입력 검증 전략을 **구문적 검증(syntactic validation)**과 **의미적 검증(semantic validation)**의 두 가지로 나눕니다. 구문적 검증은 구조화된 필드의 올바른 구문을 강제하며, 의미적 검증은 특정 비즈니스 맥락에서 값의 정확성을 보장합니다.
PostgreSQL 사례
언어별 입력 검증 외에도 데이터베이스를 설계할 때, 특히 **체크 제약 조건(check constraints)**을 사용하는 것은 SQL 인젝션(SQLi)에 대한 또 다른 방어선이 될 수 있습니다. PostgreSQL 문서에서 체크 제약 조건에 대해 다음과 같이 설명합니다.
“체크 제약 조건은 가장 일반적인 제약 조건 유형입니다. 이는 특정 열의 값이 부울(참/거짓) 표현식을 충족해야 한다고 지정할 수 있도록 합니다. 예를 들어, 제품 가격이 양수여야 한다고 요구하려면 다음을 사용할 수 있습니다.”
sql코드 복사/* 양수 제품 가격을 요구하는 체크 제약 조건 추가 */
CREATE TABLE products (
productnum integer,
name text,
price numeric CHECK (price > 0)
);
이 작업은 기존 데이터베이스에서도 ALTER TABLE을 사용하여 수행할 수 있습니다. ADD table_constraint, ALTER CONSTRAINT, DROP CONSTRAINT와 같은 하위 명령도 이를 지원하기 위해 존재합니다.
신뢰할 수 없는 데이터 탈피
OWASP의 “데이터 인코딩 및 이스케이핑 체크리스트“는 이스케이핑이 SQL 인젝션(SQLi) 같은 공격을 방지하기 위해 데이터를 안전하게 포맷하는 방법이라고 설명합니다. 이스케이핑은 신뢰할 수 있는 라이브러리의 함수를 사용하는 것이 좋습니다.
PostgreSQL 사례
예를 들어, PostgreSQL C 라이브러리(libpq)에는 명령 실행 함수와 함께 사용할 수 있는 내장 이스케이핑 함수가 포함되어 있습니다. PQescapeLiteral은 SQL 명령에 포함될 문자열을 이스케이핑하는 데 사용됩니다. 공식 libpq 문서에 따르면, “이 함수는 SQL 명령에서 데이터 값을 리터럴 상수로 삽입할 때 유용합니다. 따옴표나 백슬래시와 같은 특정 문자는 SQL 파서에 의해 특별히 해석되지 않도록 이스케이핑되어야 합니다.”라고 되어 있습니다.
이 라이브러리에는 이 외에도 유용한 이스케이핑 함수들이 포함되어 있습니다. 예를 들어, PQescapeByteaConn은 이진 데이터를 이스케이핑하는 데 사용되며, PQescapeIdentifier는 테이블 이름과 같은 SQL 식별자로 사용되는 문자열을 이스케이핑하는 데 사용됩니다. 입력 검증과 마찬가지로, 이러한 내장 함수를 사용하는 것이 “직접 구현”하는 것보다 더 나은 모범 사례입니다.
준비된 명령문, 매개변수화된 쿼리 및 저장 프로시저
CISA 권고문에서는 SQL 인젝션을 방어하기 위한 주요 접근 방식으로 매개변수화된 쿼리를 권장합니다. 권고문에 따르면, **”소프트웨어 제품을 설계하고 개발하는 동안, 개발자는 준비된 명령문을 사용하는 매개변수화된 쿼리를 활용하여 SQL 코드와 사용자 제공 데이터를 분리해야 한다. 이러한 분리는 시스템이 사용자 입력을 실행 가능한 코드가 아닌 데이터로 처리하도록 보장하며, 악성 사용자 입력이 SQL 명령문으로 해석되는 위험을 제거한다.”**고 명시되어 있습니다.
매개변수화된 쿼리는 코드에서 SQL 문과 함께 값을 전달하며, 제공된 값이 삽입될 자리표시자가 포함된 쿼리입니다. **준비된 명령문(prepared statement)**은 매개변수를 수용할 준비가 된 사전 컴파일된 쿼리를 참조합니다. **저장 프로시저(stored procedure)**는 애플리케이션에서 자주 사용되는 쿼리 시퀀스를 저장할 수 있는 명령 집합입니다. 준비된 명령문과 저장 프로시저는 SQL 인젝션 방어에 함께 사용될 수 있습니다.
저장 프로시저는 적절히 사용될 경우 추가적인 이점을 제공합니다. 이는 한 번 컴파일된 후 실행 가능한 형태로 저장되므로 성능이 향상됩니다. 실행 가능한 코드는 캐시되며, 메모리 요구량을 줄입니다. 저장 프로시저는 재사용 가능한 코드, 더 쉬운 유지 보수, 개선된 보안을 지원합니다. 프로시저는 수행되는 프로세스와 활동을 제어하여 데이터베이스 객체를 보호하고 보안을 간소화합니다. 또한, 공격자가 프로시저 내부의 SQL 문에 명령을 삽입하기가 더 어렵습니다.
PostgreSQL 사례
/* Inserting data using a procedure */
procedure_demo=# CREATE OR REPLACE PROCEDURE genre_insert_data(GenreId integer, Name character varying)
procedure_demo-# LANGUAGE SQL
procedure_demo-# AS $$
procedure_demo$# INSERT INTO public.Genre VALUES (GenreId, Name);
procedure_demo$# $$;
CREATE PROCEDURE
procedure_demo=# CALL genre_insert_data(26,'Pop');
CALL procedure_demo=# select * from public.Genre where GenreId = 26;
코드 리뷰
코드 리뷰를 수행하는 데에는 다양한 방법론이 있습니다. 단독 리뷰, 페어 프로그래밍, 소규모 팀 리뷰, 크로스 펑셔널 리뷰 등 어떤 방식을 선택하든, 코드 리뷰를 통해 보안 코드 요구 사항을 준수하도록 하면 앞서 언급된 모범 사례들이 일관되게 사용되고 구현될 수 있습니다. 코드 리뷰의 궁극적인 목표는 코드 품질을 향상시키고, 팀 내 협업을 촉진하며, 보안 실천 사항의 책임감을 모든 팀원에게 분산시키는 것입니다.
최소 권한 원칙(Principle of Least Privilege)
최소 권한 원칙은 사용자가 수행해야 할 작업에 필요한 최소 수준의 액세스 또는 권한만을 부여하도록 권장하는 보안 원칙입니다. SQL 인젝션 공격의 영향을 제한하기 위해 최소 권한 원칙을 적용하려면 데이터베이스 사용자와 애플리케이션이 SQL 쿼리를 실행하고 데이터를 액세스하는 데 필요한 권한만 가지도록 해야 합니다. 예를 들어, 사용자가 특정 테이블의 데이터를 읽기만 해야 한다면 전체 데이터베이스에 대한 읽기-쓰기 권한 대신 해당 테이블에 대한 읽기 전용 권한을 부여하는 방식으로 SQL 삽입 공격 시 발생할 수 있는 영향을 줄일 수 있습니다.
최소 권한 원칙은 앞서 언급된 저장 프로시저와도 함께 작동합니다. 데이터베이스 작업을 캡슐화하고 액세스 제어를 강화하기 위해 특정 작업에 대해 저장 프로시저를 정의하고, 해당 프로시저에 대해서만 실행 권한을 부여함으로써 기본 테이블에 대한 직접 액세스를 제한할 수 있습니다. 이를 통해 SQL 삽입 취약점을 예방할 수 있습니다.
EDB의 SQL Protect와 Privilege Analysis
EDB Postgres Advanced Server(EPAS)를 사용하는 고객을 위해, EDB는 앞서 설명된 모범 사례와 결합할 수 있는 도구와 기능을 제공합니다.
첫 번째로, SQL Protect는 들어오는 쿼리를 검사하고, 서명을 사용해 잠재적인 공격을 식별하며, 보호된 역할을 기반으로 쿼리를 모니터링하고, 공격 시도에 대한 포괄적인 통계와 기록을 제공합니다. SQL Protect는 악성 쿼리가 탐지되었을 때 경고를 보내도록 구성할 수 있어, 공격 시도에 대한 신속한 대응이 가능하도록 합니다.
두 번째로, Privilege Analysis는 EPAS v16에 새로 도입된 기능으로, 불필요하게 부여된 권한을 식별하는 데 도움을 줍니다. EDB는 “사용되지 않은 권한 식별 방법(How to Use Privilege Analysis to Identify [Un]Used Privileges)”이라는 튜토리얼을 제공하고 있습니다. 이 기능은 “사용 중이거나 사용되지 않은 권한을 분석”하여 관리자가 사용자가 업무를 수행하는 데 필요한 권한과 액세스만 보유하도록 확인할 수 있도록 도와줍니다.
결론
SQL 인젝션(SQLi)은 여전히 가장 널리 퍼져 있으며 치명적인 취약점 중 하나이지만 이를 방지하기 위한 효과적인 방법이 존재합니다. 널리 알려져 있고 잘 지원되는 보안 코드 관행과 코드 리뷰를 결합하면 소프트웨어를 안전하게 유지할 수 있습니다. 대부분의 경우, 이러한 방어 조치를 구현하면 성능 향상, 코드 유지 보수 용이성 증가, 개발 팀 내 보안 코딩 지식 전파와 같은 추가적인 이점을 제공합니다.
CISA 권고문은 또한 투명성과 소프트웨어 보안을 위한 책임을 포함하여 보안 목표를 달성할 수 있는 조직 구조를 구축하는 것의 중요성을 강조합니다. 이러한 투명성의 요구를 지원하기 위해, 향후 게시물에서 거버넌스가 보안 관행을 지원하는 데 있어 직면하는 도전과 중요성에 대한 추가 정보를 공유하고, 우리의 관행에 대한 더 많은 세부 정보를 제공하며, 새롭게 등장하는 보안 권고와 규정을 지속적으로 최신 상태로 유지할 것입니다.
SQL 인젝션(SQLi) FAQ:
Q1: SQL 인젝션은 얼마나 흔한 보안 위협인가요?
A: SQL 인젝션은 OWASP Top10에서 상위권에 포함될 정도로 오래된 위험이며, 여전히 많은 애플리케이션에서 발견됩니다. 공격자는 SQL 인젝션을 통해 데이터베이스의 민감한 정보를 탈취하거나, 데이터를 수정 및 삭제하며, 심지어는 서버의 운영 체제에 접근할 수도 있습니다. 따라서 모든 애플리케이션 개발자는 이를 방지하기 위한 적절한 보안 조치를 취해야 합니다.
Q2: SQL 인젝션 공격 유형에는 어떤 것들이 있나요?
A: SQL 인젝션은 공격 방식에 따라 여러 유형으로 나뉩니다. 오류 기반(Error-based SQL Injection), UNION 기반(Union-based SQL Injection), 저장 프로시저 기반(Stored Procedure Injection), 블라인드(Blind SQL Injection) 등 다양한 유형이 존재합니다.
Q3: SQL 인젝션 공격은 특정 데이터베이스에만 영향을 미치나요?
A: 아니요, SQL 인젝션은 SQL을 사용하는 모든 데이터베이스 관리 시스템(DBMS)에 영향을 미칠 수 있습니다. My SQL, PostgreSQL, Oracle Database, SQLite 등 모든 DBMS가 영향을 받을 수 있기 때문에 데이터베이스 유형에 관계없이 보안 조치를 적용하는 것이 중요합니다.
본문: Protecting Against SQL Injection
EDB 영업 기술 문의: 02-501-5113
이메일: salesinquiry@enterprisedb.com
홈페이지 문의: https://www.enterprisedb.com/contact_kr