유저를 가입할 수 있는 Register 페이지와
관리자 비밀번호를 요구하는 관리자 페이지가 존재한다.
먼저 sql에서 데이터를 조회할 때의 특징을 이해해야 한다.
'admin '
과 같은 공백을 포함한 데이터를 insert할 수 있으며select * from myTable where username='admin'
'admin'
과 'admin '
모두 반환된다.
문제로 돌아와서 다음의 형식으로 가입을 시도하면
id:
'admin '
password: attacker's password
안 된다.
아마 php 코드에서 trim
함수로 끝부분의 공백을 제거하기 때문에
sql문으로 사용되는 id
값은 'admin'
이 된다.
기존에 'admin'
이 존재하기 때문에 실패하는 것이다.
그렇다면 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 쿼리를 실행할 때와 다른 이유가 무엇일까...
인자로 전달된 문자열에 구분자를 삽입해주는 함수이다.
참고 문서인
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'