사용자의 브라우저(크롬, 익스플로러, 엣지, 웨일 등등)에서 스크립트가 실행되도록 공격자가 악의적인 스크립트를 사용자로 하여금 실행되도록 하는 공격 방법입니다.
XSS(Cross-Site Script)를 사용한 공격은 세션을 가로채거나 웹 페이지 변조, 악성 콘텐츠 삽입, 피싱 공격 등에 주로 사용됩니다.
주로 XSS(Cross-Site Scirpt) 공격은 3가지로 분류가 됩니다.
Reflected-XSS : 공격자가 피해자로 하여금 서버에 스크립트를 실행하도록 유도하여 정보를 요청하도록 만드는 공격입니다. 사용자가 요청한 정보를 공격자에게 전송하도록 설정하여 의도한 정보를 획득하는 방식입니다. URL 접근으로 스크립트를 피해자의 PC에서 전송하도록 만드는 공격으로 1회성 공격이라고 할 수 있습니다.
Stored-XSS : 공격자가 서버에 저장하여 공격하는 방식으로 덫을 설치한다고 생각하면 쉽습니다. 공격자가 취약한 게시판이나 댓글 등의 공간에 악의적인 스크립트를 저장하여 해당 게시물에 방문한 피해자가 스크립트를 실행하여 공격자에게 전송하는 방식입니다. Stored-XSS는 서버의 데이터베이스에 저장되어 방문하는 사용자는 상대로 실행되기 때문에 지속적인 피해를 발생시킬 수 있습니다.
DOM(Document object Model) Based XSS : 문서 객체 모델(DOM)을 사용하여 피해자의 브라우저에서 서버와 상호작용하지 않고 실행되는 스크립트입니다. 서버를 상대로 하지 않은 공격이고 대상은 피해자로 정해진 공격입니다. 스크립트 삽입 시에 서버로 전송되는 패킷에 스크립트가 포함되지 않고 피해자의 브라우저만을 상대로 하기 때문에 웹 사이트의 코드를 확인하지 않고는 발견할 수 없는 취약점입니다.
세 가지의 XSS 종류 중 Reflected와 DOM based는 비슷한 부분이 많지만 가장 큰 차이점은 서버에 스크립트를 전송하여 정보를 획득하는 방식과 피해자의 브라우저만을 상대로 하느냐가 차이입니다.
Reflected와 Stored는 응답 페이지의 HTML에서 삽입된 악성 스크립트가 보이기 때문에 발견 가능성이 높지만, DOM based는 패킷에서 보이는 공격이 아니기 때문에 웹사이트의 코드나 URL을 자세하게 보지 않는 이상 발견하기 어려운 취약점입니다.
공격 방법
(본 취약점은 DVWA를 활용하여 실습해보도록 하겠습니다.)
1.Reflected-XSS
1) Low Level
Low Level의 보안을 위한 필터를 없는 것으로 확인됩니다.
기본 스크립트 삽입을 시도해 보겠습니다.
<script>alert("XSS")</script>
소스 내에 따로 구현된 필터링이 없기 때문에 script를 사용하여 시도하도록 하겠습니다.
삽입된 스크립트가 정상적으로 실행되는 것을 확인할 수 있습니다.
2) Medium Level
페이지의 형태는 Low Level에서 본 것과 같은 것을 확인할 수 있습니다.
소스코드를 확인해보니 str_replace를 이용해 <script>를 빈칸으로 필터링하는 것을 확인할 수 있습니다.
위와 같은 경우에는 script를 사용하지 않고 태그를 이용하여 시도해보도록 하겠습니다.
<SCRIPT>alert("XSS")</SCRIPT>
소스코드를 확인했을 경우 <script>를 필터링하는 것을 확인할 수 있었습니다. 하지만 저 문자열 즉 소문자로 구성된 <script>만을 필터링하고 있으므로 대문자로 바꾸어주고 시도해보도록 하겠습니다.
스크립트가 정상적으로 실행되는 것을 확인할 수 있습니다.
필터링이 된다고 하더라도 필터링 방식에 따라 대소문자 구별만으로도 성공할 수 있는 것을 확인할 수 있었습니다.
3) High Level
페이지의 형태는 전과 동일합니다.
소스코드를 확인해보면 전과 달리 대/소분자 전부 필터링하는 것을 확인할 수 있습니다.
이런 경우에는 script를 사용하지 않고 태그를 이용하여 시도할 수 있을 것이라 생각하고 진행해보도록 하겠습니다.
위에서 img와 on 태그를 사용해서 스크립트를 작성해보았습니다.
img는 src에 redirect를 걸어줄 필요는 없기 때문에 blank로 두고 onerror에 alert를 삽입하여 진행해보도록 하겠습니다.
삽입된 스크립트가 정상적으로 실행되는 것을 확인할 수 있습니다.
위와 같은 경우 script를 사용하지 않고 on 태그를 사용하여 XSS를 성공했습니다.
사용 가능한 스크립트 태그를 생각나는 대로 나열해보면 script, iframe, object, onerror, onmouseover, onload, img, a 등등이 있습니다.
하지만 여기에서 볼 수 있는 소스코드의 차이점은 message와 name필드에 다르게 적용된 보안 조치입니다.
message필드는 htmlspecialchars( $message )로 조치된 것을 확인할 수 있는데 우회하는 방법으로 나오는 것 들은 소스코드 내에 취약한 태그가 있어서 삽입된 스크립트가 실행되는 경우 말고는 알고 있는 바가 없습니다.
(혹시 아는 분은 알려주세요ㅋㅋ)
하지만 name필드는 <script>만을 필터링하고 있으며 reflected medium level때와 같이 해당 문자열 만을 필터링하고 있다는 것을 알 수 있습니다.
그럼 전과 마찬가지로 시도하고 싶지만 name 필드의 maxlength가 10으로 제한되어 삽입할 수 없다고 생각할 수 있습니다. 이런 경우 우회 방법은 여러 가지가 있지만 두 가지만 말하자면 첫 번째는 개발자 도구에서 maxlength값을 바꿔주는 것이고 두 번째는 파라미터를 수정하는 방법이 있습니다.
먼저 maxlength값을 바꿔보도록 하겠습니다.
변경하려는 필드를 더블클릭하면 위 사진처럼 변경이 가능합니다.
물론 사용자 브라우저에서 HTML 코드 수정이므로 서버와는 관련이 없습니다.
바꾼 후에 작성해보면 위와 같이 작성되는 것을 확인할 수 있습니다. 그 상태에서 Sigh Guestbook을 눌러주시면 스크립트가 삽입되는 것을 확인할 수 있습니다.
HTML 코드만 수정한 것일 뿐 서버를 수정한 게 아니기 때문에 새로고침하면 원상태로 복귀됩니다.
두 번째는 파라미터 값을 수정하는 방법입니다.
위 사진과 같이 각 필드에 아무 값이나 채워준 후에 Sign Guestbook을 눌러줍니다. 그 파라미터 값을 아래와 같이 수정해주는 방법으로 삽입해줄 수 있습니다.
먼저 언급한 방법으로 삽입하였을 경우 위의 사진과 같이 스크립트가 실행되는 것을 확인할 수 있습니다.