2024. 3. 31. 18:52ㆍit/보안
# XSS 란?
- Cross Site Scripting, 즉 사이트 간 스트립팅이라는 이름의 웹 취약점입니다.
- 웨 사이트의 어드민(관리자)이 아닌 악의적인 목적을 가진 제 3자가 악성 스크립트를 삽입하여 의도하기 않은 명령을 실행시키거나 세션 등을 탈취할 수 있는 취약점입니다.
- 대부분 javascript를 이용한 공격이 이루어집니다.
- SQL Injection과 함께 웹 취약점 중 가장 기초적인 취약점입니다.
- 공격패턴이 다양하고 변화가 많이 이루어지기 때문에 사실상 완벽한 방어가 힘들고 짐금까지도 굉장히 위험한 취약점 중 하나입니다. 마치 인류의 영원한 적이라고 평가받는 감기 바이러스 처럼.
## 위험성
- 쿠키 및 세션정보 탈취
- 악성 프로그램 다운 유도
- 의도하지 않은 페이지 노출
## 공격 종류
### Reflected XSS (반사형 XSS)
- 공격자가 악성 스크립트를 클라이언트에게 직접 전달하여 공격하는 방식입니다.
- 특히 URL에 스크립트를 포함시켜 공격하는 경우가 대표적이며 URL이 길면 클라이언트가 의구심을 가질 수 있기 때문에 Shorten URL(URL 단축)을 이용해 짧은 URL로 만들어 공격하기도 합니다.
- 서버에 스크립트를 저장하지 않기 때문에 서버에서 이루어지는 필터링을 피할 수 있는 공격 방식입니다.
### Stored XSS (영구적 XSS)
- 공격자가 악성 스크립트를 서버에 저장시킨 다음 클라이언트의 요청/응답 과정을 통해 공격하는 방식입니다.
- 여기서 스크립트를 서버에 저장하는 행위는 게시글 쓰기 등의 행동을 지칭합니다.
- 보통 서버에서 필터링을 하기 때문에 공격을 우회하기 어렵지만 한 번 성공하면 관리자 입장에서는 눈치채기 힘들고 광범위한 피해를 줄 수 있다는 것이 특징입니다.
### DOM Based XSS (DOM 기반 XSS)
- 피해자의 브라우저가 html 페이지를 분석하여 DOM을 생성할 때 악성 스크립트가 DOM의 일부로 구성되어 생성되는 공격입니다.
- 서버의 응답 내에는 악성 스크립트가 포함되지 않지만 브라우저의 응답 페이지에 정상적인 스크립트가 실행되면서 악성 스크립트가 추가되서 실행되는 특징이 있습니다.
## 보안 대책
XSS 취약점은 공격자가 삽입한 악성스크립트로 인해 발생하기 때문에 입력값 검증을 통해 악성스크립트가 삽입되는 것을 방지해야 하며, 악성스크립트가 입력되어도 동작하지 않도록 출력값을 무효화해야 합니다.
입력값 필터링의 경우 데이터베이스에 악성스크립트가 저장되는 것을 원천적으로 차단해야 한다. 또한 악성스크립트가 삽입되어도 동작하지 않도록 출력값을 검증하여 스크립트에 사용되는 특수문자를 HTML Entity로 치환하여 응답하도록 합니다.
기본적인 대응 방법
- 입력 값의 길이 제한(이메일, 아이디, 패스워드 등 목적에 맞게)
- replace 등의 함수를 이용한 치환
- '<', '>' 와 같이 태그에 사용되는 기호를 엔티티코드로 변환
- 입력 값에 대한 꼼꼼한 유효성 검사(반드시 서버에서 수행)
- 불가피하게 HTML 태그 사용을 허용해야 할 경우 화이트리스트를 만들어 특정 태그 입력만 허용
예를 들어 아래와 같이 <, >, ', " 등 스크립트에 쓰이는 문자가 입력될 경우 스크립트로 동작하여 XSS 공격이 가능할 수 있으므로 의미가 없는 일반 문자로 치환해야 합니다.
문자 : < > ' " ( )
Entity : < > ' " ( )
치환 함수인 replace()를 사용하여 외부 입력값으로 받은 스크립트에 쓰이는 문자열을 필터링하여 공격자가 입력한 악성스크립트가 동작하지 않도록 한다. (서버 쪽의 java의 경우 replaceAll()을 사용)
let searchWord = request.getParameter("searchWord");
if (searchWord !== null) {
searchWord = searchWord.replace(/</g, "<");
searchWord = searchWord.replace(/>/g, ">");
searchWord = searchWord.replace(/\(/g, "(");
searchWord = searchWord.replace(/\)/g, ")");
searchWord = searchWord.replace(/&/g, "&");
searchWord = searchWord.replace(/"/g, """)
searchWord = searchWord.replace(/'/g, "'");
}
XSS 취약점 대비는 프론트엔드와 백엔드에서 모두 필요합니다.
- 프론트엔드
- 사용자 입력을 적절히 이스케이프하고 필터링하여 안전한 형태로 표시합니다. 이는 주로 사용자가 입력한 데이터를 화면에 출력하는 곳에서 이루어집니다.
- 브라우저에서 실행되는 JavaScript 코드에서 적절한 보안 정책(CSP 등)을 구현하여 XSS 공격을 방지합니다.
- 백엔드
- 사용자 입력을 받아들일 때, 적절한 입력 검증과 필터링을 수행하여 악의적인 스크립트가 백엔드로 전달되는 것을 방지합니다. 이는 보통 HTTP 요청을 받는 엔드포인트에서 이루어집니다.
- 데이터베이스에 저장할 때도 사용자 입력을 안전하게 다루어야 합니다. SQL Injection과 관련된 취약점도 여기에 해당합니다.
- 쿠키와 세션 관리 시에도 안전한 설정을 적용하여 XSS 공격을 방어합니다.
프론트엔드에서는 사용자 입력을 이스케이프하고 적절한 보안 정책을 구현하여 브라우저에서의 공격을 방지하고, 백엔드에서는 입력 검증 및 필터링을 통해 서버 측에서의 공격을 방어합니다.
## 참고
https://tibetsandfox.tistory.com/5
https://nordvpn.com/ko/blog/xss-attack/
https://www.fis.kr/ko/major_biz/cyber_safety_oper/attack_info/security_news?articleSeq=3408