간단히 말하면, xss란 브라우저 내에서 악의적인 코드로 인해 스트립트가 실행되는 공격기법을 말한다. 종류로는 크게 3가지와 추가적으로 알게된 Universal xss가 있다.
1. stored xss
말그대로 스크립트 코드가 저장된 형태로서 공격에 사용된다. 아래의 사진은 https://xss-game.appspot.com/level2 여기 워게임에서 2번 문제이다. stored xss를 이용하는 문제이다.
위 사진을 보면, 게시판 형태로 글을 게시할수 있다. 게시글에 일반적인 문자열 ssss을 입력하고 밑에 스크립트 태그를 입력했다. 그리고 렌더링된 코드를 보면, 입력한 스크립트 태그가 그대로 들어가 있는 것을 볼수있다.
요 문제에서는 <script>가 필터링이되서 다른 방법으로 alert() 창을 띄워야 하는데, 뭐 어쩃든 그게 중요한게 아니라 stored xss란 저렇게 입력한 값이 서버를 통해 그대로 저장이 되고, 그걸 다시 사용자의 브라우저에서 응답이 될때 악의적인 스크립트가 삽입이 되면, 어떠한 필터링이 없거나, 필터링을 우회하는경우 스크립트를 실행시킬 수 있다.
2. reflected xss
일단 stored xss의 경우. 입력 값 → 서버로 전송 → 저장 → 게시글로 보여줌 → 해당 게시글 클릭시 xss 터짐 요런 로직을 가지고 있다.
reflected xss도 매우 간단하다. 일반적으로 GET 요청인 경우, 파라미터가 URL에 붙여서 날라간다. 해당 URL 파라미터에 스크립트 태그를 넣게되고, 해당 url을 클릭했을때 스크립트가 실행되면 그걸 reflected xss라고 한다. 이해하기 쉽게 아까 그 워게임 사이트를 살펴보자.
위 사이트를 보면, 검색창이 하나 나온다. 저기에 문자열을 입력하고 Search 버튼을 누르게 되면, 입력한 값이 url 파라미터로 전송된다.
저렇게 입력한 값이 url 파라미터로 넘어가고, 입력한 문자열을 그대로 다시 보여준다. 그렇다면 저기 검색창에 스크립트 태그를 넣거나 아니면 url에 바로 스크립트 태그를 넣었을때 alert()이 뜬다면, 이는 xss 공격에 성공한 거고 이걸 바로 reflected xss라고 한다.
저렇게 파라미터에 스크립트 넣고 Go를 누르면 바로 반응한다. 그래서 reflected다.
3. Dom XSS
사실 요거랑 reflected xss랑 엄청 헷갈렸었다. 그래서 회의전에 질문하려고 했었는데, 때마침 알려주시는 형님이 저 차이에 대해서 물어봐서 정확히 알게 되었다. 이해한 내용을 예시로 함 봐보자
이런 페이지가 있다. (테스트로 만듬) test.php 페이에서는 파라미터로 들어온 값을 그대로 출력한다. 현재는 아무 파라미터가 없으니까 none을 출력한다.
para라는 이름으로 123을 넣으면 그대로 출력된다.
그렇다면 para에 스크립트를 넣으면 저렇게 바로 스크립트가 실행된다. 엥? 그럼 reflected xss랑 뭐가 도대체 다른거지? 둘다 url에 스크립트 쳐 넣어서 실행되는거 아님? 라고 존나 헷갈렸다. 하지만 두개는 차이점이 있는데, Dom Xss 인 경우는 다음의 상황에서 나타난다.
<html>
<head>
</head>
<body>
<p>hello</p>
<script>
var para=location.hash.substr(1);
var decode_para=decodeURI(para);
document.write("<p>"+"your parameter : "+decode_para+"</p>");
</script>
</body>
</html>
PHP
복사
•
location.hash는 보통 파라미터를 받을때 많이 사용하는 함수라고 한다. #을 구분자로 하여 #을 포함하여 뒤에 붙여진 파라미터를 저장한다.
•
location.hash.substr(1)은 #을 제외한 나머지 파라미터를 파싱하는 함수이다.
•
그럼 www.123.com#123 이렇게 123 파라미터를 파싱하고 있으면 location.hash.substr(1)를 이요해서 123을 파싱할 수 있다.
•
넘어온 파라미터는 인코딩이 되어있으므로, decode를 한번 해주고, 그거를 다시 브라우저에 출력해주는 코드이다.
•
하지만 입력값을 검증하는 경우가 없기 때문에 dom xss가 터진다. reflected xss와 차이점을 봐보자
<?php
echo 'hello'; echo '<br>';
if(isset($_GET['para'])){
echo "your parameter : ".$_GET['para'];}
else{
echo 'your parameter is none';
}
?>
PHP
복사
•
요거는 입력값을 $_GET[] 을 이용해서 받는다. (요건 php 문법임) . 저 코드가 서버에서 구현되어있다고 가정하면
•
현재 GET으로 요청들어온 값이 존재한다면 해당 값을 추출해서 그대로 출력해준다.
•
여기에도 역시 입력값 검증이 없기 때문에 xss가 실행될 것이다
정리하면 DOM은 파라미터를 location.hash로 파싱하여 서버까지 가지 않고, 브라우저 단에서 파싱한 데이터를 처리해서 그대로 보여준다. 이때 입력값 검증이 없어서 터지는 경우이다.
reflected는 입력값이 서버로 가서 거기서 파싱되어 처리가 되서 다시 응답을 해줄때 이역시 입력값 검증이 없어서 터지는 경우이다.