본문 바로가기

1. Web hacking (웹 해킹)/2) 개념 정리

[2020.05.19] Dreamhack 개념정리 - 4강 Client-side Advanced

 

https://dreamhack.io/

 

해커들의 놀이터, DreamHack

해킹과 보안에 대한 공부를 하고 싶은 학생, 안전한 코드를 작성하고 싶은 개발자, 보안 지식과 실력을 업그레이드 시키고 싶은 보안 전문가까지 함께 공부하고 연습하며 지식을 나누고 실력 향

dreamhack.io

1. Client-side Advanced

Client-side에서 발생하는 취약점들을 잘못 방어한 사례에 대해 알아보고 이를 공격하는 방법들을 다룬다. 이 외에도 XSS와 연계하여 HTML(DOM)과 자바스크립트 간에 객체 이름이 겹치는 것을 이용해 공격하는 DOM Clobbering에 대해 알아보고, 더불어 RPO(Relative Path Overwrite) 공격기법과 이를 방어하는 법에 대해서도 알아본다.

2. XSS

XSS 방어에는 다양한 방법이 존재한다.

가장 확실한 방법은 사용자가 HTML 태그나 엔티티 자체를 입력하지 못하도록 하고, 대신 입력을 서식 없는 평문(plaintext)으로 취급하는 것이다.

 

 

태그 및 속성 필터링 

코드를 실행할 수 있는 HTML 요소는 <script>​ 태그 이외에도 상당수 존재한다. 스크립트를 포함할 수 있는 속성이 존재한다.

대표적으로 이벤트 핸들러를 지정하는 on으로 시작하는 속성들이 있다.

많이 사용되는 이벤트는 load error가 있으며, 사용 예시는 아래와 같다.

(위의 예시 외에도 다양한 이벤트가 존재하며, 각 이벤트가 발생하는 원리도 다양하다. 자세한 정보는 Mozila Developer Network 에서 확인해볼 수 있다.)

요소의 속성값 또한 &lt; 와 같은 HTML 엔티티를 포함할 수 있어 본래 코드를 숨길 때 사용될 수 있다.

단순히 태그나 속성을 바탕으로 필터를 하게 되면 우회가 가능한 경우가 많다.

다음은 취약한 필터의 예시이다.

* 대문자 혹은 소문자만을 인식하는 필터 우회

 

 

* 잘못된 정규표현식을 사용한 필터 우회

 

* 특정 태그 및 속성에 대한 필터링을 다룬 태그 및 속성을 이용하여 필터 우회

 

JavaScript 함수 및 키워드 필터링

JavaScript는 Unicode escape sequence*, computed member access** 등 코드를 난독화할 수 있는 다양한 기능들을 포함하여 다음과 같이 필터를 우회할 수 있다.

* Unicode escape sequence: "\uAC00" = "가"와 같이 문자열에서 유니코드 문자를 코드포인트로 나타낼 수 있는 표기

** computed member access : 객체의 특정 속성을 접근할 때 속성 이름을 동적으로 계산함.

atob decodeURI 함수는 각각 Base64 및 URI로 인코딩된 데이터를 디코딩하는 함수로써 키워드 등을 부호화하여 필터를 우회할 수 있다.

 

다음은 XSS 공격에 흔히 사용되는 구문과 필터 우회를 위해 사용될 수 있는 대체 예시이다.

극단적인 사례로 JavaScript의 언어적 특성을 활용하면 6개의 문자 [, ], (, ), !, + 만으로 모든 동작을 수행할 수 있다.

이 기법은 cookie와 같이 기존 XSS 필터들이 주로 탐지하는 단어들을 언급하지 않아도 된다는 장점이 있어 상당수의 웹 사이트를 공격하는 데에 활용되어 왔다.

필터링 또는 인코딩/디코딩 등의 이유로 특정 문자 (), [], ", ' 등을 사용하지 못하는 경우가 있다.

JavaScript는 다양한 문법을 지원하는 언어로써 해당 문자를 대체할 수 있는 방법들을 통해 우회하여 공격할 수 있다.

문자열 선언

● 일반적인 방법

quotes ", ' 또는 Template literals 사용

 

● quotes 또는 Template literals를 사용하지 못하는 경우

 

함수 호출

○ 일반적인 방법

