XSS 공격은 공격자가 사용자의 의도와 다른 작업이 수행되도록 만들 수 있는 취약점입니다. 경로를 우회하거나 혹은 악성 스크립트를 실행시킬 수 있습니다.
기본 원리는 웹 사이트를 조작하여 사용자가 악성 JavaScript 코드를 실행하도록 만들어 의도와는 다른 처리가 되도록 합니다.
XSS 공격은 타겟인 애플리케이션의 종류 및 사용자의 권한에 따라 심각한 영향을 줄 수 있습니다.
XSS는 크게 Reflected XSS, Stored XSS, DOM XSS 3가지로 나뉩니다.
Reflected XSS는 공격자가 취약점이 있는 웹 사이트의 URL에 악성 스크립트를 입력하고 해당 URL을 사용자가 클릭하도록 유도해 공격합니다.
사용자가 URL을 클릭하면 요청이 서버에 전달되고, 서버는 악성 스크립트가 담긴 응답을 사용자에게 전송해 악성 스크립트를 실행하게 됩니다.
Stored XSS는 공격자가 서버에 악성 데이터를 심어놓고 다른 사용자가 해당 데이터에 접근할 때 실행되는 취약점입니다.
Reflected XSS와 동일하게 취약점이 있는 URL에 악성 스크립트를 입력하고 해당 URL을 사용자가 클릭하도록 유도합니다.
단, 차이점은 Reflected XSS는 서버에 요청이 전송되어 서버로부터 악성 스크립트가 반환되지만, DOM XSS는 클라이언트 측에서 악성 스크립트가 실행됩니다.
이를 통해 세션 쿠키, 입력 데이터, 로컬 스토리지, 세션 스토리지 정보를 탈취할 수 있습니다.
💡 DOM(Document Object Model)이란?
HTML(또는 XML)문서를 파싱해서 트리구조로 변환한 것. 각 요소들은 객체 형태이며 객체 안에는 자식 노드를 담습니다.<!DOCTYPE html> <html> <head> <title>Example</title> </head> <body> <h1>Hello, World!</h1> <p>paragraph</p> </body> </html>위 HTML 코드를 DOM 형식으로 바꾸면 아래와 같습니다.
이렇게 만들어진 DOM은 JS 코드를 통해 조작이 가능합니다.
//h1의 문구를 Hello, DOM!으로 변경. document.querySelector('h1').textContent = 'Hello, DOM!';
일반적으로 XSS 취약점을 확인하기 위해서는 JavaScript의 alert() 함수를 사용하는데, 크롬에서는 보안상의 이유로 2021년 이후로 alert()을 서로 다른 도메인에서 제공되는 콘텐츠를 포함한 iframe을 금지해놨기 때문에 이제 print() 함수를 사용하여 취약점을 확인합니다.
💡 iframe이란?
HTML에서 사용되는 태그로 웹페이지 안에 다른 웹페이지에서 제공하는 컨텐츠의 일부를 불러올 수 있는 요소 입니다.
<iframe src="https://www.example.com" width="600" height="400"></iframe>
Dangling Markup Injection은 XSS 공격이 불가능한 상황에서 교차 도메인에서 데이터를 탈취할 수 있는 기법입니다.
사용자의 입력을 엄격하게 필터링하여 XSS 공격 수행을 방지합니다.
사용자의 입력이 웹 애플리케이션에서 코드로서 입력되지 않도록 단순한 텍스트 형태로 변환합니다.
alert('XSS') 코드의 경우 인코딩을 수행해 다음과 같이 변환합니다.
\u0061\u006c\u0065\u0072\u0074(\u0027XSS\u0027)
이렇게 JS 코드 내에서 alert()함수로서 동작하지 않고 텍스트 형태로 안전하게 처리됩니다.
Content-Type 및 X-Content-Type-Options 헤더를 사용해 응답을 의도한 방식대로 해석할 수 있도록 해야 합니다.
CSP는 HTTP 응답 헤더에 Content-Security-Policy 헤더등을 포함해 브라우저에 보안 지침을 전달합니다. 이를 통해 스크립트 실행 제한, 리소스 로딩 제한을 하여 XSS 공격을 최소화합니다.
그러나 CSP를 잘못 설정할 경우 우회 가능성이 있으며, 웹 사이트의 성능이 저하될 수 있습니다.