인터넷은 클라이언트-서버 아키텍처로 동작하며, 웹 서버는 다수의 클라이언트 요청을 처리하고 상호작용한다.
그러나 클라이언트 쪽에서 예기치 못한 악성 코드를 서버로 주입하여 서버를 악용할 수 있다.
이를 인젝션 공격이라 한다.

인젝션(Injection) 공격

  • 애플리케이션 외부에서 코드를 주입하여 애플리케이션을 통제하거나 정보를 탈취하려는 공격

공격 방식

  • 사용자 입력을 통해 서버로 전달된 값을 서버나 데이터베이스에서 실행되도록 하여 의도치 않은 결과를 유발
  • 예: SQL, 명령어(Command), 코드, HTML 태그 등 삽입

서버측 한계

구분 설명
✅ 브라우저 요청 신뢰 가능 (예: 사용자가 실제로 페이지를 클릭함)
❌ 스크립트 요청 악성 코드나 해킹 도구로 생성된 요청 가능성 있음
  • 서버 측에서는 HTTP 요청의 출처를 정확히 확인할 수 없다.
  • 서버는 user-agent 헤더를 통해 출처를 확인할 수 있다.
    ➔ 스크립트와 해킹 도구가 헤더를 스푸핑(spoofing)하여 브라우저 요청과 동일하게 보이도록 위장 가능한 문제점이 존재

방어 방법

방법 설명
✅ 입력값 검증 사용자 입력 필터링 및 유효성 검사
✅ Prepared Statements SQL 인젝션 방지 (쿼리 내 값 바인딩 처리)
✅ ORM 사용 데이터베이스와의 안전한 상호작용 보장
✅ 최소 권한 설정 DB 계정 및 시스템 권한 최소화

1. SQL Injection

  • 공격자가 SQL 구문을 조작하여 데이터베이스에 직접 접근하거나 데이터를 조작하는 공격
  • SQL 문에서 특별한 의미가 있는 제어문자(control character)를 사용하여 문맥을 스킵하고 SQL문 전체의미를 변경한다.
  • 애플리케이션에서 SQL 쿼리를 사용할 때 사용자 입력을 제대로 검증하지 않으면?
    ➔ 해커는 인증을 무시가호 데이터를 마음대로 조작하여 사용자에게 제공된 페이지에 악의적인 자바스크립트 코드를 주입 할 수 있다.

SQL

  • 관계형 데이터 베이스에서 데이터와 데이터 구조를 추출
  • 데이터를 테이블 형식으로 저장하며, 각 테이블의 행은 데이터 항목이다.

웹서버는 상호작용한 HTTP 요청의 일부를 사용하여 DB를 실행하기위한 SQL문을 구성한다.
명령문의 실제 실행은 DB와 통신하는데 사용되는 전용 코드 라이브러리인 데이터베이스 드라이버를 통해 이루어진다.



1. 공격구조

SQL 인젝션 공격은 웹서버가 데이터베이스 드라이버에 전달하는 SQL문을 불안정하게 구성할 때 발생한다.

