[dreamhack] file-csp-1 문제풀이
- -
[WEB] file-csp-1 문제풀이 |
CSP(Content Security Policy)는 다양한 웹 보안 정책 중 하나다. 주로 XSS나 Data Injection, Click Jacking 등 웹 페이지에 악성 스크립트를 삽입하는 공격 기법들을 막기 위해 사용된다. 주로 헤더에 내용이 삽입되며 특정 리소스가 어디서 왔는지 검사를 하고 허용된 범위에 포함됐는지 검토한다.
문제를 확인해보자.
/test 페이지에 접근하니 Test 버튼이 눈에 띈다.
예시로 써있는 저 구문을 입력해서 버튼을 눌러보자.
이런 결과가 출력된다. 무슨 말인지 모르겠으므로 코드를 봐보자.
#!/usr/bin/env python3
import os
import shutil
from time import sleep
from urllib.parse import quote
from flask import Flask, request, render_template, redirect, make_response
from selenium import webdriver
from flag import FLAG
APP = Flask(__name__)
@APP.route('/')
def index():
return render_template('index.html')
@APP.route('/test', methods=['GET', 'POST'])
def test_csp():
global CSP
if request.method == 'POST':
csp = request.form.get('csp')
# start bot..
try:
options = webdriver.ChromeOptions()
for _ in ['headless', 'window-size=1920x1080', 'disable-gpu', 'no-sandbox', 'disable-dev-shm-usage']:
options.add_argument(_)
driver = webdriver.Chrome('/chromedriver', options=options)
driver.implicitly_wait(3)
driver.set_page_load_timeout(3)
driver.get(f'http://localhost:8000/live?csp={quote(csp)}')
try:
a = driver.execute_script('return a()');
except:
a = 'error'
try:
b = driver.execute_script('return b()');
except:
b = 'error'
try:
c = driver.execute_script('return c()');
except Exception as e:
c = 'error'
c = e
try:
d = driver.execute_script('return $(document)');
except:
d = 'error'
if a == 'error' and b == 'error' and c == 'c' and d != 'error':
return FLAG
return f'Try again!, {a}, {b}, {c}, {d}'
except Exception as e:
return f'An error occured!, {e}'
return render_template('check.html')
@APP.route('/live', methods=['GET'])
def live_csp():
csp = request.args.get('csp', '')
resp = make_response(render_template('csp.html'))
resp.headers.set('Content-Security-Policy', csp)
return resp
if __name__ == '__main__':
APP.run(host='0.0.0.0', port=8000, debug=True, threaded=True)
test 페이지에서 csp 파라미터를 받아서 http://localhost:8000/live?csp={quote(csp)}를 접속한다.
그리고 차례로 a(), b(), c(), $(document)를 실행시켜서
a='error'이고, b='error'이고, c='c'이고, d!='error'이면 플래그를 출력시킨다.
제일 처음 csp로 넘겼던 값은 CSP 헤더에 이렇게 작성되었을 것이다.
Content-Security-Policy: script-src 'unsafe-inline'
이 것은 script tag에서 inline script를 허용한다는 내용이다.
그럼 CSP 설정을 하지 않았을 때 어떻게 출력되는지 확인해보자.
모든 스크립트 태그가 실행됨을 알 수 있다.
각각 a(),b(),c(),$(document) 함수가 script 태그 안에 정의되어 있다.
그럼 여기에서 a(),b() 함수의 실행을 막고 c(), $(document) 만 실행시켜야 한다.
CSP의 script-src 정책을 이용해서 각 태그의 특징을 이용해야 한다.
a() 함수는 script 속성이 별도로 지정되어 있지 않다.
b() 함수는 nonce 속성 값으로 "i_am_user_super_random" 이 지정되어 있다.
c() 함수 또한 nonce 속성 값으로 "i_am_user_super_random" 이 지정되어 있다.
$(document) 는 c() 함수와 동일한 스크립트 태그 안에 정의되어 있다,
nonce 값으로 설정하기엔 b()와 c()가 동일하기 때문에 스크립트 해시 값으로 실행시켜야한다.
CSP는 스크립트 태그 안에 정의된 구문들을 해시 값으로 만들어서 무결성을 체크할 수 있는데
이 것을 이용하면 해당 해시와 동일한 스크립트 구문만을 실행할 수 있다.
그럼 아래 구문을 해시 값으로 만들어야 한다.
function c() { return 'c'; }
document.write('c: allow me!<br>');
try { $(document); document.write('jquery: allow me!<br>'); } catch (e) { }
*주의사항은 <script></script> 사이의 모든 공백은 HASH 값에 포함되어야 한다.
https://report-uri.com/home/hash 페이지에서 스크립트 태그 안 문자열(공백포함)을 sha256 값으로 바꿔준다.
그리고 script-src 정책으로 해당 해시를 넣어줘서 c(), $(document) 구문 만을 실행하도록 한다.
csp=script-src 'sha256-l1OSKODPRVBa1/91J7WfPisrJ6WCxCRnKFzXaOkpsY4=' |
가장 아래 4번째 스크립트 태그 안 구문이 실행된 것을 확인했다.
그 위 스크립트 태그도 allow 해줘야한다. 여기는 hash가 있으니 그대로 갖다 쓰면 되겠다.
이제 /verify 페이지에서 플래그를 획득해보자.
csp=script-src 'sha256-l1OSKODPRVBa1/91J7WfPisrJ6WCxCRnKFzXaOkpsY4=' 'sha256-pasqAKBDmFT4eHoN2ndd6lN370kFiGUFyTiUHWhU7k8=' |
문제풀이 끗
'워게임 > dreamhack' 카테고리의 다른 글
[dreamhack] web-deserialize-python 문제풀이 (0) | 2021.07.07 |
---|---|
[dreamhack] funjs 문제풀이 (0) | 2021.07.06 |
[dreamhack] login-1 문제풀이 (0) | 2021.07.01 |
[dreamhack] Mango 문제풀이 (0) | 2021.06.24 |
[dreamhack] simple-ssti 문제풀이 (0) | 2021.06.20 |