괄호(parentheses, () ) 또는 Tagged templates 사용

 

○ 괄호 또는 Tagged templates를 사용하지 못하는 경우

 

* 기타

 

 

문자열 치환

필터되는 문자열 사이에 또 다른 필터되는 문자열을 넣으면 최종적으로 바깥의 필터되는 문자열이 다시 나타나게 되어 필터가 무력화된다, 또, 웹 응용 방화벽(Web Application Firewall) 등에서 탐지하지 못하게 하는 부작용이 발생하게 된다.

대안 접근 방식으로 흔히 다음과 같이 스트링에 변화가 없을 때까지 지속적으로 치환하는 방식이 사용되곤 한다. 특정 키워드가 최종 마크업에 등장하지 않도록 하는 데에 효과적일 수 있지만 미처 고려하지 못한 구문의 존재, WAF 방어 무력화 등은 동일하다는 점을 기억해야 한다.

 

 

활성 하이퍼링크

HTML 마크업에서 사용될 수 있는 URL들은 활성 콘텐츠를 포함할 수 있다. 이 중 javascript: 스키마는 URL 로드 시 자바스크립트 코드를 실행할 수 있도록 한다.

브라우저들은 또한 URL를 사용할 때 정규환(normalization)를 거치는데, 이 과정에서 \x01, \x04 와 같은 특수 제어 문자들이 제거될 수 있다.

HTML 요소 속성에서 엔티티를 사용할 수 있다는 점을 이용하면 다양한 우회 기법을 사용할 수 있게 된다.

 

JavaScript에서는 URL 객체를 통해 URL을 직접 정규화할 수 있으며, protocol, hostname 등 URL의 각종 정보를 추출할 수 있다.

디코딩 전 필터링 (Double encoding 등)

본래 입력 검증은 디코딩 등의 모든 전처리 작업을 마치고 최종적으로 사용되는 형태에서 이루어져야 한다.

그러나 일부 웹 응용은 웹 방화벽 등의 필터링 기능에 의존하거나, 데이터의 개별 요소를 추출하기 전 데이터를 전체 데이터(JSON,Form data 등)에 필터를 가하는 경우가 있다.

예시로, 웹 방화벽(Apache HTTP Server의 mod_security 등)을 사용하는 응용에서 만일 POST 요청으로 데이터를 받는데 파라미터 값에 추가로 URL Decode를 가한다면 방화벽의 XSS 필터링은 무효화된다.

마찬가지로 내부 응용에서 XSS 필터 검사를 하고 URL Decode 등을 가한다면 %253E%3E< 식으로 필터가 무용지물이 되어버린다.

불필요한 인코딩을 줄이고, 응용에서 사용되는 인코딩 방식을 통일하는 등으로 디코딩 전, 필터링 취약점을 줄일 수 있다.

 

 

 

길이 제한

삽입될 수 있는 코드의 길이에 제한이 있는 경우, 다른 경로로 실행할 추가적인 코드(payload)를 URL fragment 등으로 삽입 후 삽입 지점에는 본 코드를 실행하는 짧은 코드(lanuncher)를 사용할 수 있다.

Fragment로 스크립트를 넘겨준 후 XSS 지점에서 loaction.hash로 URL의 Fragment 부분을 추출하여 eval()로 실행하는 기법이 흔히 쓰인다.

그 외에도 쿠키에 페이로드를 저장하는 방식과 import와 같은 외부 자원을 스크립트로 로드하는 방법도 사용할 수 있다.

* location.hash를 이용한 공격방식

* 외부 자원을 이용한 공격 방식

 

 

3. CSP

CSP: Content Security Policy, 컨텐츠 보안 정책

CSP는 XSS 공격이 발생하였을 때 그 피해를 줄이고 웹 관리자가 공격 시도를 보고받을 수 있도록 하는 기술이다.

웹 페이지에 사용될 수 있는 자원에서 위치 등에 제약을 걸어 공격자가 웹 사이트에 본래 있지 않던 스크립트를 삽입하거나 공격자에게 권한이 있는 서버 등에 요청을 보내지 못하도록 막을 수 있다.

CSP는 XSS 등 공격의 피해를 완전히 무력화하기 위한 수단은 아니기 때문에 XSS에 대한 자체적인 방어가 병행되어야 한다.

