현재 웹 상에서 확인할 수 있는 이 프로젝트는 그저 홈페이지 이외에 특이한 점을 찾기 어렵다.
node.js 환경 기반 서버이다. Next.js 프레임워크를 사용한다.
flag는 /flag.txt에 존재한다.
딱히 이 프로젝트에 활용할 취약점이 있어보이는 의존성은 없었다.
해당 파일은 /api/team/?id=x 형태로 호출되며, id 값은 의도상 정규식에 의해 숫자로만 이루어져야 한다. 또한 id 값에 /나 ..이 포함된 경우 Directory Traversal 공격을 방지하는 필터링 로직이 있다.
하지만 여기서 정규표현식은 /^[0-9]+$/m 로 선언되어 있는데, m 플래그는 "multiline" 플래그로 ^, $가 각 줄의 시작과 끝을 의미하게 된다. 따라서 줄바꿈 문자가 있다면 id에 숫자가 아닌 다른 문자가 포함되어도 정규식 검사를 통과할 수 있다.
다음 난관은 ..과 /을 includes 함수를 활용해 필터링하는 로직을 우회해야한다. 그것은 Next.js의 HTTP Parameter Pollution을 통해 구현할 수 있었다. 같은 id를 여러 개 붙여서 정의하면 id는 배열이 되어 저장된다. 따라서 includes 함수는 배열의 원소중 정확히 .. 이나 /을 가지는 원소가 있어야 필터링 로직이 걸린다. 따라서 id=1%0A&id=../../../flag.txt 처럼 요청을 보내면 정규식과 includes 함수를 모두 우회할 수 있다.
이제 slice (0,100) 범위 내의 경로를 정의하여 .png를 날리고 파일을 읽게 해야 flag.txt를 얻을 수 있다.
그래서 우리는 경로를 잘 지정해서 flag.txt를 읽어야한다. 여기서 많이 헤맸는데, 결국 /proc/self/task/{tid}/root/flag.txt 경로를 잘 지정해야한다는 것을 알았다. 이 방법으로 flag를 얻을 수 있다. /proc/self는 현재 실행중인 프로세스의 정보가 있는 곳이다. 여기서 task 폴더에 들어가면 특정 작업을 하고 있는 thread id 폴더가 있는데 여기서 서버가 돌아가는 프로세스인 tid는 무작위로 퍼징을 통해 알아야한다. 결국 이 tid 디렉터리는 결국 또 /proc/self와 같은 디렉터리로 인식이 되므로 root디렉터리도 동일하게 위치해있다. 따라서 이 방법으로 flag를 얻을 수 있다.