LEVEL 2: Dream Gallery

https://dreamhack.io/wargame/challenges/552

환경


  • Flask에서 동작하는 웹 애플리케이션.
  • [/view] 페이지에서 서버에 등록된 이미지들을 출력.
  • [/request] 페이지에서 URL을 통해 업로드.
  • [/upload] 페이지에서 파일을 등록하여 업로드.


접근


  • [/request]에서 브라우저를 통해 내부 파일을 업로드할 수 없도록 url 파라미터의 입력 값이 “file://”으로 시작되거나 “flag” 문자열이 포함되면 업로드를 하지 않도록 필터링한다.
  • url 파라미터에 “file:///flag.txt“를 전달하는 것을 목표로 한다.


풀이


  • 웹 브라우저에 “file://”으로 scheme을 완성하지 않아도 내부 파일에 접근이 가능하다. 아래의 이미지와 같이 “file:/home/kali”를 전달하면, 내부에서는 “file:///home/kali”로 자동 완성이 되고, 정상적으로 페이지를 불러온다. 문제의 url 파라미터는 입력 값에서만 검사하기 때문에, 입력 값을 “file:“로 하면 해당 필터링을 우회할 수 있다.
  • 플래그 파일을 읽기 위해 경로 필터링 중 “flag”를 우회해야 한다. 웹에서 요청을 전송할 때, URL 인코딩을 수행한다. 그리고 서버에서 동작할 때 디코딩된다. 그리고 서버 내부에서 mini_database 배열에 저장할 때 URL 디코딩을 한 번 더 수행한다. 그러므로 총 2번의 URL 디코딩을 수행한다. 그러나 “flag” 필터링은 URL 디코딩이 한 번 일어났을 때 검사를 수행하므로, 요청 값을 두 번 인코딩하면 “flag” 필터링을 우회할 수 있다.
    • “f” 문자를 URL 인코딩하면 %66이다. 그리고 한 번 더 인코딩하면 %2566이 된다.
빨간 박스로 표시한 부분이 서버에서 동작할 때 URL 디코딩 되는 부분이다.


플래그 획득 과정


  • /request 페이지에서 아래와 같이 페이로드를 입력하고 전송.
  • /view 페이지에 flag.txt의 값이 담긴 이미지를 출력.
  • 추가된 이미지를 [새 탭에서 이미지 열기]로 base64로 인코딩된 플래그 값을 볼 수 있다.
  • 인코딩된 플래그를 디코딩하면 플래그 획득.


참고 자료


https://www.w3schools.com/tags/ref_urlencode.ASP

Published by