CSP 헤더는 1개 이상의 정책 디렉티브가 세미콜론 ';' 으로 분리된 형태로 이루어져 있다.

정책 디렉티브는 지시어 종류 (ex. default-src, script-src)와 1개 이상의 출처 (ex. 'self', https:, *.dreamhack.io)가 스페이스로 분리된 형태로 지정하여야 한다.

다은은 페이지 내부의 자원들이 같은 Origin 또는 https:// example.dreamhack.io 에서만 로드되어야 함을 나타내는 CSP 헤더이다.

 

 

다음은 <script nonce="1AfdcQ8/gY+d1Yarc7=="> 와 같이 특정 nonce 속성이 입력된 태그만을 허용하며, 추가로 <base> 태그가 현재 페이지가 참조하는 상대 경로들이 해석되는 기준점을 바꾸지 못하도록 한다.

nonce 값은 공격자가 예측할 수 없도록 페이지를 접근할 때마다 재생성하여야 한다.

 

 

다음은 SHA384 해쉬가 38b060a751ac9638...4898b95b 인 스크립트를 허용하는 CSP 헤더이다.

 

만약 페이지가 PHP나 Python CGI 등 동적 기능을 사용하지 않는 정적인 웹 페이지라면 CSP 정책을 HTML <meta> 태그로도 지정할 수 있다.

이는 바뀌지 않는 자원들을 별도의 HTTP 서버 설정 없이 HTML 페이지 내에서 지정할 수 있도록 한다.

동적 웹 페이지에서도 사용할 수 있으나 사용자가 동적 콘텐츠를 이용해 CSP를 무력화하지 못하도록 주의해야 한다.

CSP 규칙은 가능한 한 세밀하게 설정하는 것이 좋다.

CSP 정책이 관용적으로 설정될 경우 (ex. 특정 CDN의 모든 자원 허용) 공격자는 CSP 내에서 허용된 서버를 공격하거나 웹 사이트의 API 엔드포인트 등을 역이용하여 XSS 공격을 감행할 수 있어 효과가 떨어지게 된다.

 

 

CSP 우회 - 신뢰하는 도메인에 업로드

CSP를 이용하면 브라우저가 특정 웹 사이트에서만 자원을 불러오게끔 제한할 수 있다.

만약 해당 웹 사이트가 파일 업로드 및 다운로드 기능을 제공한다면, 공격자는 해당 사이트에 스크립트 등을 업로드한 뒤 다운로드 주소로 대상 웹 페이지에 해당 자원을 포함시킬 수 있게 된다.

 

이 외에도 JSONP API가 신뢰하는 도메인에 존재한다면 다음과 같은 공격이 가능하다.

이에 대한 해결책

도메인 Origin 대신 해쉬나 nonce 등을 이용하는 방법이 있다.

부득이하게 웹 사이트 단위 자원 출처 지정이 필요한 경우 HTTP 요청의 Accept 헤더를 바탕으로 현재 요청이 <script src=".."> 등에서 기원한 것인지 확인하여 요청을 거부할 수 있다.

한편, JSONP API를 제공하는 서비스는 콜백 이름에 식별자를 제외한 문자를 거부함으로써 이를 추가적으로 방어할 수 있다. 그러나 가능한 경우 JSONP보다는 CORS를 지원하는 API를 사용하는 것이 좋다.

CSP에서 기본적으로 사용할 수 있는 Origin 명세는 다음과 같다.

 

CSP 우회 - nonce 예측 가능

CSP의 nonce를 이용하면 따로 도메인이나 해쉬 등을 지정하지 않아도 공격자가 예측할 수 없는 특정 nonce 값이 태그 속성에 존재할 것을 요구함으로써 XSS 공격을 방어할 수 있다.

이 방어가 효과적이기 위해서는 nonce 값이 공격자가 취득하거나, 예측할 수 없는 것이어야 한다.

이는 보통 매 요청마다 nonce를 새로 생성함으로써 이루어지는데, 만일 이를 생성하는 알고리즘이 취약하여 결과를 예측할 수 있다면 공격자는 이를 유추해 자신의 스크립트를 웹 사이트에 삽입할 수 있다.

nonce를 사용할 때에는 nonce 값을 담고 있는 HTTP 헤더 또는 <meta> 태그가 캐시되지 않는지 주의하여야한다.

