접속하면 소스코드 준다. 근데 github 링크도 줘서 들가보면 문제 아카이빙 되어있는데 아마 정황상 실제 ctf에 출제됐을 당시엔 app.py의 소스코드만 공개되어있던것 같다. (이유는 뒤에 가면 나옴)

 

 

코드오디팅이야 각자 문제 코드 보시고, 중요한 부분만 살펴보면.

 

Exec 함수가 실제 사용자의 input action에 따라 동작을 수행하는 곳이다.

 

특이하게 살펴볼 곳은, if 'scan' in self.action과 if 'read' in self.action이 elif로 묶인게아니라 별도로 if로 되어있는것, 그리고 action을 ==이나 ===으로 일치를 보는게 아니라 'in' 키워드로 문자열에 속하는지를 통해 검증하는것이다.

 

위 코드는 sign값을 만들어내어 유저에게 전달해주는 함수이다. 코드 상 self.action은 scan으로 고정되어있기때문에 read action에 대한 sign값은 os.urandom(16)으로 정해진 secret_key로 해싱하기 때문에 예측할 수 없다. (현재로서는)

 

실제 sign을 만들어내는 함수로써, user input인 action과 param을 받아 secret_key와 더하여 md5 해싱한다.

여기서 주목할 점은 본래 argument가 action, param순으로 되어있는데 구욷이 key+param+action 순으로 더하여 해싱한다는 것이다. (나름의 힌트가 아니었을까)

 

뭐 앞단의 검증들이 끝나면 urllib.urlopen으로 param값을 넘기는 전형적인 ssrf형태의 코드가 나온다.

 

또 뭐 앞에 waf라고 해서 file이랑 gopher 스키마를 막는 구문이 있긴한데 이건 그냥 urllib.urlopen('/etc/passwd')로 하면 바로 파일 접근이 가능하기에 쉽게 우회될 수 있따.

 


 

그럼 이제부터 어떻게 풀어나갈지 한번 살펴보자

 

특이점

1. if elif가 아닌 if if로 되어있음 (앞의 if문이 충족해도 뒤의 if문까지 실행됨)

2. ==, ===가 아닌 in 키워드로 action 값 검증

3. key+param+action 순서의 md5 해싱

4. 굳이 md5로 해싱?

 

이를 살펴보면, 우리가 만약

 

1. 'scanread' 형식으로 action을 준다면?

 - if if로 되어있기 때문에 in 키워드를 if 'scan' in action과 if 'read' in action 조건을 둘다 만족시켜 read 구문까지 실행될 수 있다.

2. key+param+scan + read 형식의 md5를 예측할수있다면?

 - sign값을 알기 때문에 정상 요청이 가능하다!

 

이 문제를 풀기 전에 codegate 2020 csp 문제를 풀어봤기 때문에 length extension attack에 대하여 알고 있는 상태였따.

 

md5에 대한 length extensio attack을 할 수 있는 툴로는 'HashPump'가 있다.

 

이를 통해 length extension attack을 한다면 우리는 scan과 read를 동시에 하며 ssrf를 통한 lfi(local file include)가 가능해질것이다.

 


 

 

action : scan

param : /etc/passwd

일때 sign 값

 

 

known hash와 data1에 data2를 더했을 때의 예측 md5값과 modified data

 

 

실제 요청 쿼리

 - /etc/passwd가 잘 가져와짐!

 

 

 

이제 여기서부터가 실제 ctf랑 달랐던 부분인데,

 

실제 ctf에선 'flag is in ./flag.txt'가 hint로 나왔나보다.

 

근데 난 flag.sh에서 flag경로가 나와서 ('/app/flag.txt') 그냥 바로 /app/flag.txt를 lfi로 가져왔는데, ctf에선 현재경로의 flag.txt를 구하라고 했다.

 

구하는 방법은, /proc/self/cwd/ 는 현재 실행된 프로세스를 실행한 디렉터리와 링킹되어있다.

 

따라서 /proc/self/cwd/flag.txt 가져오면 ./flag.txt와 동일하게 된다.

 

 

flag get!

+ Recent posts