여러가지/이것저것

XSS(Cross-Site Scripting)?

hyeseong-dev 2024. 3. 21. 13:03

XSS(Cross-Site Scripting) 공격은 웹 애플리케이션의 보안 취약점을 이용하여, 공격자가 사용자의 웹 브라우저에 악의적인 스크립트를 실행시키는 공격 방법입니다. 이 스크립트는 사용자가 방문하는 웹 페이지에 삽입되며, 사용자의 세션 토큰이나 쿠키 정보를 탈취하거나, 사용자를 가장하여 웹 애플리케이션에 요청을 보내는 등 다양한 악의적인 활동을 수행할 수 있습니다.

XSS 공격의 주요 유형

XSS 공격은 크게 세 가지 유형으로 분류됩니다:

1. 저장된(Stored) XSS: 악의적인 스크립트가 웹 애플리케이션의 데이터베이스에 저장되고, 다른 사용자가 해당 데이터를 조회할 때 실행되는 공격입니다. 예를 들어, 포럼 게시글이나 댓글에 악의적인 스크립트를 포함시키는 경우가 있습니다.

 

2. 반사된(Reflected) XSS: 사용자로부터 입력 받은 데이터를 즉시 에코(echo)하는 웹 페이지에서 발생하는 공격입니다. 사용자가 악의적인 링크를 클릭할 때, 해당 링크에 포함된 스크립트가 사용자의 브라우저에서 실행됩니다.

 

3. DOM 기반(DOM-based) XSS: 웹 애플리케이션의 클라이언트 측에서 처리되는 DOM(Document Object Model)의 취약점을 이용하는 공격입니다. 이 공격은 웹 페이지의 DOM 환경을 조작하여 스크립트를 실행시킵니다.

XSS 공격의 방어 방법

XSS 공격을 방어하기 위한 주요 방법은 다음과 같습니다:

1. 입력값 검증(Sanitization): 사용자로부터 받은 입력값에 대해 엄격하게 검증하고, 스크립트 태그나 이벤트 핸들러 같은 잠재적으로 위험한 요소를 제거합니다.

 

2. 출력 인코딩: 사용자 입력을 웹 페이지에 출력할 때, HTML, JavaScript 등의 인코딩을 적용하여 실행 가능한 스크립트가 아닌 단순 텍스트로 처리되도록 합니다.

 

3. 콘텐츠 보안 정책(CSP): CSP를 사용하여, 웹 브라우저가 실행할 수 있는 스크립트의 출처를 제한합니다. 이를 통해 외부 도메인에서 로드되는 악의적인 스크립트의 실행을 방지할 수 있습니다.

 

4. 쿠키에 HttpOnly 및 Secure 플래그 설정: 쿠키에 HttpOnly 플래그를 설정하면, JavaScript를 통한 쿠키 접근을 차단할 수 있습니다. Secure 플래그를 설정하면, 쿠키 정보가 HTTPS를 통해서만 전송되도록 합니다.

XSS 공격은 사용자의 신뢰를 기반으로 하는 웹 애플리케이션에서 심각한 위협이 될 수 있으므로, 위와 같은 방어 기법을 적절히 구현하여 애플리케이션의 보안을 강화해야 합니다.


예시

Python Flask 웹 애플리케이션에서의 XSS 취약점 예시

from flask import Flask, request, render_template_string

app = Flask(__name__)

@app.route('/')
def index():
    # 사용자로부터 입력 받은 "name" 파라미터 값을 가져옵니다.
    user_name = request.args.get('name', 'Guest')
    # 사용자 입력을 검증하지 않고, 바로 HTML 템플릿에 포함하여 렌더링합니다.
    # 이 과정에서 XSS 취약점이 발생할 수 있습니다.
    return render_template_string('<h1>Hello, ' + user_name + '!</h1>')

if __name__ == '__main__':
    app.run(debug=True)

이 코드에서, 사용자는 웹 애플리케이션의 URL에 name 파라미터를 추가하여 자신의 이름을 입력할 수 있습니다. 예를 들어, 사용자가 웹 브라우저의 주소 창에 다음과 같이 입력할 수 있습니다:

http://localhost:5000/?name=John

이 경우, 웹 페이지는 "Hello, John!"을 출력합니다.

그러나 악의적인 사용자가 name 파라미터에 JavaScript 코드를 포함한 링크를 다음과 같이 만들 수 있습니다:

http://localhost:5000/?name=<script>alert('XSS');</script>

이 경우, 서버는 <script>alert('XSS');</script>를 사용자의 이름으로 받아들이고, 이를 HTML에 그대로 삽입하여 렌더링합니다. 결과적으로, 웹 페이지를 방문하는 모든 사용자의 브라우저에서 JavaScript 코드가 실행됩니다. 이것이 바로 XSS 취약점이 발생하는 방식입니다.

방어 기법

이러한 XSS 취약점을 방지하기 위해서는 사용자 입력을 HTML 템플릿에 삽입하기 전에 적절히 검증 및 escape 하는 것이 중요합니다. Flask와 같은 현대적인 웹 프레임워크는 자동으로 HTML 이스케이핑을 제공하지만, 개발자는 render_template_string 같은 메서드를 사용할 때 주의해야 합니다. Flask에서는 Jinja 템플릿 엔진을 사용하여 변수를 렌더링할 때 자동으로 이스케이프 처리를 합니다:

from flask import Flask, request, render_template

@app.route('/')
def index():
    user_name = request.args.get('name', 'Guest')
    # 안전한 방법: 사용자 입력을 변수로 전달하고, 템플릿에서 이스케이프 처리를 합니다.
    return render_template('index.html', name=user_name)

index.html:

<h1>Hello, {{ name }}!</h1>

이 방법을 사용하면, Flask가 자동으로 name 변수를 안전하게 이스케이프 처리하여 XSS 공격을 방지할 수 있습니다.