SQL 인젝션 예시 ( ` 와 – )

아래의 SQL 문은 HTTP 요청에서 가져온 이메일과 암호 매개변수를 사용해서 SQL문에 직접 삽입하기때문에 안전하지 않다.

INSERT INTO users (email, password) VALUES ("kims10@gmail.com", "$10$wlse99");
-- 인젝션 공격에 취약한 SQL문
String sql = "SELECT * FROM users WHERE email ='" + email + "' AND password ='" + password + "'";
statment.executeQuery(sql);

위의 SQL문은 인젝션 공격에 취약하다.
공격자는 입력된 사용자명 필드에 ' OR '1'='1과 같은 코드를 입력하여 로그인 우회를 시도할 수 있다.

` SQL 제어문자 ‘ 는 매배 변수가 확인되지 않아 해커가 웹사이트의 인증 시스템을 우회하도록 입력을 조작할 수 있다.

-- 해커가 인증을 우회하는 SQL 인젝션 사용
statement.executeQuery(
  "SELECT * FROM  users WHERE email='test10@gmail.com' --① 'AND password = $10$wlse99' ② "
);

위의 코드는 해커가 이메일 매개변수를 test10@gmail.com’ 으로 전달하여 SQL문을 일찍 종료하고 암호 검증 로직이 실행되지 않도록 한다. (①까지만 실행되고 ①이후의 모든것(②)을 무시한다)

  • '(단일따옴표)이메일 인수를 조기에 종료
  • --(sql 주석 구문)데이터베이스 드라이버를 속여 암호 확인을 수행하는 구문의 끝을 무시하도록한다.

SQL 인젝션 예시 ( ; )

statement.executeQuery(
  "SELECT * FROM users WHERE email='test10@gmail.com';① DROP TABLE users;② --' AND password='$10$wlse99");

위의 sql 문은 이메일 매개변수를 DROP ABLE ussers;– 로 전달한다.

  • ;(세미콜론)은 첫번째 SQL문(①)을 종료
  • 이후 추가로 테이블을 파괴하는 구문(②)을 삽입하여 데이터베이스를 송상된상태로 만든다.


2. 조치 방법

1. 매개변수화된 구문 사용 (Prepared Statement)

  • 코드에 바인딩(binding) 매개변수 ?를 사용하여 SQL문을 구성
    ➔ 제어문자는 다음 문자를 제어문자로 처리하지 안도록 데이터베이스에 알려주는 이스케이프 문자(escapte character)가 붙는다.

Binding 매개변수 - ?

  • 데이터베이스 드라이버가 입력된 일부 입력으로 안전하게 대체하는 자리 표시 문자
  • 바인딩 매개변수를 포함하는 SQL문prepared statement라고 한다.
-- 바인딩 매개변수를 사용하여 SQL 인젝션 공격에서 보호
String sql = "SELECT * FROM users WHERE email = ? and password = ?"; -- ①
statement.execute(sql, email, password); -- ②
  • ① 은 ?를 바인딩 매개변수로 사용하여 매개변수화된 형태로 SQL 쿼리를 구성한다.
  • ② 는 각 매개변수에 대한 입력값을 구문에 바인딩하여 DB 드라이버에서 임의의 제어문을 안전하게 처리하고, SQL문에 매개변수 값을 삽입하도록 요청한다.

2. ORM (Object-Relational Mapping)

  • 객체(Object)와 관계형 데이터베이스(Relational Database) 간의 데이터를 자동으로 매핑해주는 기술
  • ORM을 사용하면 SQL문을 직접 작성하지 않고, 객체 지향 코드로 데이터베이스 조작 가능 최근에는 많많은 웹 애플리케이션에서 SQL 명시적 작성 대신 추상화된 방식으로 데이터에 접근한다
User.find(email: "test10@gmail.com")
-- ORM이 내부적으로 SQL을 생성하여 실행
  • ORM은 기본적으로 바인딩된 매개변수(Parameter Binding)를 사용하기때문에 SQL 인젝션 공격에 안전
  • 하지만 개발자가 직접 SQL을 작성(raw query)하는 경우 인젝션 공격의 위험이 발생하기때문에 PreparedStatement / 파라미터 바인딩 적용해야한다

3. 추가 조치 : 심층 방어

SQL 인젝션 공격에서 심층 방어는 바인딩 매개변수를 사용하는것이지만, 개발자가 몇가지 단계를 추가하여 피해를 줄일 수 있다.

✅ 최소 권한 원칙(Principle of Least Privilege) 적용
  • 데이터베이스 사용자 계정에 대해 필요한 최소 권한만 부여하여 피해 범위를 최소화

적용 방법

  1. 역할 기반 권한 분리(RBAC)
  • 읽기 전용 API ➔ 읽기 전용 계정 사용
  • 쓰기 작업 필요 시 ➔ 쓰기 권한이 있는 계정으로 제한
  1. DDL 권한과 DML 권한 분리
  • DDL 권한(CREATE, DROP 등) → 운영 중엔 부여 금지
  • DML 권한(SELECT, INSERT, UPDATE, DELETE)만 부여하여 웹 서버의 권한을 제한
  1. 권한 최소화의 효과
  • 백도어 혹은 SQL 인젝션이 발생시, 제한된 권한 때문에 민감한 데이터 접근 및 구조 변경 불가능
    ➔ 이로 인해, 백도어가 있더라도 특정 데이터나 기능에 접근할 수 있는 권한을 제한할 수 있다.
2) blind & nonBlind SQL 인젝션 공격 구분

