Google에서 9만 달러 포상금을 받은 원격 코드 실행 취약점을 발견한 과정

1 hour ago 4

Google의 공용 문서 플랫폼 DevSite에서 Flask 세션 쿠키 안에 그 쿠키의 서명 키가 들어 있어, 로그인 없이 세션을 위조할 수 있는 취약점이 발견됨 쿠키에 담긴 OAuth client_secret 이 Flask SECRET_KEY 로도 사용됐으며, 추출한 값으로 만든 서명을 서버가 받아들이는 것까지 확인함 OAuth 콜백이 세션 속 객체를 pickle.loads 로 역직렬화하면서, 위조한 쿠키가 인증 없는 원격 코드 실행으로 이어짐 운영 서버에서 명령을 실행하는 대신 time.sleep(N) 을 넣어 검증했으며, 지정한 대기 시간에 맞춘 응답 지연과 대조 실험으로 실행 여부를 확인함 취약점은 Google 도메인 7개에 걸쳐 있었으며, Google은 이를 수정하고 9만 달러의 포상금을 결정함 OAuth 흐름에서 발견한 비정상적으로 큰 쿠키 Google 개발자 문서 사이트들이 공유하는 OAuth 흐름을 조사하던 중, /oauth2authorize가 계정 없이도 Flask 세션 쿠키를 발급하고 Google 로그인 페이지로 리디렉션하는 것을 확인함 쿠키는 일반적인 session=<payload>.<timestamp>.<signature> 구조였지만, 약 1,200바이트로 CSRF 토큰과 반환 URL만 담기에는 컸음 Flask 세션 쿠키는 서명될 뿐 암호화되지 않으므로, 보유한 사람이 내용을 읽을 수 있음 페이로드 앞의 점은 zlib 압축을 뜻하며, Base64 디코딩과 압축 해제 후 JSON을 읽을 수 있었음 세션에는 _permanent, google_oauth2_csrf_token, google_oauth2_flow_<csrf> 항목이 들어 있었음 흐름 객체 안의 " b" 키는 Flask의 바이트 값 태그였고, 이를 Base64 디코딩하자 pickle 데이터가 나옴 pickletools.dis로 확인한 객체는 oauth2client.client.OAuth2WebServerFlow였음 객체에는 Google OAuth의 client_id와 client_secret이 평문으로 담겨 있었으며, 공개 본문에서는 비밀값을 가렸음 해당 비밀값은 본문 작성 시점에도 유효한 상태였음 OAuth 비밀값과 세션 서명 키의 재사용 추출한 OAuth client_secret 을 Flask SECRET_KEY 로 사용하자 발급된 쿠키의 서명이 검증됨 우연한 일치가 아닌지 확인하기 위해...

Read Entire Article