kjh00n의 기록저장소

SQL Injection 본문

어플리케이션 보안 운영

SQL Injection

kjh00n 2025. 1. 8. 14:46

SQL Injection

Injection

● 주입 공격

● 데이터 입력이 가능한 위치에 공격을 위한 입력 값을 주입하는 공격

 

SQL Injection

● DB에 직접적으로 전달되는 입력 값에 SQL문이나 DB에서 실행가능한 명령을 삽입하여 인증

● 공격 대상 → DB Server (DB Hacking)

 

Injection Vector

● GET, POST의 매개변수가 SQL Query에 포함되는 위치

● HTTP Request의 Message Header

 

분류

 

Non Blind SQL Injection

● Query의 결과 값이 반환되는 경우 사용

● 공격자가 반환 값을 조작해 공격을 감행하는 형태

● 일반적인 SQL Injection은 Non Blind Injection을 말함

● Query 결과 확인

  • Error Based SQL Injection = 에러 메시지를 이용하는 방법
  • Query Result SQL Injection = Query의 결과를 이용하는 방법

 

Blind SQL Injection

● Query의 결과 값이 반환되지 않는 경우 사용

● 눈에 보이지 않기 때문에 일일이 하나씩 유추해서 원하는 결과를 얻어야 함

● Query 결과 확인

  • Boolen(TRUE, FALSE) SQL Injection = 결과가 참인지 거짓인지에 따라 판단함
  • Time Based SQL Injection
  • → 페이지 응답이 다른 경우에는 응답 페이지에 따라 참/거짓으로 판단
  • → 페이지 응답이 같은 경우에는 Time Base(시간 기반)으로 판단
  • → 참일 때와 거짓일 때 페이지 응답 시간을 다르게 설정해서 Delay 시간에 따라 참/거짓 판단

공격방법

방법①

로그인을 하려고 할 때 사용되는 SQL문이다. ↓

 

select * from member where u_id='' and u_pw=''; 인데 [ ' or '1 ] 문구를 대입해보면

select * from member where u_id='' or '1' and u_pw='' or '1'; 이라는 SQL문이 생성됨

(u_id가 없거나 1일때와 u_pw가 없거나 1일때 라는 조건이 생겨버린다)

조건문에 1을 사용해서 조회하면 모든 목록이 조회되고 0을 사용하면 아무런 값도 조회되지 않는다.1은 항상 참으로 평가되고 0은 항상 거짓으로 평가되기 때문이다.

 

숫자가 꼭 1이 아니어도 된다. 얘는 단순 예시일 뿐이다↓

' or '1 → SQL문의 ID부분에 입력

' or '1 → SQL문의 PW부분에 입력

 

select * from member where u_id='' or '1' and u_pw='' or '1';  ← 조건이 총 4개가 생성되었음

(u_id가 '' 이거나 '1'일 때와  u_pw가 '' 이거나 '1'일 때)

 

'1' and u_pw='' = 거짓

→ u_id='' or 거짓 or '1';

 

u_id='' or 거짓 = 거짓

→ 거짓 or '1' = 참

 

ID와 PW에 ' or '1 값을 대입
로그인 성공
로그인 된 모습

1111111로 로그인 된 이유는 로그인 데이터 저장이 배열로 저장되는데 DB의 맨 첫번째값이 저장되기 때문이다.


방법②

은 MariaDB의 주석 기호이다.

select * from member where u_id='' or '1' #' and u_pw='hello';

# 뒤에 있는 값들은 전부 주석처리되서 작용한다

 

id = 'or 1 #

pw = 아무거나입력 (어차피 주석처리되니까)

ID에 ' or 1 # 을 입력하고 PW에는 아무런 값이나 입력했다
로그인 성공

● 출력된 결과의 행이 여러개인 경우 첫번째 행을 저장하여 로그인 수행

→ 원하는 행의 계정으로 로그인 하고 싶은 경우에는 limit 사용

ID에는 ' or 1 limit 1,1 #을 입력하고 비밀번호는 아무거나 입력
limit 1,1이 되어있으니 2번째 행의 값이 출력
DB에 이렇게 저장되어있다~

 

● 원하는 행이 아닌 원하는 계정으로 로그인하고 싶은 경우

id = root' # 

pw = 아무거나

select * from member where u_id='' or '1' and u_pw=''; 인데

select * from member where u_id='root' #' or '1' and u_pw='';이 되어버린다~

ID에 root' #을 입력하고 PW는 아무거나 입력
root계정인 관리자로 로그인이 되었음

 

 


방어방법

공격방법 ①② 방어

● 로직추가

저 로직때문에 SQL Injection이 가능해지는 것이다 (기존 코드)

rs_arr에 값이 있으면 그 후에 조건문이 실해되는 로직이다.

실제 DB에 ID와 PW가 맞는지 여부는 체크하지 않고 결과가 있는지 여부만 확인한다

이 로직은 입력한 id의 값과 pw의 값이 DB에 저장된 값과 일치해야 로그인이 가능해진다 (변경된 코드)
ID와 PW에 ' or '1 을 대입하여 로그인하려고 해도 불가능해진다
로그인 실패 (지금까지의 방법 모두 똑같다)

 

'어플리케이션 보안 운영' 카테고리의 다른 글

Blind SQL Injection  (0) 2025.01.09
SQL Injection 공격 기법 및 데이터베이스 정보 추출 (board_view.php)  (0) 2025.01.09
CSRF  (0) 2025.01.07
XSS 보안 및 우회  (0) 2025.01.07
XSS  (0) 2025.01.06