PHP나 CGI 계열 스크립팅을 사용할 때에는 특히 주의하여야한다. 왜냐하면 스크립트들이 마치 디렉토리처럼 /index.php/style.css 와 같이 뒤에 추가적인 경로를 부텨 접근될 수 있기 때문이다.

만약 캐시 서버가 확장자를 기반으로 캐시여부를 판단한다면 .css는 일반적으로 정적파일이므로 동적 콘텐츠로 간주하지 않아 캐시에 저장할 수 있고, 이 경우 캐시가 만료될 때까지 요청시만다 같은 nonce가 들어오기 때문에 공격자는 이를 바탕으로 nonce를 획득할 수 있다. 콘텐츠가 캐시되어 서버측 XSS가 일어나지는 않으나, DOM XSS 등 클라이언트 측에서 일어날 수 있는 공격에 취약해지게 된다.

○ Nginx와 PHP FastCGI SAPI(php-fpm)를 사용하였을 때의 예시

 

아래는 shnippets/fastcgi-php.conf 의 내용이다.

 

위와 같은 Nginx 설정을 갖고 있을 때 /dom_xss_vulnerable.php/style.css 의 주소로 접근하면 dom_xss_vulnerable.php 파일이 실행되어 nonce<meta http-equiv="Content-Security-Policy" content="... nonce ..."> 태그로 출력된다.

