https://dreamhack.io/wargame/challenges/435
소스 코드 분석
/flag 페이지에서 삽입한 페이로드를 check_xss 함수에서 취약한 페이지로 연결된 url을 read_url 함수로 생성한 웹 봇이 방문한다.

/flag 페이지에서 삽입한 페이로드를 취약한 페이지인 /vuln 페이지에 삽입하고 해당 url을 웹 봇에게 방문시킨다.

CSP로 보안 설정을 한다. 이 문제를 풀기 위해 눈여겨볼 함수다.

다른 페이지들은 여태 풀어본 XSS와 아주 유사하다. 차이점은 CSP로 설정한 nonce가 걸려있어 자바스크립트를 인라인으로 실행할 수 없다.

풀이
CSP의 자바스크립트 설정인 script-src를 보면 self와 nonce-{nonce} 설정이 있다. nonce의 값을 모르면 인라인 코드를 사용할 수 없지만 Same Origin 내에서 불러온 자바스크립트는 실행할 수 있다. 취약한 페이지인 /vuln에서 param 값에 “aaa”를 넘겨주면 화면에 “aaa” 만을 출력한다. 그렇다면 “alert(1)”을 넘겨주면 “alert(1)” 만을 출력할 것이다. 이는 자바스크립트 파일의 역할을 해줄 것이다. 그렇다면 Same Origin 이면서, 인라인 코드가 아니므로 CSP 보안 설정을 우회하고 자바스크립트를 실행할 수 있다.
우선 위 설명대로 alert(1)이 동작하는지 확인해본다. <script> 태그의 src 속성으로 /vuln 페이지에 “alert(1)”를 넘겨준 페이지를 불러온다.
<script src="/vuln?param=alert(1)"></script>

자바스크립트가 정상적으로 작동하므로 웹 봇이 /memo 페이지에 플래그를 남길 수 있는 페이로드를 작성하여 /flag 페이지에 삽입한다.
<script src="/vuln?param=location.href='/memo?memo='%2bdocument.cookie"></script>


왜 페이로드에 +가 아니라 %2b인가?
원래는 src 속성으로 스크립트를 불러올 때 한 단계만에 불러오지만 이번은 URL을 통해 한 단계 더 거치게 된다. 그래서 아래의 그림처럼 ‘+’를 쓰게 되면 URL decoding으로 ‘+’는 공백으로 디코딩되어 자바스크립트는 에러를 일으키므로 실행되지 않는다. 그래서 ‘+’로 처리될 수 있도록 URL encoding을 한 것이다.
