ROOTME] SQL Truncation

노션으로 옮김·2020년 3월 24일
0

wargame

목록 보기
23/59
post-thumbnail

문제

유저를 가입할 수 있는 Register 페이지와

관리자 비밀번호를 요구하는 관리자 페이지가 존재한다.


풀이

sql 특징

먼저 sql에서 데이터를 조회할 때의 특징을 이해해야 한다.

  1. sql에서는 'admin '과 같은 공백을 포함한 데이터를 insert할 수 있으며
  2. 다음 쿼리의 결과로
select * from myTable where username='admin'

'admin''admin ' 모두 반환된다.

공백 삽입 injection

문제로 돌아와서 다음의 형식으로 가입을 시도하면

id: 'admin '
password: attacker's password

안 된다.
아마 php 코드에서 trim 함수로 끝부분의 공백을 제거하기 때문에
sql문으로 사용되는 id값은 'admin'이 된다.
기존에 'admin'이 존재하기 때문에 실패하는 것이다.

truncation attack

그렇다면 id 값을 다음과 같이 시도해볼 수 있다.

'admin                        cut'

중간에 삽입된 공백은 trim 함수에서 제거되지 않는다.
sql 쿼리로 그대로 사용된다.

sql에서 id값의 길이를 제한했을 것이다. 그렇게 되면 뒤의 cut 단어는 무시되고 최대길이까지의

'admin                 '

만 DB에 저장된다.
그리고 admin으로 로그인을 시도하면, 내가 가입한 'admin 공백'의 값이 우선적으로 조회되어 내가 입력한 비밀번호로 admin 페이지에 접근할 수 있는 것이다.


부록

의문

본문의 truncation에 해당하는 내용

insert into myTable values('admin                    cut', 'password;);

의 쿼리를 로컬(kali linux, mysql)에서 실행해보면, 쿼리가 실행되지 않고 최대길이를 초과했다는 에러가 발생한다.
PHP로 SQL 쿼리를 실행할 때와 다른 이유가 무엇일까...

quotename

인자로 전달된 문자열에 구분자를 삽입해주는 함수이다.

참고 문서인
http://repository.root-me.org/Exploitation%20-%20Web/EN%20-%20Blackhat%20US%202006%20:%20SQL%20Injections%20by%20truncation.pdf
를 통해 알게된 함수이다.

quotename(인자1, [인자2])

인자2가 없으면, default로 대괄호가 구분자로 사용된다.

PRINT(QUOTENAME ('ABCD')) ==> [ABCD]
PRINT(QUOTENAME ('ABCD','''')) ==> 'ABCD'

참조: https://coding-factory.tistory.com/117

0개의 댓글