(1) 비블라인드 SQL 인젝션

  • 공격자가 SQL 쿼리 결과를 즉시 확인할 수 있는 공격
  • 쿼리 결과가 브라우저 또는 응답에 그대로 노출
  • 공격자가 바로 오류 메시지, 데이터, 성공 여부 등을 확인 가능
?id=1 OR 1=1
-- 결과 페이지에 전체 데이터가 노출

(2) 블라인드 SQL 인젝션 (Blind)

  • 쿼리 결과를 직접 확인할 수 없는 경우, 애플리케이션의 반응을 통해 간접적으로 정보 유추
  • 애플리케이션이 직접 결과를 보여주지 않음
  • 대신, 응답 시간, 리디렉션 여부, 에러 발생 여부 등으로 추측
?id=1 AND IF(SUBSTRING(user(),1,1)='r', SLEEP(5), 0)
-- 사용자 이름 첫 글자가 r이면, 5초 지연 → 이를 통해 정보 유추 가능

블라인드 SQL 인젝션

  • 블라인드 SQL 인젝션은 공격자가 쿼리 결과를 직접 확인할 수 없는 상황에서 사용하는 기법
  • SQL 결과를 보여주지 않으므로, 공격자는 쿼리 결과의 참/거짓 여부에 따른 애플리케이션의 반응을 통해 정보를 유추
-- Boolean 기반 블라인드 SQL 인젝션
SELECT * FROM users WHERE id = '1' AND SUBSTRING(password, 1, 1) = 'a';
-- 조건을 변화시키면서 데이터베이스에 대한 정보를 유추

-- 시간 기반 블라인드 SQL 인젝션
SELECT IF(SUBSTRING(password, 1, 1) = 'a', SLEEP(5), 0) FROM users WHERE id = '1';
-- password의 첫 글자가 'a'인 경우 데이터베이스가 5초간 대기하도록하여 간접적으로 SQL 결과를 알아냄

대응 방법

  1. ✅ PreparedStatement / ORM 사용
  • 쿼리 내 파라미터 바인딩으로 입력값을 구분하여 SQL 주입 차단
  1. ✅ 입력값 유효성 검사
  • 입력값 검증을 통해 악의적인 쿼리가 포함되지 않도록한다.
  • 사용자 입력에 특수문자, SQL 키워드 필터링
  • 예상 데이터 유형만 허용 (예: 숫자, 이메일 등)
유형 설명  
Boolean 기반 참/거짓에 따라 응답이 달라지는 점을 이용해 정보 유추
Time 기반 SLEEP() 함수 등을 이용해, 쿼리 실행 시간 지연을 통해 응답 속도 차이를 분석

두 경우 모두 SQL 인젝션 방지를 위해 입력값 검증과 쿼리 파라미터 바인딩이 중요하며, 애플리케이션 로그 및 보안 도구를 통해 이상 접근을 모니터링하는 것도 추가적인 보안 강화 방법이다.

2. Command Injection

  • 애플리케이션에서 운영 체제 명령어를 실행할 때 외부 사용자가 임의의 명령어를 삽입할 수 있는 취약점을 노리는 공격
  • 예: 서버에서 특정 명령을 수행할 때 사용자 입력이 검증 없이 실행될 경우 공격자가 쉘 명령어를 삽입하여 시스템을 악용
ping $USER_INPUT
# $USER_INPUT에 ; rm -rf /와 같은 명령어를 주입하여 서버의 파일을 삭제하는 등의 피해를 입힐 수 있다.

대응 방법

1. 이스케이프 제어 문자

  • SQL 인젝션 공격과 마찬가지로 HTTP 요청에서 입력을 적절히 이스케이스프하여 커맨드 주입을 방지
  • 민감한 제어문자 (&)다른 안전한 문자로 대체(프로그래밍 언어에따라 다름)

2. 최소 권한의 원칙

  • 웹 서버 프로세스는 필요한 권한으로만 실행하여, 웹 서버 프로세스가 읽고 쓸 수 있는 디렉터리를 제한
  • 예: Linux에서 chroot 명령어를 사용하여 프로세스가 지정된 루트 디렉터리 외부에서 탐색되지 않도록 함

