
첫 번째 문제를 번역기로 해석해 보니
XSS란 무엇인가요?
크로스 사이트 스크립팅(XSS라고도 함)은 HTML/스크립트 태그의 허용을 입력으로 결합하여 인코딩이나 삭제 없이 브라우저로 렌더링하는 취약점/결함입니다.
크로스 사이트 스크립팅(XSS)은 가장 널리 퍼져 있고 악성 웹 애플리케이션 보안 문제입니다
이 공격에 대한 간단한 잘 알려진 방어 방법이 있지만 웹에는 여전히 많은 사례가 있습니다. 수정 사항에 대한 커버리지도 수정 측면에서 문제가 되는 경향이 있습니다. 이 방어에 대해서는 잠시 후에 자세히 설명하겠습니다.
XSS는 상당한 영향을 미칩니다
특히 '풍부한 인터넷 애플리케이션'이 점점 더 흔해짐에 따라 JavaScript를 통해 연결된 권한 있는 함수 호출이 손상될 수 있습니다. 그리고 적절하게 보호되지 않으면 민감한 데이터(예: 인증 쿠키)를 도용하여 다른 사람의 목적을 위해 사용할 수 있습니다.
간단한 예:
alert("XSS Test");
alert(document.cookie);
<script>alert("XSS Test")</script>
요약
1. XSS는 "검증되지 않은 외부 스크립트가 내 브라우저에서 실행되어 내 정보를 훔쳐 가는 공격"이라고 이해하시면 됩니다.

문제를 확인해 보니
동일한 페이지를 새 탭에서 열어서 개발자도구를 이용하여 기존의 페이지와 동일한 세션 정보(쿠키값)를 가졌는지에 대한 문제입니다.


먼저 문제에서 제시했던 대로 기존의 페이지 URL을 복사해서 새 탭에서 붙여넣기를 해줍니다.


첫 번째 페이지와 두 번째 페이지의 세션 값이 같은 걸 확인할 수 있습니다.

두 개의 페이지 모두 쿠키값을 확인했다면 체크박스를 눌러서 제출해 주면, 이번 문제는 간단하게 해결할 수 있습니다.

두 번째 문제를 번역기로 해석해 보니
시도해 보세요! 반영된 XSS
과제의 목표는 어떤 분야가 XSS에 취약한지 식별하는 것입니다.
서버 측의 모든 입력을 검증하는 것은 항상 좋은 방법입니다. 검증되지 않은 사용자 입력이 HTTP 응답에 사용될 때 XSS가 발생할 수 있습니다. 반영된 XSS 공격에서는 공격자가 공격 스크립트로 URL을 만들어 다른 웹사이트에 게시하거나 이메일을 보내거나 피해자가 이를 클릭하도록 할 수 있습니다.
필드가 XSS 공격에 취약한지 쉽게 알 수 있는 방법은 alert() 또는 console.log() 메서드를 사용하는 것입니다. 그 중 하나를 사용하여 어떤 필드가 취약한지 알아보세요.
요약
1. 사용자 입력을 서버에서 검증하는 것이 가장 좋은 방법이다.
2. 해커가 공격 스크립트로 URL을 만들어 웹사이트에 게시하거나, 이메일을 보내 피해자가 클릭하게 유도한다.
3. alert(), console.log() 메서드를 이용하여 어떤 필드가 취약한지 알아내라

위와 같이 구매 버튼을 눌렀을 때 메시지에는 쇼핑해 줘서 고맙고 해당 신용카드를 청구했다고 합니다.


먼저 요청을 보냈을 때 어떤 응답이 오는지 확인을 해봅시다. 응답을 확인해 보니 본문에 사용자의 신용카드 입력 값이 그대로 응답 본문에 포함되어서 보내지는 걸 알 수 있습니다. 그렇다면 우리는 응답 본문을 근거로 공격을 시도해 볼 수 있을 거 같습니다.

신용카드 필드에 우리는 다음과 같은 코드를 작성해 볼 겁니다.
<script>alert('XSS Attack Success')</script>


