ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Bugbounty Study] #Vimeo _ SSRF
    Study/Bugbounty Study 2021. 1. 27. 20:53

    # uploading process SSRF _ \$100 + \$4,900

    medium.com/@dPhoeniixx/vimeo-upload-function-ssrf-7466d8630437

     

    Vimeo upload function SSRF

    TL;DR

    medium.com

    해당 글은 Vimeo 동영상 업로드 과정에서의 SSRF 취약점에 대한 글이다.

    이 취약점 제보를 통해 총 두 번의 Bounty를 받았다.

     

    해당 글의 타겟인 Vimeo는 직접 제작한 동영상을 업로드 및 공유할 수 있는 사이트로,

    로컬에 저장되어 있는 파일뿐만 아니라 드롭박스나 Google Drive 등 다양한 방식으로 업로드할 수 있다.

     

     

    BurpSuite를 이용하여 Google Drive로의 동영상 업로드 요청을 확인하였다.

     

    Upload Request

     

    동영상 파일이 저장되어 있는 URLGoogle authorization값을 전송하는 것을 볼 수 있는데,

    이는 백엔드 서버가 해당 값으로 구글 드라이브의 파일에 접근해 가져오기 위한 값이다.

    백엔드 서버에서 어떤 일이 발생하는지 알아보기 위해 동영상 다운로드를 요청한 후 WireShark로 패킷을 확인하였다.

     

    HTTP Stream Of Download Request

     

    패킷의 Range, Content-Range 같은 일반적이지 않은 헤더를 통해 어떤 일이 발생하는지 알 수 있다.

    대부분 동영상의 크기가 크기 때문에 Vimeo가 전체 파일을 한 번에 요청하지 않는다고 추측할 수 있다.

    만약, 동영상의 크기가 작으면 전체 파일을 요청할 것이고, 크면 전체 파일이 될 때까지 파일의 부분을 요청할 것이다.

     

    Normal Upload Process

     

    [Upload Process]
    1. 동영상 업로드 요청 (Client -> Backend Server)
    2. 동영상 크기 확인을 위한 0Byte 데이터 요청 (Backend Server -> hoster.com)
    3. Content-Range값을 통해 동영상 크기 응답 (hoster.com -> Backend Server)
    4. 동영상 데이터 요청 (Backend Server -> hoster.com)
    5. 동영상 데이터와 함께 요청 완료 응답 (hoster.com -> Backend Server)
    6. 파일 인코딩 검사를 통해 동영상 파일 여부 확인 후 사용자 프로필로 전달 (Backend Server)

    [Header Range, Content-Range] https://developer.mozilla.org/ko/docs/Web/HTTP/Range_requests
    [HTTP 206 State Code] https://developer.mozilla.org/ko/docs/Web/HTTP/Status/206

     

    서버가 파일의 크기를 확인하는 요청을 보낸 다음, 만약 단일 연결으로 전송할 만큼 파일의 크기가 작으면 전체 파일을 요청할 것이다.

    이 부분에서 원작자는 서버에서 Backend Server가 요청한 만큼의 데이터보다 적은 양의 데이터로 응답하면 어떻게 될지 궁금하였고, 이를 위해 Python으로 웹 서버를 구축하여 테스트하였다.

    전체 파일의 길이는 554321B이지만 Vimeo에서 전체 파일을 요청할 때 8228B만 응답하였다.

     

     

    로그를 통해 Vimeo Server에서 8228B만큼 저장하여 8228-554321 범위의 남은 파일을 요청한 것을 확인할 수 있다. 이런 경우 서버가 Vimeo에 Redirect 응답을 보내면 SSRF로 이어질 수 있다.

     

    Redirect Responed Process

     

    [Redirect Responed Process]
    1. 동영상 업로드 요청 (Client -> Backend Server)
    2. 동영상 크기 확인을 위한 0Byte 데이터 요청 (Backend Server -> evil.com)
    3. Content-Range값을 통해 동영상 크기 응답 (evil.com -> Backend Server)
    4. 동영상 데이터 요청 (Backend Server -> evil.com)
    5. 8228Byte의 동영상 데이터와 함께 요청 완료 응답 (evil.com -> Backend Server)
    6. 파일이 응답받은 크기가 아니므로 나머지 데이터 요청 (Backend Server -> evil.com)
    7. http://evil.com/Hello.txt로 Redirect 응답 (evil.com -> Backend Server)
    8. Backend Server가 Redirect되어 http://evil.com/Hello.txt로 접근
    9. Hello.txt의 내용과 함께 요청 완료 응답 (evil.com -> Backend Server)
    10. 파일이 응답받은 크기가 아니므로 나머지 데이터 요청 (Backend Server -> evil.com)
    11. 나머지의 동영상 데이터와 함께 요청 완료 응답 (evil.com -> Backend Server)
    12. Backend Server는 받은 파일의 크기가 더 크지만 부족하지 않으므로 넘어간 후 받은 파일 병합
        (파일의 8228 offset은 Backend Server가 Redirect 된 evil.com/Hello.txt의 데이터로, FIRST_8228_BYTES_OF_VIDEO_FILE + Helloworld!zzz + REST_BYTES_OF_THE_VIDEO_FILE과 같이 보일 것이다.)

     

    몇몇 웹 서버에서 공격을 재현하는 것은 제한적이어서 공격을 수행하기 위해 서버를 구축하여 실행하였다.

    구축한 서버를 통해 공격이 제대로 동작하는 것을 확인하였다.

    (참고: 업로드된 파일을 다운로드할 수 있어 쉽게 SSRF를 확인할 수 있다.)

     

     

    [Exploit]
    1. 구축한 서버에 대한 정보 수집
    2. 서버가 구글 인스턴스임을 확인하여 인스턴스 메타데이터 검색
    3. 응답할 Redirect 주소 변경
      (http://metadata.google.internal/computeMetadata/v1beta1/instance/service-accounts/default/token)
    4. 공격 재현
    5. 컴퓨팅 엔진 API access token 얻음

     

    [Exploit 결과]

     

    댓글

@Jo Grini's Blog