Wargame/webhacking.kr

Challenge old 60 (300)

마띠(쥔장) 2020. 2. 18. 00:50

<?php
  include "../../config.php";
  if($_GET['view_source']) view_source();
  login_chk();
  echo "Your idx is {$_SESSION['idx']}<hr>";
  if(!is_numeric($_COOKIE['PHPSESSID'])) exit("Access Denied<br><a href=./?view_source=1>view-source</a>");
  sleep(1);
  if($_GET['mode']=="auth"){
    echo("Auth~<br>");
    $result = file_get_contents("./readme/{$_SESSION['idx']}.txt");
    if(preg_match("/{$_SESSION['idx']}/",$result)){
      echo("Done!");
      unlink("./readme/{$_SESSION['idx']}.txt");
      solve(60);
      exit();
    }
  }
  $p = fopen("./readme/{$_SESSION['idx']}.txt","w");
  fwrite($p,$_SESSION['idx']);
  fclose($p);
  if($_SERVER['REMOTE_ADDR']!="127.0.0.1"){
    sleep(1);
    unlink("./readme/{$_SESSION['idx']}.txt");
  }
?>

먼저 PHPSESSID가 is_numeric()에 안걸리면 안되기 때문에 '12345'로 변조해보겠슴다

이후 로그인을 다시 해주고, URL에 ?mode=auth를 입력합니다

코드대로 'Auth~'가 출력되네요

세션 ID를 숫자로 바꾸지 않고 바로 auth mode로 가면 Access Denied가 뜹니다

 

그 다음 코드를 보면

$result = file_get_contents("./readme/{$_SESSION['idx']}.txt");

txt파일을 문자열로 읽어오는 코드인데, idx가 같으면, 'Done!'을 띄우며 문제가 풀려요

하지만 마지막 if문에서 접속한 IP가 127.0.0.1이 아니면 1초 뒤 unlink()로 파일을 삭제해버립니다

 

그런데 접속한 주소가 127.0.0.1이 되게 변조하는 법을 못 알아봤어요..

라업을 찾아보니 Race Condition 문제라는데 개념은 알아도 이게 어떻게 적용되는지 몰라서

한참을 이해 못했는데.. 결국 if문 조건은 아무 관련이 없었고, sleep()이 핵심이었습니다.

 

슬립하는 그 1초 사이에 다른 클라이언트로 똑같이 접속하면

원래 클라이언트와 경쟁해서 flag를 볼 수 있을 것 같다는 생각이 들었어요

그래서 이번엔 크롬이 아닌 익스플로러로 접속했어요

세션 ID를 똑같이 숫자로, 하지만 크롬에서의 '12345'와는 다르게 '123'으로 설정해줍니다

새로고침 후, 재로그인까지 끝내고

양쪽에 두 창을 동시에 띄운 후 1초 안에 크롬-익스 또는 익스-크롬 순으로 새로고침을 누릅니다

이 의미는 하나(먼저 새로고침 누른 브라우저)는 txt파일 생성용으로,

하나(두번째로 새로고침한 브라우저)는 문제 푸는 용으로 쓰겠다는 뜻입니다

제 경우엔 크롬에서 문제가 풀렸으니 익스가 txt 파일 생성용으로 쓰인 거져

 

127.0.0.1이 중요한게 아니라, sleep(1) 사이에 다른 클라이언트가 접속해서

'파일 삭제-파일 생성-문제 해결' 단계가 뒤섞이도록 새로고침을 몇 번 눌러주면,

어느 순간에 파일 삭제보다 문제 해결의 순서가 앞서서 문제가 풀리는.. 겁니다!

728x90