스크립트를 입력해서 요청하면 문제가 해결된걸 볼 수 있습니다. 이렇게 해서 신용카드 입력 필드에 검증이 제대로 이루어지지 않아 XSS 공격에 취약하다는 걸 알게 되었습니다.

세 번째 문제를 번역기로 해석해 보니
DOM 기반 XSS의 잠재력 식별
DOM 기반 XSS는 일반적으로 클라이언트 측 코드에서 경로 구성을 검색하여 찾을 수 있습니다. 페이지에 "반사"된 입력을 가져오는 경로를 찾습니다.
이 예제에서는 경로 핸들러에서 '테스트' 코드를 찾아야 할 것입니다(WebGoat은 백본을 기본 JavaScript 라이브러리로 사용합니다). 때때로 테스트 코드가 생산되지 않을 때가 있습니다(그리고 종종 테스트 코드는 간단하고 보안이나 품질 관리가 부족합니다!).
당신의 목표는 경로를 찾아서 이를 악용하는 것입니다. 먼저, 기본 경로는 무엇인가요? 예를 들어, 이 강의의 URL을 보세요 ...이 강의는 /WebGoat/start.mvc#lesson/CrossSiteScripting.lesson/9와 같아야 합니다. 이 경우의 '기본 경로'는 다음과 같습니다: start.mvc#lesson/The CrossSiteScripting.lesson/9 이후는 JavaScript 경로 핸들러에 의해 처리되는 매개변수입니다.
그렇다면 제작 중에 앱에 남아 있던 테스트 코드의 경로는 무엇인가요? 이 질문에 답하려면 JavaScript 소스를 확인해야 합니다.
요약
1. DOM 기반 XSS는 주로 클라이언트 측 코드(JavaScript)의 라우트(Route) 설정에서 발견됩니다. 페이지에 입력값이 "반사(Reflected)"되어 나타나게 만드는 라우트가 있는지 확인해야 합니다.
2. 실제 운영 환경에 실수로 남겨진 '테스트용 코드' 찾기
3. WebGoat는 Backbone.js를 주요 자바스크립트 라이브러리로 사용하고 있으므로, 이 라이브러리의 라우팅 방식을 살펴보아야 합니다.
4. 기본경로 및 파라미터
base route : start.mvc#lesson/
parameters : CrossSiteScripting.lesson/9

문제에서 제시한 곳을 개발자 도구를 이용해서 한번 찾아보았습니다. 확인해 보니 GoatRouter.js파일이 있고 Backbone.js라는 자바스크립트 라이브러리에서 사용하는 '라우팅(Routing) 설정' 부분을 찾을 수 있었습니다. 웹사이트 주소창에 특정 경로가 입력되었을 때, 자바스크립트가 "아, 이 주소가 들어오면 이 함수를 실행해야지!"라고 결정하는 규칙들입니다.

이 코드는 주소 패턴 : 실행할 함수 이름 쌍으로 이루어져 있습니다.
| 주소 패턴 (URL) | 실행될 함수 (Handler) | 의미 |
|---|---|---|
| 'welcome' | welcomeRoute | #welcome 접속 시 환영 페이지 호출 |
| 'lesson/:name' | lessonRoute | #lesson/수업이름 접속 시 해당 수업 호출 |
| 'lesson/:name/:pageNum' | lessonPageRoute | #lesson/수업이름/페이지번호 접속 시 특정 페이지 호출 |
| 'test/:param' | testRoute | #test/아무값 접속 시 테스트 함수 호출 |
| 'reportCard' | reportCard | #reportCard 접속 시 성적표 페이지 호출 |
여기서 : (콜론)의 의미
: 뒤에 붙는 이름(name, pageNum, param)은 변수라는 뜻입니다.

왜 'test/:param'이 위험할까?
우리가 앞에서 이야기한 DOM 기반 XSS의 핵심 단서가 바로 이 녀석입니다.
개발자가 테스트용으로 만든 이 경로는 #test/ 뒤에 오는 값을 그대로 화면에 출력하거나 처리할 가능성이 매우 높습니다.
만약 testRoute 함수가 param으로 들어온 값을 아무런 검사 없이 브라우저 화면(DOM)에 집어넣는다면, 공격자가 주소창에 자바스크립트를 넣는 순간 실행되어 버립니다.
아마 이게 문제에서 말했던 test route일 거 같습니다. 그렇다면 test route를 알았으니, 문제로 돌아가 보겠습니다.

