By fandu | June 2, 2016
[번역글] Uber.com Remote Code Execution
최오리군의 번역글입니다.
에- 따끈따끈 할 때 올렸어야 했는데.
코드게이트 문제 출제 할 때 쓰겠다고 킵해놨었는데 아이고 의미없다ㅋㅋ
여튼, 더 늦기 전에 후딱 올려봅니다.
원문의 링크는 아래를 참고 해 주세요!
[Bug Bounty] Uber 遠端代碼執行- Uber.com Remote Code Execution via Flask Jinja2 Template Injection
며칠 전 Uber에서 버그 바운티 계획을 발표하였다.
Hackerone에서 처음 이 소식을 접했는 데 상금이 적지도 않고,
XSS/CSRF 취약점도 최소 3000달러에서 시작하기도 하고, 재미있을 거 같아서 한번 보기로 했다.
공식 홈페이지에서 발표한 세부적인 기술 사항을 보면
Uber 홈페이지는 메인 페이지부터 파이썬 플라스크와 Node.js로 구성되어 있는 것을 알 수 있다.
그렇기 때문에 취약점을 찾을 때 자연스럽게 이 두 가지 프레임워크의 취약점을 중점적으로 찾게 되었다!
Uber 홈페이지에서는 전화 번호 및 이름을 수정할 때
메일이나 텍스트 메시지를 전송하는 형식으로 사용자에게 계정이 변경되었다는 정보를 전송한다.
이러한 작업을 진행한 후에 Uber에서 전달된 메시지를 살펴보면 아래 사진과 같이 이름 뒤에 2가 붙어있는 것을 볼 수 있다.
뒤로 되돌아가며 원인을 분석한 결과 Entry Point가 Riders.uber.com인 것을 알 수 있었다.
Riders.uber.com은 사용자들이 개인 프로필을 수정하거나 결제 내용을 보여주고 우버를 타고 다닌 경로를 출력해준다.
이름을 수정하는 부분에서 {{1+1}}를 사용하였는 데 이로 인해 문제가 생긴다.
취약점의 원인은 파이썬 플라스크에서 디폴트로 사용된 템플릿 엔진인 Jinja2에 존재하는 데
Jinja2에서도 파이썬 문법으로 HTML을 생성할 수 있다.(당연히 샌드박스도 존재한다.)
그렇기 때문에 {{1+1}} 이 구문에 파이썬에 의해 2로 해석되어 메일에 저장되고 필자의 메일에 까지 전송된 것이다.
더욱 상세한 내용은 PortSwigger(BurpSuite 개발자)가 Blackhat 2015에서 발표한
Server-Side Template Injection:RCE for the modern webapp를 참고하라.
그렇기 때문에 지금 우리는 Jinja2의 문법에서 제한적으로 이름 부분에 파이썬 코드을 실행할 수 있다!
예를 들어 이름란에 Jinja2 문법에 따라 {% for c in [1,2,3]%}{{c,c,c}}{%endfor%}를 한 번 써보자.
템플릿 엔진을 이용하여 Uber 서버가 우리가 입력한 for문을 돌게 해보자. 결과는 메일로 전달 받을 수 있다. ㅎ
메일을 보면 성공적으로 for문을 실행한 것을 볼 수 있다.
그러나 글 앞에서도 언급했듯이 무제한으로 파이썬 코드를 실행할 수 있는 것은 아니다.
Jinja2에 있는 Sandbox를 활용하여 위협에 대응하는 방법으로 함수를 사용하여 방어 기능을 수행한다.
하지만 이 부분은 CTF를 하는 친구들에게는 큰 문제가 되지 않을 것이다.
왜냐하면 여러 대회에서 파이썬의 샌드박스 우회 문제가 흔히 나오기 때문에 이 방법을 바로 활용하면 된다.
이 부분에 대한 상세한 내용은 아래 링크를 참고하면 된다.
Exploring SSTI in Flask/Jinja2
Exploring SSTI in Flask/Jinja2, Part2
利用 Python 特性在 Jinja2 模板中執行任意代碼
Exploit 시작
{{[].class.base.subclasses()}}를 사용하면 사용하는 모듈들을 알 수 있다.
빈 부분으로 보이는 것은 HTML에 의해 <>로 감싸졌기 때문이다.
실제 내용은 메일 파일을 보면 바로 볼 수 있다.
추가적으로 사용하는 모듈에서 Celery를 볼 수 있는 데 이를 바탕으로 웹 페이지의 대략적인 구성을 살펴보았다.
Riders.uber.com에 들어가 이름을 수정하면 데이터 베이스에 저장된다.
하지만 텍스트 메시지나 메일을 보내는 등 시간을 많이 소모하는 작업들은
Asynchronous Task 메커니즘을 사용하여 벡엔드의 Worker에 전달한다.
반면에 Worker가 데이터베이스에서 이름을 가져와서 템플릿을 생성할 때에는
연결되게 뽑아내는 방식으로 템플릿을 생성하기 때문이 이렇게 원격에서 코드가 실행되는 것이다.
마지막으로 한마디 더하면 필자에게는 버그 바운티를 하는 이유는 상금이든 뭐든 다 아니다.
제일 중요한 것은 사람들이 찾지 못하는 부분, 발견하지 못하는 부분에서 찾아내는 것이고
다른 사람들이 필자의 취약점을 인정받는 것이다.
여기서 오는 성취감이 필자가 취약점을 찾는 원동력이 된다.
original post link : [Bug Bounty] Uber 遠端代碼執行- Uber.com Remote Code Execution via Flask Jinja2 Template Injection