CDN은 보통 CSS 또는 스크립트 등 정적 파일을 캐싱하기 때문에 meta 태그로 출력된 nonce 또한 같이 캐싱된다. (https://docs.microsoft.com/ko-kr/azure/cdn/cdn-how-caching-works )

따라서 DOM XSS에 취약한 해당 페이지의 nonce 값이 고정되어 공격자는 <script nonce="{고정된 nonce 값}"> alert(1); </script> 와 같은 마크업을 이용할 수 있다.

PATH_INFO 기능을 사용하지 않는 경우

해당 설정은 location ~ \.php$ 처럼 URL의 끝부분이 .php 일 때만 FasgCGI로 넘어가게 수정되어야 한다. 또한 URL에 a/b.php/c/d,php 와 같이 .php 중복으로 사용될 때를 대비하여 fastcgi-php.conf 스니펫을 사용하지 않고 다음과 같이 변경되어야 한다.

 

 

CSP 우회 - base-uri 미지정

HTML 하이퍼링크에서 상대 경로를 지정하면 브라우저는 마치 파일 경로처럼 기본적으로 현재 문서를 기준으로 주소를 해석하게 된다. HTML <base> 요소는 상대 경로가 해석되는 기준점을 변경할 수 있도록 하며, <a>, <form> 등의 target 속성의 기본 값을 지정하도록 한다.

만일 공격자가 <base href="https:/malice.test/xss-proxy/">와 같은 마크업을 삽입하면, 추후 상대 경로를 사용하는 URL들은 본래 의도한 위치가 아닌 공격자 서버의 자원을 가리키게 된다. 공격자는 이를 통해 임의의 스크립트 등을 삽입할 수 있게 된다.

본래 <base> 태그의 href 속성을 사용하지 않는 페이지라면 이를 방어하기 위해 다음과 같은 정책을 설정할 수 있다.

 

 

* 임의의 HTML 마크업을 삽입해 글을 올릴 수 있는 서비스가 있다고 가정하자.

해당 서비스는 업로드 과정에서 필터링을 통해 <a> 태그 내에 있는 href 속성이 외부 링크면 내부 페이지(아래 link.php)로 이동해 경고하는 기능을 제공한다.

 

외부 링크는 내부 link.php를 거쳐가게 된다.

CSP의 base-uri 지시어를 지정해주지 않으면 위 방법으로 우회할 수 있다.

이를 막기 위해 CSP base-uri 'none' 정책을 사용해야 한다.

 

4. CSRF

잘못된 CSRF Token 생성

CSRF Token은 같은 Origin에서만 접근 가능한 형태로 특정 토큰을 저장해 제3자가 아닌 사용자로부터 요청이 왔다는 것을 인증할 수 있는 방법이다.

CSRF Token 값은 보통 HTML Form의 hidden 필드로 입력되나, 동적 요청에서도 사용될 수 있다.

CSRF Token 방식은 CAPTCHA 또는 암호방식과 달리 추가적인 사용자 상호작용이 불필요하다는 장점을 가지고 있다.

하지만 XMLHttpRequest나 Fetch API 등으로 Authorization과 같은 헤더를 설정하여 통시하는 것에 비해 여러 가지 보안 문제의 원인이 되기도 한다.

CSFR Token 취약점 예시

- 짧은 CSRF Token

CSRF Token은 외부자가 예측 불가능하도록 설계된 만큼, 무차별 대입공격(brute-force attack)이 효과적이지 않도록 토큰의 길이가 충분히 길어야 한다.

- 예측 가능한 CSRF Token (PRNG 등)

토큰의 길이가 충분해도, 공격자가 충분히 접근 가능한 데이터 (ex. 현재 시간 등)을 바탕으로 생성하거나 또는 암호학적으로 안전하지 않은 의사 난수 생성기를 사용하게 되면 토큰 예측이 덜 어려워진다.

이 경우, 공격자는 토큰을 추론해 사용자의 신원 정보를 탈취할 수 있다.

공격자가 예측할 수 없거나, 충분한 안전성이 보장된 난수 생성기(CSPRNG)를 사용해야 예측 공격을 방지할 수 있다.

- CSRF Token 유출

CSRF Token이 제공하는 보안은 토큰이 공격자가 알지 못함을 전제로 하며, 따라서 다른 경로로 제3자에게 노출되지 않도록 주의해야 한다.

CSRF Token이 URL의 Query 파라미터로 넘겨지게 되면 이후 다른 링크를 방문했을 때 Referer 헤더로 토큰이 그대로 노출되고, 공격자는 이를 이용해 역으로 사용자를 공격할 수 있게 된다.

5. CORS

이 주제에서는 CSP 기술의 사용에 있어서 주의할 점과 취약점 발생 시 CSRF 등 다른 취약점과 연계되는 방식에 대해 알아보도록 하자.

CORS 기술의 사용에 있어 발생할 수 있는 취약점은 크게 다음과 같이 나눌 수 있다.

- 현재 사이트에서 다른 사이트로 정보 유출

- 다른 사이트에서 현재 사이트 변조 (무결성)

Window.postMessage API

SOP가 도입되면서 서로 다른 오리진들은 직접적으로 리소스를 공유하지 못하게 되었다. 이를 해결하기 위해서 Origin을 횡단하여 메시지를 주고받을 수 있는 API가 고안되었다.

메시지를 전송할 때는 대상 윈도의 postMessage 메소드를 호출, 수신하는 윈도는 message 전역 이벤트를 청취하여 메시지를 받을 수 있다.

* targetWindow.postMessage(message, targetOrigin[, transfer])

 

* message 이벤트 (MessageEvent)

 

postMessage 를 통해 message로 문자열뿐만 아니라 객체 또한 주고받을 수 있으나, 보안을 위해 함수(객체 메소드 포함), DOM 노드(요소 등) 객체, 프로토타입 및 get/set 속성 정보는 보낼 수 없다.

또한, 전송되는 모든 객체는 복사되므로 송신 후 객체를 변경해도 수신하는 윈도에서는 변경 내용을 볼 수 없다.

Window.postMessage 사용 시 취약점 - Origin 미확인

Window.postMessage API 사용시 Origin을 명확히 지정 및 검사해야 한다.

SOP를 우회하여 자유자재로 다른 윈도와 통신할 수 있도록 만들어진 API이기 때문에 Origin 검사 또한 웹 개발자의 책임이 된다.

특정 윈도는 모든 Origin에서 오는 메시지를 수신할 수 있는데, 이때 message 이벤트 핸들러에서 origin 속성을 검사하지 않고 메시지의 내용을 신뢰하면 보안 문제가 발생할 수 있다.

 

 

Window.postMessage 사용 시 취약점 - Origin 전환 경합 조건

postMessage를 사용할 때, 메시지를 보내는 대상은 웹 문서가 아닌 창(윈도)이다.

웹 문서는 보통 그 출처가 고정되어 있지만, 창의 경우에는 가용자가 하이퍼링크를 방문하거나 스크립트가 다른 문서로 Redirect시켜 들어 있는 문서가 바뀔 수 있다.

이 상태에서 메시지를 보내게 되면 본래 의도하지 않는 Origin에 메시지가 누출되는 보안 문제가 발생할 수 있다.

postMessage의 두 번째 매개변수 targetOrigin에 대상 Origin 문자열을 명시하면 이 문제를 해결할 수 있다.

브라우저에서 메시지 송신 시점에서 Origin을 검사하여 일치하지 않는 경우 송신을 거부한다.

반면 "*"을 지정하는 것은 targetWindow의 Origin이 무엇이든지 상관없이 메시지가 보내지므로 권장하지 않는다.

* https://dreamhack.io/ 예시

 

* https://settings.dreamhack.io/ 예시

 

* https://attacker.text/entry 예시

 

JSONP

JSONP란?

JSON with Padding의 준말. CORS 기술이 도입되기 전 SOP를 우회하기 위해 흔히 쓰였던 방식이다.

JSONP API는 JSON API과 유사한, 응답 데이터를 특정 콜백 함수를 호출하는 코드로 감싸고 요청 시 XHR이 아니라

<script src="https://api.test/request.jsonp?id=123&callback=onAPIResonse"> 와 같이 스크립트로 포함시켜 동작한다는 점이 다르다.

 

응답은 onAPIResponse({...}); 식으로 생성되어 최종적으로 본래 문서의 함수를 호출하게 된다.

JSONP에 의해 발생할 수 있는 취약점

- Origin 검사 부재로 인한 CSRF

- 콜백 함수명 검증 부재로 인한 제공자 XSS

- JSONP API 침해 사고 발생시 사용자 XSS

CORS 정책

CORS 정책은 서버가 HTTP 응답 헤더를 통해 직접 허용하고자 하는 Origin을 지정할 수 있도록하는 기술로, SOP와 JSONP의 한계를 넘기 위해 설계되었다.

JSONP가 지니고 있던 문제를 해결하여 타 서비스에서 유입된 스크립트를 실행하지 않고도 XMLHttpRequest 등으로 타 웹사이트의 자원을 요청할 수 있다.

CORS 요청 보낼 때

브라우저는 먼저 대상 웹 서버에 OPTIONS 메소드를 가진 예행(pre-flight)요청을 추가로 보낸다. 이는 서버가 CORS 접근을 인식하고 지원하는지 판별하기 위한 과정으로, 만일 서버가 OPTIONS 헤더를 지원하지 않는다면 CORS 표준에 맞지 않는 응답을 보내게 되고, 요청은 중단된다.

만일 서버가 CORS 정책을 지원하면 OPTIONS 요청의 응답에 허용되는 Origin 등의 정보를 보내게 된다.

CORS와 관련된 HTTP 헤더는 다음과 같다.

 

CORS 정책을 요청하는 클라이언트의 헤더는 다음과 같다.

 

 

6. Exploit Techniques

XSS 공격과 연계할 수 있는 익스플로잇 테그닉에 대해서 알아보도록 하자.

Relative Path Overwrite (RPO)

특정 URL의 하위 경로를 접근해도 같은 웹 페이지가 출력되는 것을 이용해 페이지에서 참조된 상대 경로 URL의 기준점을 바꾸는 공격

예를 들어,

아래와 같이 스크립트를 로드하는 태그가 두 개 있다.

 

1번째 줄과 2번째 줄의 스크립트 태그의 차이는 src의 맨 앞에 존재하는 /의 차이가 있다.

1번째 줄은 앞에 존재하는 /에 의해 스크립트 로드시 최상위 경로부터 시작하여 탐색(절대 경로)하고 로드한다.

반면에 2번째 줄의 스크립트는 현재 경로에서 시작해서 탐색(상대 경로)하고 로드한다.

../ 와 같이 경로를 조작하여 해당 서버에서 원하는 스크립트 등이 해당 페이지에 로드 되도록 유도하여 공격에 사용할 수 있다.

RPO를 방어할 수 있는 최선의 방법

CSS, JavaScript 등을 참조할 때 절대경로(ex. /js/util.js 또는 https://mydomain/js/util.js)를 사용하는 것이다.

DOM Clobbering

메일 수신자, 게시글 작성자 등 제 3자에 의해 HTML 마크업이 제공될 때, idname과 같은 속성을 이용하여 JavaScript에서 접근할 수 있는 전역변수 공간 또는 개체 속성 공간 상에서 원하는 이름으로 임의의 DOM 객체를 삽입하는 공격

웹 프로그램을 하다 보면 document.getElementById()​를 사용하지 않고도 노드 id를 변수처럼 사용할 수 있음을 알 수 있다. Window 전역 객체는 JavaScript Proxy와 유사한 형태로 구현되어 있어 정의되지 않은 속성은 DOM에서 찾게된다. 이 외에도 form 요소 또한 하위 요소를 name 값으로 찾을 수 있도록 되어 있다.

 

만약 HTML 마크업이 사용자나 제 3자로부터 제공된다면 문제가 발생할 수 있다.

글로벌 변수 이름공간이나 요소 객체 속성은 미리 정의된 속성(ex. element.innerHTML, window.open 등)과 충돌할 수 있으며, 프로그래머가 예상했던 것과 다른 값이 반환되게 된다.

만약 웹 응용이 미리 정의되지 않은 전역 변수에 접근한다면 공격자가 입력한 요소로 대체되어 반환될 수 있다. 또한 form 등 요소에서 속성을 접근할 때 본래 속성값이 아닌 삽입된 객체가 반환되게 된다.

DOM Clobbering을 방어할 수 있는 가장 효과적인 방법

간접적 메소드 호출 및 접근자를 사용한다. (ex. Funtion$call)

 

Template / DOM XSS

서버측 XSS 공격과 유사하나 JavaScript에서 innerHTML 등 마크업을 해석하는 속성을 사용하거나 템플릿 라이브러리를 사용할 때 그 마크업 또는 템플릿을 제3자가 제공 가능할 때 이를 이용해 스크립트 등을 삽입하는 공격

DOM에서 innerHTML, outerHTML, insertAdjacentHTML 등은 스크립트에서 HTML 마크업을 삽입할 수 있도록 한다. 또한, 다양한 자바스크립트 라이브러리 또는 프레임워크는 {{ 1 + 1 }} 와 같이 코드나 식을 실행하여 그 결과를 문서에 표시할 수 있도록 하는 템플릿 엔진을 제공하고 있다.

 

만약 이들 마크업이나 템플릿을 제 3자가 입력할 수 있다면 다음과 같이 임의의 스크립트를 실행할 수 있게 된다.

 

 

DOM XSS를 방지하려면

가급적 innerHTML와 같이 마크업을 해석하는 속성의 사용을 피해야하고, 부득이 서식 등 마크업 입력이 필요한 경우 서버측 XSS 방어와 같이 XSS 필터를 이용하여 안전한 마크업이 삽입되도록 해야한다.

템플릿을 사용하는 경우도 마찬가지로 외부에서 들어오는 입력을 템플릿으로 사용하지 않는 것이 좋다.

CSS Injection

다른 태그들의 사용이 불가하고, style 태그 또는 style 속성에 대해서 변조가 가능할 때 사용할 수 있는 방법 중 하나. 다른 태그의 속성 값을 참/거짓(True/False)의 방식을 통해 알아내거나, HTTP 트래픽을 생성시킬 수 있다.

Attribute Selectors

 

p 태그 중 name 속성의 값이 test인 태그를 지정하여 color를 red로 설정하는 CSS문법이다.

 

HTTP Send

 

위와 같은 문법들을 통해 HTTP 요청을 생성할 수 있다.

아래와 같이 중요한 데이터가 페이지 내에 존재하며, css 문법을 사용할 수 있을 경우 CSS Injection을 통해 해당 페이지의 중요 정보를 획득할 수 있다.

 

 

* 공격 페이로드 - 1 

[value^='a'] value의 첫 단어가 a인 경우 background 이미지로 http://hacker.dreamhack.com/a에 요청하는 문법이다.

즉 위와 같은 페이지에서는 [value^='S'​] 조건이 참이 되며, http://hacker.dreamhack.com/S 주소에 HTTP 요청을 전송하게 된다.

해당 HTTP 요청을 받는 공격자는 password의 첫 단어가 S라는 것을 알 수 있게 된다.

 

 

* 공격 페이로드 - 2

첫 단어가 S 라는 점을 알게된 후 다시 한번 요청하여 다음 단어를 획득할 수 있다.

이와 같은 방법을 반복하여 전체 단어를 획득할 수 있다.

 

 

Attribute Selectors syntax