이렇게 자바스크립트에 있는 test route를 찾아서 문제를 해결하였습니다.

네 번째 문제를 번역기로 해석해 보니
해보세요! DOM 기반 XSS
일부 공격은 "블라인드"입니다. 다행히도 서버가 실행 중이므로 성공 여부를 알 수 있습니다. 방금 찾은 경로를 사용하여 인코딩 없이 경로의 매개변수를 반영하여 WebGat에서 내부 기능을 실행할 수 있는지 확인하세요. 실행하려는 기능은 다음과 같습니다:
webgoat.customjs.phoneHome()
물론 콘솔/디버그를 사용하여 트리거할 수도 있지만, 새 탭의 URL을 통해 트리거해야 합니다.
트리거하면 브라우저 콘솔에 무작위 번호와 함께 후속 응답이 표시됩니다. 아래에 무작위 번호를 입력하세요.
요약
1. 방금 찾은 test/:param 라우트를 이용하여, 특정한 함수를 실행 -> webgoat.customjs.phoneHome()
2. 개발자도구 말고 URL에 직접 입력해야 한다.
3. 공격이 성공하면 콘솔 창에 무작위 값이 출력되니 그 값을 알아내서 문제를 해결해라

먼저 testRoute함수가 어떻게 동작하는지부터 확인해 보겠습니다.

testRoute 메서드는 param을 매개변수로 받아 lessonController의 testHandler 함수를 다시 호출하고 있습니다. 이번에는 testHandler 메서드를 확인해 봅시다.

testHandler 메서드는 param을 매개변수로 받고 lessonContentView에 showTestParam 메서드를 호출합니다. 이번에는 showTestParam 메서드를 확인해 봅시다.

showTestParam 메서드는 param을 매개변수로 받고 .lesson-content 클래스에 해당하는 요소에 innerHTML 형태로 'test'라는 단어와 함께 추가되어 사용되고 있습니다.

드디어 공격을 시도해 볼 수 있겠습니다. 주소창에 test route를 이용하여 start.mvc#test/123 라는 값을 넣어보겠습니다.

공격 결과가 화면에 나타난걸 볼 수 있습니다. 이번에는 script를 사용하여 공격을 시도해 보겠습니다.


script를 이용한 공격도 화면에 성공적으로 나온 걸 확인할 수 있습니다.
이제 webgoat.customjs.phoneHome()함수를 실행해서 결과를 확인해 보겠습니다.

<script>console.log(webgoat.customjs.phoneHome())<%2Fscript>
위와 같이 주소창에 스크립트를 작성합니다.

하단에 phoneHome Response is 무작위 값이 나옵니다. 해당 무작위 값을 복사하시면 됩니다.

복사한 값을 넣으면 이번 문제를 해결할 수 있습니다.
이번 실습에서는 Cross Site Scripting(이하 XSS or 크사)을 공부해 봤습니다. 저번에 배웠던 SQL Injection이나 Path Traversal 공격 같은 경우에도 프런트엔드 쪽이든 백엔드(서버) 쪽이든 사용자 입력값에 대해 검증을 하지 않았을 때 생기는 문제점들이 아주 많았습니다. 그만큼 프런트엔드도 마찬가지지만 특히 백엔드에서는 더욱 신경을 써야 합니다. 왜냐하면 서버까지 데이터가 넘어오면 DB에도 접근할 수 있게 될 수도 있으므로 특히 신경을 써야 합니다. XSS는 생각보다 자주 발견되는 취약점입니다. 오히려 SQL Injection 같은 경우가 더 공격하기 쉽지 않을 수도 있습니다. SQL인젝션의 경우 DB 때문에 상당히 민감하므로 보안에 신경을 많이 쓰는 반면 사용자 입력값에 대한 검증은 안일하게 넘어가는 경우도 종종 있기에 은근히 발견이 자주 되는 취약점입니다.