1. 문제분석 & 풀이
문제에 접속하면 파일을 업로드 할 수 있게 되어있다.
소스를 분석해보자.
1. 업로드한 파일의 이름을 $fn에 저장한다. (3번줄)
2. $fn을 여러번의 문자열 치환과정을 거친다. (4~7번줄)
3. $cp에 임시파일경로를 저장한다. (9번줄)
4. 임시로 저장된 파일을 ./{$upload_dir}/{$fn} 경로에 복사한다. (10번줄)
5. ./{$upload_dir}/{$fn} 파일을 열어서 flag값을 쓴다. (11~13번줄)
결론적으로 flag를 얻는것이 목표고 flag를 얻기위해서는 "./{$upload_dir}" 가 무엇인지 알아내서 flag 파일의 경로를 알아내야한다.
그러나 주어진 소스에는 {$upload_dir} 가 무엇인지 나오지 않아서 정상적인 방법으로 알아낼 수는 없다.
../ 를 파일이름에 넣어서 값을 전송해 copy() 부분에서 파일을 복사하는 경로를 조작해보려했지만 2번 과정에서 문자열 치환 과정을 통해 막아놨다.
어떻게하면 경로를 확인할 수 있을까?라고 생각하던중 이런글을 봤다.
파일시스템에서 파일경로의 최대글자가 256자로 제한되어있다는 것이다!
그렇다면 파일을 업로드할때 파일이름을 256자가 넘는 값으로 조작하면 오류가 발생하지 않을까?
개발자도구의 console 탭을 이용해서 257자리의 문자열을 만들고 복사했다.
그 후 아무파일이나 업로드하여 버프스위트를 이용해 패킷을 잡아보니 filename 부분이 있다.
아까 복사했던 257자리 문자를 filename의 값으로 바꿔 패킷을 조작 후 전송해봤다.
경고창이 떴다!!!!
소스의 21번줄인 copy() 함수에서 오류가 발생했다고 하면서 copy() 안에 인자인 경로를 보여주고있다.
파일이 업로드되는 경로를 알아냈으니 아무파일이나 업로드하고 직접 경로로 접속해 flag값을 확인해보자!
클리어!!
2. reference
https://ko.wikipedia.org/wiki/%EA%B8%B4_%ED%8C%8C%EC%9D%BC_%EC%9D%B4%EB%A6%84