기존 HTML escape 메서드 대체의 필요성을 느끼다
로그인하려 사용자가 입력한 ID를 전달 받은 서버에서 XSS 방어를 처리하려는 목적으로 사용한
StringEscapeUtils의 escapeHtml 메서드를 보고 문득 의문이 들었다.
StringEscapeUtils는 우리 프로젝트에서 총 3개의 버전이 있는데 아래와 같다.
- lang.StringEscapeUtils
- lang3.StringEscapeUtils
- text.StringEscapeUtils
이 3개 중에서 기존에 import 되어있는 StringEscapeUtils 클래스는 lang 라이브러리였다.
그러나 lang 라이브러리 StringEscapeUtils 클래스의 escapeHtml은 <script> 같은 특수기호가 있는 XSS 공격은 방어가 가능하지만 ';alert(1);' 같은 스크립트로 우회하여 공격할 때에는 우회한 문자열이 HTML 엔티티로 인코딩되지 않는 문제점이 있다.
이를 개선한 것이 lang3 라이브러리의 StringEscapeUtils 클래스이다.
그러나 lang3 안에 들어가 있는 기능들이 너무 많아지다 보니, 아파치 재단에서 '문자열 계산이나 제어(lang3)'과 '문자열 알고리즘이나 이스케이프(text)'를 분리하였다.
따라서 lang3과 text 라이브러리 모두 StringEscapeUtils 클래스에 우회한 XSS 공격 스크립트를 방어할 수 있으나,
현재 최신 버전은 commons-text 라이브러리에서 이스케이프 기능을 사용할 수 있게 해놓았다고 보면 된다.
보안 강화를 위해 text 라이브러리를 도입하여 escapeHtml4를 이용하여 싱글 쿼테이션까지 완벽히 막고 싶었으나, 라이브러리를 추가하고 STS4 환경에서 project clean까지 진행하였지만 기존 환경에 묶여 있는 lang 2와의 충돌 혹은 로딩 우선순위 문제로 인해 제대로 반영되지 않는 현상이 발생했다.
왜 커스텀 HTML Escape 메서드를 만들게 되었나
지금 상황에서는 수많은 기존 라이브러리들과의 의존성이 얽혀 있고, 이를 강제로 해결하려다 보면 배포 환경 자체가 흔들릴 위험이 있었다.
그렇다고 수정하지 않고 구버전을 그냥 쓰자니 혹시 모를 보안이 걱정되었다.
그래서 환경 설정을 고치느라 시간을 보내기보다, 가장 확실하고 가벼운 해결책을 택하기로 했다.
싱글 쿼테이션으로 우회한 XSS 공격을 방어하기 위해 내부 공통 클래스에 escapeHtml 메서드를 직접 구현하였다.
커스텀 HTML Escape 메서드 구현
아래 escapeHtml 메서드는 공지사항 검색어, 결제페이지 내 요청사항 입력란 등 여러 페이지에서 공통적으로 사용할 계획이 있기 때문에 공통 클래스에 코드를 작성하였다.
public static String escapeHtml(String input) {
if (input == null) return null;
StringBuilder sb = new StringBuilder();
for (char c : input.toCharArray()) {
switch (c) {
case '<': sb.append("<"); break;
case '>': sb.append(">"); break;
case '&': sb.append("&"); break;
case '"': sb.append("""); break;
case '\'': sb.append("'"); break;
case '/': sb.append("/"); break;
default: sb.append(c);
}
}
return sb.toString();
}
해당 메서드를 적용시킨 결과,
';alert(1);' 스크립트가 ';alert(1);'로 변환되어 안전한 문자열로 처리되었다.
항상 적용 된 라이브러리가 안전한가?
내가 작성한 코드에 허점은 없을까?
항상 의심하자.
시간이 지날 수록 공격 수법이 진화함에 따라 보안도 계속 업데이트 되어야 한다는 것을 새삼 깨닫게 되는 날이었다.
'[Project] > 업무일지' 카테고리의 다른 글
| 결제 지연 146초에서 0.003초로 - 인덱스 하나가 바꾼 드라마틱한 성능 개선기 (0) | 2026.03.13 |
|---|---|
| 같은 EC2인데 왜 운영체제(OS)가 다를까? (Amazon Linux vs CentOS) (1) | 2026.03.12 |
| [AWS/CloudWatch/RDS] 가용메모리 및 CPU 사용률 지표 확인 (1) | 2025.10.23 |
| [에러 핸들링] 파라미터 내 처리 불가 데이터 삽입 시 톰캣 기본 에러페이지 내 서버 버전 미노출 처리 (0) | 2025.09.17 |
| [에러 핸들링] 잘못된 메소드 호출에 대한 응답 내 서버 버전 미노출 처리 (0) | 2025.09.17 |