csrf-1


  • 홈페이지에 접속한 4개의 링크가 나오는데요.
  • 각 링크에 접속해서 기능을 사용하면 아래와 같은 결과를 확인할 수 있습니다.

  • 소스코드를 통해 CSRF 취약점이 존재하는 구간을 확인해보겠습니다.

def admin_notice_flag()

  • 먼저, admin_notice_flag() 함수를 살펴보니, 2번의 검증 로직이 존재합니다.
    • 현재 /admin/notice_flag 경로로 요청을 보내는 주체가 자기 자신이 맞는지를 확인하고,
    • GET 요청 시 함께 넘어온 파라미터(userid) 값이 admin 인지 확인합니다.
  • memo_text 글로벌 변수에 플래그 내용이 추가되기 때문에, 함수 호출만 되면 /memo 경로에서 플래그 확인이 가능하겠네요. (추가로, 처음 확인했을 때 “Access Denied” 응답이 온 건 요청 주체가 호스트 본인이 아니라서 였습니다.)

def flag()

  • 다음으로는 flag() 함수입니다.
  • 이 함수에서는 /flag 경로로 POST 요청 시 넘어온 param 값을 check_csrf 함수에 넘겨주고 있습니다.

def check_csrf(…)

  • check_csrf(...) 함수는 넘어온 값들로 url 변수 값을 새로 설정한 다음 read_url 함수의 인자로 넘깁니다.
  • 여기서 URL 값에 사용된 /vuln 경로는 Reflected XSS 취약점이 존재했습니다.
    • ( xss-1, xss-2 문제와 코드의 흐름이 동일했습니다. )

def read_url(…)

  • read_url(...) 함수에서는 check_csrf 함수에서 넘어온 URL과 쿠키 값을 활용해서
  • 셀레니움 브라우저로 해당 경로 접근을 시도합니다.


PoC

  • 자, 위에서 분석한 내용들을 바탕으로 CSRF 취약점을 악용해보겠습니다.
  • admin_notice_flag 함수로 플래그를 확인하려면 2번의 검증 우회가 필요합니다.
    • 1번째는 함수 호출을 외부가 아닌 내부에서 호스트가 직접 해야 한다는 것이고
    • 2번째는 함수 호출 시 GET 파라미터(userid) 값으로 admin이 포함돼야 한다는 것입니다.
  • 아래와 같이 페이로드 작성 후 /flag 경로에서 POST 요청을 보내보겠습니다.
    • <img/src="/admin/notice_flag?userid=admin">

  • 이제 /memo 경로로 접근해서 기록된 정보를 확인해보면?
  • KIAAAAAAAAAAAAAAA~ 플래그 확인이 가능합니다.

🐛.. 🐛.. 🐛..