3. 네트워크 방화벽 및 접근 제어 목록을 구성하여 엑세스 제한


3. 원격 코드 실행 공격 (Remote Code Execution, RCE)

  • 원격으로 서버내의 코드를 실행할 수 있는 취약점을 노리는 공격
  • 서버에서 동작하는 코드에 악성 코드를 포함해 실행시킬 수 있다
  • 서버의 권한을 탈취하거나 시스템을 제어하는 데 사용
  • 예: 파일 업로드 기능이 있는 웹사이트에서 파일을 검증하지 않고 실행 가능한 스크립트 파일을 서버에 저장하게 하면 공격자가 서버에서 임의의 코드를 실행

대응 방법 직렬화시 공격자가 조작된 직렬화 데이터를 서버에 전달하여 악성 코드를 실행할 수 있다.
Java와 같은 언어에서 역직렬화 과정 중 특정 메서드가 호출될 때 악의적인 객체가 실행될 수 있어 위험하다.

  1. 역직렬화 중 코드 실행 비활성화
  • 신뢰할 수 있는 데이터만 역직렬화되도록 설정
  • 불필요한 역직렬화는 비활성화.
  1. Whitelist 기반 클래스 제한
  • 방식으로 신뢰할 수 있는 클래스만 역직렬화 가능하도록 설정
  • 라이브러리나 프레임워크에서 제공하는 보안 옵션을 활용하여 역직렬화 중 코드 실행을 방지
용어 설명
직렬화 (Serialization) 네트워크를 통해 데이터 구조를 전달하기위한 목적으로 메모리 내 데이터 구조를 이진 데이터의 스트림으로 변환하는 과정
역직렬화 (Deserialization) 이진 데이터가 데ㅔ이터 구조로 다시 변환 될때 다른 끝에서 발생하는 역행 프로세스


4. 파일 업로드 취약점을 이용한 공격

  • 파일 업로드 기능을 통해 서버에 악성 파일을 업로드하고 이를 실행함으로써 서버를 공격하는 방법
  • 예: PHP 웹 서버에서 .php 확장자를 가진 파일을 업로드하고 해당 파일이 서버에서 실행되도록 유도하여 악성 코드를 실행

대응 방법

1. 보안 시스템의 호스트 파일

  • 파일이 저장될 위치와 접근 권한을 엄격히 제한하고, 민감한 시스템 디렉토리에 악성 파일이 업로드되거나 실행되는 것을 방지

2. 업로드된 파일을 실행 할 수 업슨 지 확인

  • 업로드된 파일이 실행되지 않도록 서버 설정을 통해 확장자에 따라 실행 권한을 제한
  • 예: Apache와 같은 웹 서버에서는 .php, .exe와 같은 파일이 특정 디렉토리에서 실행되지 않도록 설정

3. 업로드된 파일으 내용 확인

  • 파일의 확장자만을 확인하는 것이 아니라, 파일의 실제 내용을 검토하여 예상되는 파일 형식과 일치하는지 확인
  • 이미지 파일을 업로드할 경우, 이미지 파일의 헤더를 확인해 파일 내용이 실제 이미지인지 검사하거나, 파일의 MIME 타입을 검증해 악성 파일을 걸러낼 수 있다

4. 바이러스 백신 소프트웨어 실행


방어 방법 요약

1. Prepared Statements 사용

  • SQL Injection을 방지하기 위해 파라미터화된 쿼리를 사용하자.

2. 입력 값 검증

  • 사용자 입력을 철저히 검증하고, 명령어나 코드로 실행되지 않도록 제한하자.

3. 파일 업로드 제한

  • 서버에 업로드된 파일이 실행되지 않도록 MIME 타입 및 확장자를 검증하자.

4. 최신 보안 패치 적용

  • 애플리케이션 및 서버의 최신 보안 업데이트를 유지하여 알려진 취약점을 제거하자.

인젝션 공격에 대한 예방 및 대응은 애플리케이션의 보안을 유지하기 위해 필수적이며, 개발 초기 단계부터 안전한 코딩 방식을 적용하는 것이 중요!

댓글남기기