버그바운티(Bug Bounty) Write-up / Reflected Cross site Scripting ($375)
Security/BugBounty Study

버그바운티(Bug Bounty) Write-up / Reflected Cross site Scripting ($375)

https://hackerone.com/reports/438240

 

Starbucks disclosed on HackerOne: Reflected Cross site Scripting...

**Summary:** Reflected Cross site Scripting (XSS) on https://www.starbucks.com/account/signin?ReturnUrl **Description:** The attacker can execute javascript on the victims account just after the authentication process. **Platform(s) Affected:** www.starbuc

hackerone.com


Reflected XSS - 375$

스타벅스 버그바운티 건인데요. 작성자는 Reflected XSS 를 발생시켜서 375달러를 바운티 받았습니다. 

취약점이 발생한 URI는 https://www.starbucks.com/account/signin?ReturnUrl 로 가입을 완료하고, 리다이렉션 되는 부분에 넘겨지는 파라미터로 스크립트를 주입하여 실행시켰는데요. 어제 적었던 포스팅이랑 내용은 같으나 우회를 한 기법이 특이해서 적어보았습니다.

https://www.starbucks.com/account/signin?ReturnUrl=%19Jav%09asc%09ript%3ahttps%20%3a%2f%2fwww%2estarbucks%2ecom%2f%250Aalert%2528document.domain%2529

공격 구문입니다. 현재 인코딩되어있는 상태라 디코딩을 해보겠습니다.

https://www.starbucks.com/account/signin?ReturnUrl=Jav asc ript:https ://www.starbucks.com/%0Aalert%28document.domain%29

한번 디코딩했음에도 불구하고 아직 인코딩이 완벽하게 이루어지지 않은걸 보실 수 있는데요. 이 구문은 현재 두번 인코딩 되어있습니다. 한번 인코딩 한 후에, %(퍼센트) 에 대한 URL 인코딩을 한번 더 해주었습니다. 이부분은 뒤에서 설명 하겠습니다. 

URL : %19   ASCII : 25 

한번 디코딩된 코드를 보면  '  '  라는 %19 에 해당하는 문자가 있는데요. 이 문자는 제어문자로 Serial 통신에서 사용되는 문자입니다. 뜻은 "매체종료" 라고 합니다. 사실 왜 이걸 넣었는지는 잘 모르겠습니다. 우회기법중 하나 인것 같네요.

 

URL : %09   ASCII : 9

그다음 Jav 와 asc 사이 그리고 asc와 ript 사이에 %09 라는 문자가 들어갔는데요. 이 문자는 Horizontal Tab기능 입니다.  이 기능도 마찬가지로 javascript라는 단어에 대한 우회를 위해서 넣어 준 것 같습니다. 공백으로 보이네요.

 

URL : %0A ASCII : 10

마지막으로 alert 문자 앞에 있는 %0A 입니다. 이 문자는 개행기능을 하지만, 시리얼 통신에만 적용되므로 그냥 공백으로 보입니다. 

 

https://www.starbucks.com/account/signin?ReturnUrl=Jav asc ript:https ://www.starbucks.com/
alert(document.domain)

한번 더 URL 디코딩을 해주었습니다. 왜 더블인코딩을 할까 찾아본 결과 (제가 맞는지는 모르겠습니다. 명확한 자료가 없었네요) URL 디코딩은 서버측에서 따로 코드를 추가하지 않아도, 자동으로 딱 1번 이루어 집니다. nginx 라던지, apache 라던지에서요. 

 

1
2
3
4
5
<?php
    $input = htmlentities($_GET["query"]);
    echo urldecode($input);
?>
 
cs

 

php 코드로 예를 들어보겠습니다. (이 서버에는 XSS 필터도 사용하고 있습니다) 개발자는 URL 을통해 GET이든 POST든 넘어온 파라미터 값을 사용하려고 합니다. 개발자는 생각했죠. "음 URL인코딩되서 값이 넘어올것이니까 디코딩해야겠네." 그래서 디코딩을 해주었고, 디코딩된 값을 사용했습니다. 여기서는 아무런 문제가 없죠. 한번 디코딩된 값은 한번 인코딩하든 두번 인코딩 하든 똑같은 값이나오니까요. 

하지만 해커가 이 버그를 인지하고 두번 인코딩하여서 보내면 문제가 발생합니다. 서버자체에서 한번 디코딩된 값은 서버 내 XSS 필터를 거치게 되는데, URL 인코딩으로 인해 필터를 우회합니다. 하지만 개발자가 따로 디코딩 루틴을 추가하지 않았다면 두번의 인코딩이 풀리지 않아서 아무런 기능을 하지 않는 문자열일 뿐입니다. 그런데 개발자가 추가한 디코딩 루틴으로 두번의 인코딩이 풀리고, 공격자의 쿼리가 동작하게 됩니다.


 

정확한 우회가 되는 내부 알고리즘이나 이런것은 찾아도 정보가 많이없어서 잘 모르겠으나 대충 이런 방식으로 우회를 시도한 것 같습니다.