잔디🌿 2025. 4. 28. 20:35

XSS는 공격자가 자신의 코드를 피해자의 브라우저에 주입한다.

이 코드는 대상 웹사이트에서 온다.

웹사이트에서 온 코드는 믿을만하다고 여겨져 페이지를 바꾸고, 쿠키를 읽고, 요청을 보내는 것이 가능해진다.

csrf - 서버를 공격

xss - 브라우저를 공격

Non-persistent XSS Attack

웹사이트는 유저의 input이 그대로 웹사이트에 반영되어 실행되는 공격이다.

이런 취약한 사이트가 있다

그럼 공격자는 피해자에게

이 링크를 클릭하게 한다. 피해자가 이 링크를 클릭하면 get요청이 웹 서버에 전달되고, 이 값이 반영된 페이지를 내놓게 된다. 그러면 이 자바스크립트가 피해자의 브라우저에 뜨게 된다.

Persistent(Stored) XSS Attack

이는 공격자가 직접 서버를 공격하여 persistent storage에 악성 스크립트를 저장한다.

데이터를 전달하는 창(예를들어 프로필)에 데이터를 띄워야하는데 이 데이터에 HTML코드나 javaScript 코드가 들어갈 수 있다.

하지만 이 값들이 필터링되지 않는다면 브라우저에서 실행된다.

브라우저는 이를 정상코드라고 판단하여 동등한 권한으로 실행한다.

이런식으로 사용자의 입력이 코드에 바로 반영될수도 있다.

XSS로 얻을 수 있는 손상

웹 훼손 - DOM 노드를 건들 수 있기 때문에 아예 페이지를 바꿀수도 있다.(기사 제목 바꾸기..)

spoofing request - 사용자 대신 서버에 요청을 할수도 있다.

stealing information - 사용자의 개인정보를 훔칠수도 있다.(쿠키나 개인정보 등)

XSS 공격해보기

우리는 자바스크립트 코드를 주입할 수 있는 곳을 알아보아야한다.

자기를 다른 사람에게 친구추가하는 공격 해보기

1번을 통해 자신의 아이디를 찾고

2번을 통해 csrf 토큰을 발견한다

3번을 통해 쿠키를 볼 수 있다. 공격자의 코드는 공격자의 웹사이트 내부에 삽입되니까 쿠키에 접근할 수 있고, 그러다보니 브라우저가 정상 코드로 여기고 쿠키를 보낼 수 있다.

여기서는 csrf 방어 토큰 우회가 가능하다

왜냐하면 이 코드는 페이지 내에 주입되어있기 때문에 페이지 내부에 있는 자바스크립트 요소들에 직접 접근이 가능하기 때문이다.

이런식으로 1,2번 코드로 토큰을 가져오고, 3,4번 코드로 코드 내부에 반영하면 된다.

공격자는 이렇게 자신의 프로필에 코드를 심어둔다.

피해자가 해당 프로필을 클릭하면 피해자의 계정에 공격자가 친구추가된다.

다른사람의 프로필 변경하기

공격자는 자신이 프로필 변경해보고 http 캡쳐를 통해 구조를 알아봄

이 때 마지막에 userid가 들어가는데 이는 피해자의 브라우저 내부에서

elgg.session.user.id로 가져올 수 있다.

그럼 이런식으로 코드를 심어둘 수 있다.

이 때 samy 본인은 공격을 피하기 위해서

userid가 47이 아닐때만 공격 스크립트가 작동하도록 한다.

Self-Propagation XSS Worm

가해자의 웸을 사용하면 피해자들의 프로필이 가해자의 자바스크립트 코드까지 복사해간다.

그래서 피해가 전염된다.

Document Object Model(DOM) Approach

DOM은 페이지를 트리객체로 구성

돔 api를 사용하면 우리는 각 객체에 접근 가능하다

만약 페이지가 자바스크립트 코드를 포함하면 이는 트리 객체로 구성된다.

그래서 dom api는 자바스크립트 코드를 가져올 수 있따.

각 노드는 이름이 있고, document.getElementByID() api를 통해 노드를 찾을 수 있다.

이렇게 스크립트가 자기 자신을 읽고 다른 코드에 반영할 수 있다

여기서는 worm dom을 가져와서 피해자의 프로필 내부에 붙이고자 한다.

1,2번에서는 코드를 가져오고, 3번에서는 이를 url로 만든다. 그 다음 4번에서는 이를 공개로 설정한다.

이렇게 하면 다른 피해자가 피해자의 프로필에 접속하면 피해를 받게 된다.

The Link Approach

여기서는 공격코드를 외부에서 불러온다.

그래서 우리는 여기서는 프로필에 worm코드를 넣을 필요가 없다.

브라우저는 <script>태그가 있는 부분을 자동실행한다.

대응방법

필터링

user input으로 받은 코드를 제거

<script> 태그로 대응하긴 힘들다 → 이 태그 말고도 다른 태그들이 많아서

자바스크립트 코드를 필터링하는 오픈소스 라이브러리를 사용한다.

인코딩

html 마크업 부분을 다른 문자로 치환한다.

이렇게하면 브라우저가 이를 실행하지 않는다.

php module HTMLawed : 악성코드 필터링해줌

php function htmlspecialchars : 코드가 오직 문자열로만 실행되게 한다.

Content Security Policy(CSP)

근본적인 문제는 데이터 표시하는 곳에 코드가 섞인다는 것이다.

그래서 이를 방지하기 위해 스크립트가 내부에 삽입되는 것을 허용하지 않고, 오직 외부링크로만 허용하도록 한다.

그리고 위와 같이 허용된 곳에서만 script를 가져올 수 있게 한다.

또한 nonce라는 랜덤값을 사용해서 허용된 스크립트만 코드를 실행할 수 있도록 한다.

default-src 'self'
기본 리소스는 오직 현재 서버에서만 불러오도록 제한
script-src 'self' 'nonce-1rA2345' www.example.com
스크립트는 현재 서버, nonce가 일치하는 인라인 스크립트, www.example.com에서만 허용

CSP 우회

허용된 출처를 악용한다.

JSONP : <script>태그를 이용해 외부 서버에서 데이터를 가져오는 방식

이러한 코드가 있다고 했을 때 도메인 상에서는 허용된 http://api.example.com을 사용한다.

JSONP 서버는 이 callback 파라미터에 들어 있는 값으로 자바스크립트 함수 호출 형태로 응답

웹페이지는 개발하면 모두 사용가능하다는 장점이 있지만 공격 위험이 크다.

이 코드에서 noscript는 구조를 깨서 실행을 못하게하는데, dom에 삽입되면 사라지면서 작동 →해킹

또한 xss우회 코드가 주석처리 될 가능성도 있다.