웹 애플리케이션을 개발할 때, 보안은 항상 최우선 과제 중 하나이다. 특히, 크로스 사이트 스크립팅(XSS) 공격은 매우 흔한 보안 취약점 중 하나로, 이를 방지하기 위한 적절한 조치가 필요하다.
Jsoup은 Java 기반의 HTML 파싱 라이브러리로, HTML 문서에서 데이터를 추출하거나 HTML을 조작하는 데 유용하다. 특히, Jsoup의 clean() 메서드는 HTML 문서에서 악성 스크립트나 불필요한 태그를 제거하여 안전한 HTML을 생성하는 데 사용된다. 해당 포스트에서는 Jsoup의 clean() 메서드 사용법과 Spring 기반 환경에서의 활용 예시에 대해 상세히 설명한다.
XSS란 무엇인가?
XSS(Cross-Site Scripting)는 공격자가 악성 스크립트를 웹 페이지에 삽입하여 다른 사용자가 해당 페이지를 방문할 때 스크립트가 실행되도록 하는 공격 기법이다. 이를 통해 공격자는 사용자의 세션을 탈취하거나, 악성 코드를 실행하거나, 민감한 정보를 탈취할 수 있다.
Jsoup clean() 메서드 사용법
clean() 메서드는 HTML 문자열과 허용할 태그 및 속성을 정의하는 Safelist 객체를 인자로 받아, 지정된 규칙에 따라 HTML을 정리(clean)한다. 기본적인 사용법은 다음과 같다.
String safeHtml = Jsoup.clean(unsafeHtml, Safelist.basic());
여기서 unsafeHtml은 정리할 HTML 문자열이고, Safelist.basic()은 기본적으로 허용할 태그와 속성을 정의한 Safelist이다. Jsoup은 여러 가지 기본 Safelist를 제공하며, 필요에 따라 커스터마이징 할 수도 있다.
Safelist.none() | 모든 태그와 속성을 제거한다. |
Safelist.simpleText() | 텍스트와 기본적인 텍스트 포맷팅 태그만 허용한다. |
Safelist.basic() | 기본적인 HTML 태그와 속성을 허용한다. |
Safelist.basicWithImages() | 기본적인 HTML 태그와 속성에 이미지 태그를 추가로 허용한다. |
Safelist.relaxed() | 상대적으로 많은 태그와 속성을 허용한다. |
기본 제공 Safelist 외에도, 필요에 따라 커스터마이징 된 Safelist를 생성할 수 있다. 예를 들어, 특정 태그와 속성만 허용하는 Safelist를 생성하려면 다음과 같이 한다.
Safelist customSafelist = new Safelist()
.addTags("a", "b", "p")
.addAttributes("a", "href")
.addProtocols("a", "href", "http", "https");
String safeHtml = Jsoup.clean(unsafeHtml, customSafelist);
위 예제에서는 a, b, p 태그와 a 태그의 href 속성만 허용하고, href 속성의 값으로는 http와 https 프로토콜만 허용하도록 Safelist를 커스터마이징하였다.
Safelist()
Safelist 클래스는 다양한 메서드를 제공하여 허용할 태그와 속성을 세부적으로 설정할 수 있다.
addTags(String... tags)
- 허용할 태그를 추가한다.
addAttributes(String tag, String... attributes)
- 특정 태그에 대해 허용할 속성을 추가한다.
addEnforcedAttribute(String tag, String attribute, String value)
- 특정 태그에 대해 강제할 속성을 추가한다.
addProtocols(String tag, String attribute, String... protocols)
- 특정 태그와 속성에 대해 허용할 프로토콜을 추가한다.
removeTags(String... tags)
- 허용 목록에서 태그를 제거한다.
removeAttributes(String tag, String... attributes)
- 특정 태그에 대해 허용 목록에서 속성을 제거한다.
Spring 기반 환경에서의 활용 예시
Spring 기반의 웹 애플리케이션에서 Jsoup을 활용하여 사용자 입력을 정리하는 예제를 살펴보자. 예를 들어, 사용자가 입력한 댓글을 저장하기 전에 악성 스크립트를 제거하는 기능을 구현할 수 있다.
컨트롤러 작성
@RestController
public class ShibaController {
@PostMapping("/sanitizeInput")
public String sanitizeInput(@RequestBody String userInput) {
return Jsoup.clean(userInput, Safelist.basic());
}
}
위 예시에서, 사용자가 입력한 데이터를 @RequestBody로 받아 Jsop.clean() 메서드를 사용하여 필터링한 후 반환한다.
공격 시나리오
이제 실제로 XSS 공격을 시도하는 예시를 보겠다. 다음과 같은 HTML 폼이 있다고 가정하자.
<!DOCTYPE html>
<html>
<head>
<title>XSS Test</title>
</head>
<body>
<form action="/sanitizeInput" method="post">
<label for="input">Enter some text:</label>
<input type="text" id="input" name="input">
<button type="submit">Submit</button>
</form>
</body>
</html>
사용자가 입력 필드에 다음과 같은 악성 스크립트를 입력한다고 가정하자.
<script>alert('XSS Attack!');</script>
이 입력이 서버로 전송되면, Jsoup.clean() 메서드가 이를 필터링하여 안전한 형태로 변환한다. 변환된 결과는 다음과 같다.
<script>alert('XSS Attack!');</script>
이제 브라우저에서 이 결과를 렌더링하면, 스크립트가 실행되지 않고 단순한 텍스트로 표시된다.
이와 같이, Jsoup의 clean() 메서드를 사용하여 Spring 기반의 웹 애플리케이션에서 사용자 입력을 안전하게 처리할 수 있다. 이를 통해 XSS 공격을 방지하고, 애플리케이션의 보안을 강화할 수 있다. HTML 태그를 직접 받아야 하는 경우가 생긴다면 반드시 Jsoup clean()을 이용한 필터링 과정을 거쳐서 개발하도록 하자.
REFERENCE
'Spring' 카테고리의 다른 글
Spring Boot 3 + Swagger Codegen 적용하기 (2) | 2024.12.27 |
---|---|
[OAS] Swagger Codegen 필요성 (With. Spring Boot) (1) | 2024.12.26 |
비동기 프로그래밍 @Async와 CompletableFuture (0) | 2024.08.29 |
Controller에서 의존성 주입 대상 필드 값이 NULL이 되는 문제와 해결방안, 이유 (0) | 2024.02.17 |
Spring Data Redis를 활용해서 레디스 기본 명령어 사용하는 방법 (0) | 2024.02.12 |
댓글