문제에 접속하니 소스만 있어서 바로 분석해봤다.
1. id 파라미터가 없으면 id 파라미터 값을 "guest"로 설정한다. (5번줄)
2. id에 addslashes()로 이스케이프 처리를 한다. (8번줄)
3. id에 ( , ) , select , from , 콤마 , by , . 이 있으면 access denied 를 띄우면서 종료된다. (9번줄)
4. id의 길이가 15자리가 넘으면 프로그램 종료된다. (10번줄)
5. sql 쿼리를 실행해서 결과 id가 "admin"이면 문제가 해결된다. (11~14번줄)
select id from chall61 order by id desc limit 1
우선 chall61 테이블에 존재하는 id 값 중 가장 높은 순서의 값이 뭔지 보기 위해 id 파라미터에 id를 넣어서 전송해봤다.
test가 나왔다.
아마 chall61에 있는 id값중 가장 높은 순서의 값이 test 인가 보다.
사실 DB에 admin인 id가 있다면 admin은 가장 낮은 순서의 값일 가능성이 높기 때문에 쿼리에서 desc가 아니라 asc
즉, 오름차순이였더라면 한번에 구했을 지도 모른다...ㅠ
따라서 where 문을 조작하면 해결 되겠지만 select , from 등이 막혀있기 때문에 where 문을 조작하는 것은 불가능 할 것 같다.
여러가지를 생각해봤지만 DB에서 데이터를 꺼내는 방법은 불가능한 것 같다.
그렇다면 select 를 활용해서 직접 "admin"을 만들어서 출력하는 방법이 있을 것이다.
ex) select "admin" 이라는 쿼리를 실행한다면?
admin
-------
admin
위와 같은 결과가 나올 것이다. 이를 활용해서 "admin"을 출력해보자!
근데 여기서 문제가 있다.
소스의 13번줄을 보면 $result['id'] 를 사용하고 있다.
즉, 속성이 id인 데이터의 값이 "admin"이어야 한다는 것인데 위에 방식은 속성이 "admin"인 데이터의 값이 "admin"인 상황이다.
그렇다면 위 결과에서 속성값만 id로 바꿀수는 없을까????
sql의 alias(별칭)을 이용하면 된다!
alias에 관련된 예제를 들어보겠다.
select this_is_my_heart 라는 쿼리를 실행한다면?
this_is_my_heart
------------------
heart
이런 결과가 나온다고 하자.
근데 속성의 이름이 너무 길어서 마음에 들지가 않아서 heart 라고 간단하게 줄여서 출력하고 싶다면? alias(별칭)을 이용하면 된다.
select this_is_my_heart as heart 와 같이 [속성] 뒤에 as를 붙여서 원하는 별칭을 설정할 수 있다.
이 쿼리를 실행한다면?
heart
------------------
heart
이런 결과가 나오며 속성부분이 간단한 별칭으로 바뀌어 출력되는 것을 확인 할 수 있다.
이처럼 select문으로 출력할때 원래 속성명 대신에 별칭을 붙여서 출력하고 싶은 경우 alias를 사용할 수 있다.
그렇다면 이런 alias(별칭)을 이용해서 속성이름만 id로 바꿔주면 우리가 원하는 결과를 출력할 수 있다!
select "admin" as id from chall61 order by id desc limit 1
alias를 이용해서 쿼리를 만들면 위와 같이 만들 수 있다.
그러나 위 페이로드는 정규표현식 필터링과 addslashes()에 의한 이스케이프 처리가 걸리는 점이 몇 가지 있어서 수정해줘야한다.
우선 " 의 경우 이스케이프 처리 때문에 사용할 수 없다.
따라서 "admin"은 0x61646D696E 와 같이 16진수로 우회해야한다.
select 0x61646D696E as id from chall61 order by id desc limit 1
바꾸면 이렇게 나올 것이다.
이제 id 파라미터로 값을 전송해보자!
Access Denied???????
뭐지? 하는 마음으로 소스를 다시 확인해보니 id 파라미터에는 15자리의 제한이 있었다....ㅠ
우리가 보낸 페이로드는 총 18자리로 3자리를 초과한다.
줄여줘야 할 것 같은데 어떻게 줄일까??
사실 sql의 alias(별칭)은 설정할 수 있는 방법이 두 가지다.
첫번째는 위에 설명처럼 as를 이용하는 것
두번째는 as를 생략하고 띄어쓰기 하나로 표현하는 방법이다!
즉, 0x61646D696E as id 는 0x61646D696E id 로 표현해도 똑같은 의미가 된다!
select 0x61646D696E id from chall61 order by id desc limit 1
이것을 이용해 다시 표현하면 위와 같은 쿼리가 완성된다.
id 파라미터에 넣을 값도 정확히 15자리로 이젠 필터링에 걸리지 않을 것이다!
이제 값을 보내보자.
클리어!!