티스토리 뷰

XSS 유형
- Reflected
- DOM-based
- Stored or Persistent
- Universal
Reflected XSS
Reflected XSS는 웹 어플리케이션의 지정된 파라미터를 사용할 때 발생하는 취약점을 이용한 공격이다. 검색 결과, 에러 메세지 등 서버가 외부에서 입력을 받아 브라우저에 응답할 때, 파라미터에 삽입된 악성 스크립트를 사용자에게 그대로 전달하면서 발생한다.
- 공격자는 파라미터에 악성 스크립트가 포함된 URL을 피해자에게 전달한다(링크, 악성 메일 등).
- 피해자가 악성 웹 페이지를 로드하는 링크를 클릭해 서버에 요청한다.
- 웹 서버의 응답 페이지에 악성 스크립트 포함되고, 이는 피해자의 브라우저에서 실행된다.
- 스크립트가 Session ID와 같은 민감한 정보를 훔쳐서 공격자에게 전송한다.
DOM-based XSS
DOM을 통해 HTML, XML 등의 정적 문서의 요소에 동적으로 접근하고 업데이트 할 수 있다. DOM에 포함된 스크립트는 브라우저에서 렌더링 할 때 실행되고, DOM 문서 내의 객체에 접근할 수 있다. 값을 읽거나 쓸 수 있으므로 웹 페이지의 컨텐츠를 동적으로 변화시킬 수 있다.
- 공격자는 파라미터에 악성 스크립트를 포함시킨 URL을 작성하여 피해자에게 전달한다(링크, 악성 메일 등).
- 피해자의 브라우저는 렌더링 중 HTML을 페이지에 추가하기 위해 `innerHTML`등의 사용자 입력을 구문 분석해 페이지를 동적으로 생성한다.
즉, 서버의 응답 내에는 악성 스크립트가 없으나 브라우저에서 스크립트가 실행되며 악성 스크립트가 추가된다. 특히 이를 예방하기 위해 웹 방화벽에 의존하거나 서버 측 코드에서 필터링하는 경우 URL의 맨 끝에 `#`(Fragment)를 두고 악성 스크립트를 위치시키면 브라우저에서 `#` 문자 뒤의 내용을 서버에 전달하지 않기 때문에 보이지 않게 우회할 수 있다.
Stored XSS or Persistent XSS
Stored XSS는 웹 어플리케이션 취약점이 있는 웹 서버에 악성 스크립트를 영속적으로 저장하는 방식이다. 따라서 악성 스크립트가 웹 서버 데이터베이스로부터 온다.
- 공격자가 웹 사이트의 입력 form을 통해 POST로 악성 스크립트를 전달하면 서버는 해당 내용을 DB에 저장한다.
- 피해자가 해당 페이지를 요청한다.
- 서버는 저장된 악성 스크립트를 포함한 응답(페이지)을 전송한다.
- 피해자의 브라우저에서 스크립트가 실행되어 XSS 공격이 수행된다.
Universal XSS
Universal XSS는 클라이언트 측 취약점으로 경우에 따라 SOP 정책의 제약을 우회할 수 있다. 브라우저 자체의 취약점이나 확장 기능, 플러그인의 취약점을 이용한다.
10

`GoatRouter.js` 파일을 보면 아래와 같은 내용을 찾을 수 있다.

`'test/:param': 'testRoute'` 부분을 확인할 수 있다. 현재 페이지의 URL은 `/WebGoat/start.mvc#lesson/CrossSiteScripting.lesson/9`이다. 따라서 테스트 페이지의 URL은 `start.mvc#test`가 된다.
11

이전 문제에서 찾아낸 경로를 이용해 루트에서 매개변수를 반영하고 인코딩 없이 WebGoat의 내부 함수를 이용할 수 있는지 확인해야 한다.
`#test/:param` 형태의 URL을 요청하면 다음 코드가 실행된다.
testRoute: function (param) {
this.lessonController.testHandler(param);
//this.menuController.updateMenu(name);
}
내부적으로 `lessonController.testHandler()`를 호출한다. 이 함수는 아래와 같다.
this.testHandler = function(param) {
console.log('test handler');
this.lessonContentView.showTestParam(param);
};
다시 `lessonContentView.showTestParam()` 함수를 호출한다. 이 함수는 아래와 같다.
/* for testing */
showTestParam: function (param) {
this.$el.find('.lesson-content').html('test:' + param);
}
JQuery를 사용해 `$el` 요소에서 클래스 이름이 `.lesson-content`요소를 찾고 여기에 `.html()`을 이용해 타겟 요소의 내용을 제거하고 `param`을 저장한다. `el`은 상단에 정의되어 있다. (`el: '#lesson-content-wrapper'`)

따라서 `#test/:param` URL 접속 시 `.html()`로 인해 DOM 요소의 내용이 `param` 값으로 수정된다. 실행하려는 함수는 `webgoat.customjs.phoneHome()`이고 이 함수는 전역에서 실행되므로 `param`에 스크립트를 포함시키면 실행된다.
`#test/code` URL 요청 시 아래와 같이 해당 DOM 요소 내에 텍스트가 변경된 것을 확인할 수 있다.

바로 스크립트를 넣으면 브라우저는 동적으로 삽입된 스크립트를 실행하지 않으므로 동작하지 않는다. 따라서 이미지 태그를 넣고, `onerror` 이벤트 핸들러를 추가해 이미지 로드에 실패했을 때 스크립트를 실행하도록 한다.
<img src="nowhere" onerror="webgoat.customjs.phoneHme()">
'Wargame > WebGoat' 카테고리의 다른 글
| Server-Side Request Forgery (0) | 2024.05.23 |
|---|---|
| Cross-Site Request Forgery (0) | 2024.05.23 |
| Injection: SQL Injection (intro) (0) | 2024.05.16 |
- Total
- Today
- Yesterday
- Bandit
- 회고
- SEO
- math
- Database
- Spring Security
- Dreamhack
- PS
- CSRF
- askers
- sqli
- java
- React
- Transaction
- oauth2
- opengraph
- XSS
- WEB
- DP
- sql injection
- Spring
- Misc
- Framework
- webgoat
- JPA
- test
- linux
- WarGame
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | |
| 7 | 8 | 9 | 10 | 11 | 12 | 13 |
| 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| 21 | 22 | 23 | 24 | 25 | 26 | 27 |
| 28 | 29 | 30 |