본문 바로가기

24년 1학기 학교공부/네트워크웹보안

[NW] XSS (Cross-Site Scripting Attack)

목차

    728x90
    반응형
    SMALL
    2024학년도 1학기 충남대학교 장진수 교수님의 네트워크 및 웹 보안 수업 정리자료입니다.

     

     

     

     

     

    The Cross-Site Scripting(XSS) Attack

     

    XSS 공격이란 공격자가 타겟 웹사이트를 통해 희생자의 브라우저에 본인의 악성 코드를 감염시키는 공격을 말한다.

     

    공격자는 희생자가 안전하다고 믿는 웹사이트에 악성 스크립트를 심는다. 웹사이트로부터 넘어오는 코드는 신뢰할 수 있다고 간주되므로, 페이지의 내용에 접근하거나, 변경하거나, 쿠키를 읽거나, 사용자를 대신해 요청을 보낼수도 있다.

     

    XSS 공격은 데이터베이스에 악성 스크립트가 저장되는지의 여부에 따라 Non-persistent(Reflected) XSS, Persistent(Stored) XSS로 나눌 수 있다.

     

     

    Non-persistent (Reflected) XSS Attack

     

    반사된(Reflected) XSS 혹은 비지속적(Non-persistent) XSS라고 불리며, 가장 일반적인 유형이다. 웹 클라이언트가 HTTP 쿼리 매개변수에 어떠한 값을 제공할 수 있을 때, 해당 값에 악성 스크립트를 삽입하면 HTTP 응답에 그대로 포함되어 즉시 실행되는 공격을 말한다.

     

    1. 공격자가 XSS 공격에 취약한 웹사이트를 찾아, 기존 웹사이트 URL 구조를 분석하여 악성스크립트를 담은 URL을 만든다.
    2. 공격자가 웹 상 어딘가에 해당 URL을 두고, 사용자가 이를 클릭한다. (보통 피싱 이메일 등으로 받는다.)
    3. 사용자가 URL을 클릭하면, 공격자가 작성한 악성 스크립트코드가 삽입된 요청을 original 사이트에 전송한다.
    4. 서버는 해당 악성스크립트 코드를 그대로 반사하여 브라우저에 실행시킨다.

    만약 악성 스크립트 코드에 사용자의 쿠키 및 정보를 탈취하는 내용이 있었다면, 공격자에게 사용자의 정보가 넘어간다. 공격자는 이렇게 빼앗은 쿠키 및 세션을 사용하여 사용자의 권한으로 행동할 수 있을 것이다.

     

     

    이때 반사(reflect)란, request에 담겨서 서버로 전달된 특정 쿼리스트링이 respond에 그대로 담겨 돌아오는 과정을 뜻한다. 서버가 쿼리스트링(etc. 사용자의 입력 값)을 필터링하지 않으면 이와 같이 Reflected XSS 공격에 취약한 반사를 일으키게 된다.

     

    때문에 사용자에게 입력받은 값을 서버에서 되돌려주는 웹사이트의 경우 Reflected XSS 취약성이 높다고 판단할 수 있다. 대표적으로 검색 엔진의 경우, 검색창에서 하나의 문자열을 검색할 때 일반적으로 결과 페이지에 그대로 다시 표시되므로 Reflected XSS 공격에 취약하다.

     

     

    Reflected XSS 공격의 예시를 살펴보자.

     

    위와 같이 XSS공격에 취약한 위 웹사이트가 있다고 가정하자. 위 웹사이트는 사용자로부터 입력값을 하나 받는다. 이는 input이라는 파라미터에 저장이 되고, url에 그대로 표시된다.

     

    이제 공격자가 위와 같이 word 부분에 악성 스크립트를 위치시킨 URL을 희생자에게 전송하고, 이를 클릭하도록 꼬신다.

     

    정상적인 페이지였다면 검색하고자 하는 단어를 입력하고 검색 버튼을 눌렀을 때, 해당 단어가 포함된 검색 결과를 반환할 것이다. 즉 사용자가 입력했던 단어가 그대로 html 코드 상에 위치한다는 뜻이다. 이 위치에 스크립트가 오게 되면, html 코드 상에 <script>alert("attack!!!");</script>가 위치하므로 스크립트가 실행되어 attack!!! 알람이 뜨게 된다.

     

     

    Reflected XSS 공격은 일반적으로 피해자가 링크를 클릭하여 스크립트를 실행하도록 유도한다. original 웹사이트의 서버에 스크립트를 저장해두지 않기 때문에 Non-persistent(비지속적, 1회성) XSS 공격이라고도 불린다.

     

     

     

    Persistent (Stored) XSS Attack

    영구적(Persistent) XSS 혹은 저장형(Stored) XSS라고 불리며, 보안이 취약한 웹사이트에 해커가 악성 스크립트를 저장한 후, 클라이언트가 스크립트가 저장된 곳을 방문하면 실행되도록 하는 공격을 말한다.

     

    1. 공격자가 original 웹사이트의 게시글, 방명록 등과 같은 곳에 악성 스크립트를 삽입한다.
    2. 사용자가 웹 사이트를 탐색하다가 해당 게시물에 방문한다.
    3. 사용자에게 악성 스크립트를 담은 게시물 조회 respond가 전달된다.
    4. respond 메세지가 실행되면서, 악성 스크립트가 실행된다.

     

     

     

     

    XSS 공격 피해

    XSS 공격을 받게 되면 웹 사이트가 훼손되거나, 정보가 도용되거나, Spoofing과 같은 피해가 일어날 수 있다.

     

    1. Web defacing(웹 훼손)

    JavaScript 코드는 DOM API를 사용하여 호스팅 페이지 내부의 DOM 노드에 액세스할 수 있습니다. 따라서 삽입된 JavaScript 코드는 페이지를 임의로 변경할 수 있습니다. 예: JavaScript 코드는 뉴스 기사 페이지를 가짜로 변경하거나 페이지의 일부 그림을 변경할 수 있습니다.

     

     

    2. Spoofing requests

    삽입된 JavaScript 코드는 사용자를 대신하여 서버에 HTTP 요청을 보낼 수 있습니다. (이후 슬라이드에서 논의)

     

     

    3. 정보 도용

    주입된 JavaScript 코드는 세션 쿠키, 웹 페이지에 표시된 개인 데이터, 웹 애플리케이션에 의해 로컬로 저장된 데이터를 포함한 피해자의 개인 데이터도 도용할 수 있습니다.

     

     

     

    XSS 공격 Surface

    공격을 시작하기 위해, 자바스크립트 코드를 삽입할 수 있는 곳을 찾아야한다. input field는 공격자가 자바스크립트 코드를 넣을 수 있는 잠재적인 공격 surface이다.

    웹 어플리케이션이 코드를 제거하지 않으면, 코드가 브라우저에서 실행되어 피해를 일으킬 수 있다.

     

     

     

    XSS Attacks Example

    "Brief Description" 필드에 코드를 삽입함으로써, Alice가 Samy의 프로필에 방문했을 때 코드가 실행되도록 하자.

     

    Elgg란 소셜 네트워킹을 위한 오픈소스 웹 어플리케이션이며, XSS 대응책이 실행되지 않는다.

    Elgg 웹사이트 : http://www.xsslabelgg.com 

    두 웹사이트는 Apache의 virtual hosting을 통한 localhost에 호스트되어있다.

     

     

    on HTTP GET services

    GOAL : Alice가 본인의 동의 없이 Samy를 친구추가한다.

     

    1. HTTP 헤더 캡쳐

    공격자는 웹페이지에 Samy, Charlie라는 이름으로 Elgg 계정을 두 개 생성한다. 이후 Charlie로 접속해서 Samy를 친구추가할 때 발생하는 HTTP request를 캡쳐한다.

    • Line 1 : Elgg의 친구 추가 request URL. 친구로 추가되는 유저의 UserID을 볼 수 있다. 즉 Samy의 UserID는 47이다.
    • Line 2 : Elgg의 CSRF 대응책. 정상적으로 동작한다.
    • Line 3 : 각 유저마다 고유한 세션 쿠키 값이다. 브라우저에 의해 자동으로 전송된다. 여기서 공격자가 쿠키에 접근하고자 할 경우, 자바스크립트 코드가 CSRF처럼 third party 페이지에서 온 게 아니라 Elgg 웹사이트에서 온 것이므로 허용될 것이다.

     

    2. CSRF Countermeasure parameter 값 찾기 : _elgg_ts, _elgg_token

    공격자는 CSRF 보호를 우회하기 위해 토큰 값을 찾아야한다. 이 값은 자바스크립트 변수에 할당되어, 페이지 내에서 찾을 수 있다.

    • Line 1, 2 : secret 값은 두 자바스크립트 변수에 할당되고, 이 변수들로부터 값을 가져와 공격을 더 쉽게 만들어준다.

    해당 공격의 자바스크립트 코드는 페이지 안에 삽입되므로, 페이지 내에서 자바스크립트 변수에 접근할 수 있다.

     

     

    3. 스크립트 구성

    • Line 1, 2 : 자바스크립트 변수로부터 타임스태프 값과 secret token 값을 가져온다.
    • Line 3, 4 : 데이터들을 첨부하여 URL을 구성하낟.
    • 나머지 코드 : Ajax를 이용해 GET request를 생성하는 내용이다.

     

    4. 프로필에 코드 삽입

     

    1. Samy가 본인 프로필의 "About me" 란에 스크립트를 작성한다.
    2. 이후 Alice로 로그인해서 Samy의 프로필을 방문한다.
    3. 자바스크립트 코드가 실행되지만 Alice에게는 보이지 않는다.
    4. 서버로 친구 추가 request가 전송된다.
    5. 이후 Alice의 친구 리스트를 확인하면, Samy가 추가되어있다.

     

     

    on HTTP POST services

    GOAL : 피해자(Alice)의 프로필을 "Samy is my hero" 문구로 동의 없이 수정한다.

     

    1. HTTP 헤더 캡쳐

    공격자는 Samy라는 이름으로 Elgg 계정을 생성하고, 프로필 수정 시의 HTTP request를 캡쳐한다.

    • Line 1 : Elgg의 프로필 수정 request URL.
    • Line 2 : 각 유저마다 고유한 세션 쿠키 값이다. 브라우저에 의해 자동으로 설정된다.
    • Line 3 : Elgg의 CSRF 대응책. 정상적으로 동작한다.
    • Line 4 : description 필드를 "Samy is my hero"로 설정한다.
    • Line 5 : 모든 필드의 accesslevel을 2로 설정한다. 모두에게 보여질 수 있다는 의미이다.
    • Line 6 : 피해자의 UserID(GUID)이다. 피해자의 프로필 페이지 소스를 방문해서 얻을 수 있다. XSS에서는 이 값을 페이지로부터 얻을 수 있기 때문에 elgg.session.user.guid.라는 자바스크립트 변수를 사용해서 GUID를 얻을 수 있다.

     

    2. 스크립트 구성

    • Samy 자신의 프로필인지 확인해야한다. 그렇지 않으면 악성 content를 Samy의 프로필에 덮어쓰게 될 수 있다.

     

    3. 프로필에 코드 삽입

    1. Samy가 본인의 프로필에 스크립트를 삽입하고, 다른 사람들이 그의 프로필을 방문하기를 기다린다.
    2. Alice 계정으로 로그인하여 Samy의 프로필을 방문하면, Samy의 프로필이 즉시 로드되고 악성 코드가 실행된다.
    3. Alice 프로필을 확인해보면, "Samy is my hero" 문구가 그녀의 프로필 About me 란에 추가되어 있는것을 볼 수 있다.

     

     

     

    Self-Propagation XSS Worm

    2005년, XSS 공격이 자체적으로 확산되도록 하는 Worm 바이러스가 개발되어 크게 확산된 적이 있었다. 해당 매커니즘을 살펴보고 self-propagation XSS worm을 구현해보자.

    XSS 공격은 악성 스크립트가 실행됨으로써 발생하므로, 자체적으로 확산되기 위해서는 자바스크립트 코드가 자기 자신을 복제할 수 있어야 한다. 대표적으로 두 가지 방법이 있다.

     

    1. DOM approach : DOM APIs를 통해 DOM에서 직접적으로 자바스크립트 코드가 자가복제 된다.

    2. Link apprach : <script> 태그 내에서 src 속성을 사용하는 링크를 통해 웹페이지 내에 자바스크립트 코드가 포함된다.

     

     

     

    DOM(Document Object Model) Approach

    DOM은 페이지의 내용을 개체 트리(DOM 노드)로 구성합니다.

    ● DOM API를 사용하여 트리의 각 노드에 액세스할 수 있습니다.
      ● 페이지에 JavaScript 코드가 포함되어 있으면 트리에 개체로 저장됩니다.
      ● 따라서 코드가 포함된 DOM 노드를 알고 있다면 DOM API를 사용할 수 있습니다.
    노드에서 코드를 가져옵니다.
      ● 모든 JavaScript 노드에 이름을 부여한 다음 document.getElementByID() API를 사용하여 노드를 찾습니다.

    ● “document.getElementById(“worm”)을 사용하여 노드의 참조를 가져옵니다.
      ● innerHTML은 스크립트 태그를 포함하지 않고 노드의 내부 부분을 제공합니다.
      ● 따라서 공격 코드에서는 전체 코드의 복사본과 함께 설명 필드에 메시지를 넣을 수 있습니다.

     

    window.onload = function() {
        var headerTag = "<script id=\"worm\" type=\"text/javascript\">";		(1)
        var jsCode = document.getElementById("worm").innerHTML;
        var tailTag = "</" + "script>";							(2)
        
        // 위 요소를 모두 더해 URI 인코딩을 진행한다.
        var wormCode = encodeURIComponent(headerTag + jsCode + tailTag);		(3)
        
        // description 필드와 access level을 설정한다.
        var desc = "&description=Samy is my hero" + wormCode;
        desc += "&accesslevel[description]=2";						(4)

    라인 ①과 ②: 스크립트 태그를 포함하여 웜 코드의 복사본을 구성합니다.
      라인 ②: 문자열을 두 부분으로 나누고 "+"를 사용하여 서로 연결합니다. 전체 문자열을 직접 입력하면 Firefox의 HTML 파서는 해당 문자열을 스크립트 블록의 닫는 태그로 간주하고 나머지 코드는 무시됩니다.
      두원량(Wenliang Du). 컴퓨터 및 인터넷 보안 2판.
    자기 전파 XSS 웜
      라인 ③: HTTP POST 요청에서 데이터는 "application/x-www-form-urlencoded"와 같은 Content-Type을 사용하여 전송됩니다. encodeURIComponent() 함수를 사용하여 문자열을 인코딩합니다.
      ④라인: 각 필드의 액세스 수준: 2는 공개를 의미합니다.
      Samy가 자신의 프로필에 이 자체 전파 코드를 배치한 후 Alice가 Samy의 프로필을 방문하면 웜이 실행되어 Alice의 프로필을 수정하고 그 안에 웜 코드의 복사본도 배치됩니다. 따라서 Alice의 프로필을 방문하는 모든 사용자도 같은 방식으로 감염됩니다.

     

     

    Link Approach

    • JavaScript 코드는 URL에서 가져옵니다. 예를 들어, xssworm.js라는 파일이 웹 페이지에 삽입된 스크립트 태그를 통해 호출됩니다.
    • 이 접근 방식에서는 프로필에 코드를 직접 포함시킬 필요가 없습니다. 웜 코드가 손상을 입히고 자기 복제를 달성하기 위해서는 페이지 내에서 코드가 실행되기만 하면 됩니다.

     

     

    Countermeasures

    Filter Approach

    • 사용자 입력에서 코드를 제거합니다.
    • <script> 태그 이외에도 다양한 방법으로 코드를 삽입할 수 있기 때문에 구현이 어렵습니다.
    • 예를 들어, onclick, onmouseover와 같은 태그 속성을 통해서도 JavaScript 코드가 삽입될 수 있습니다.
    • JavaScript 코드를 필터링할 수 있는 오픈소스 라이브러리를 사용하는 것이 좋습니다. 예를 들어, 'jsoup' 같은 라이브러리가 있습니다.

     

    Encoding Approach

    • HTML 마크업을 다른 표현으로 대체합니다.
    • 데이터가 브라우저로 보내지기 전에, JavaScript 코드가 포함된 데이터가 인코딩됩니다. 이렇게 하면 브라우저가 이를 JavaScript로 실행하지 않고 텍스트로 표시합니다.
    • 예를 들어, <script> alert('XSS') </script>를 &lt;script&gt;alert('XSS')&lt;/script&gt;와 같이 인코딩합니다.

     

    Elgg's Approach

     

    Content Security Policy

     

     

     

     

    💡 CSRF와 XSS의 차이점

     

    💡 Can we use the countermeasures against CSRF attacks to defend against XSS attacks, including the secret token and same-site cookie approaches?

     

     

    더보기
    728x90
    반응형
    LIST