본문 바로가기

비개발자의 개발 일지

현장 팀장에서 수출 ERP까지 — AI와 함께 시스템을 만든 기록

시리즈 보기
php

PHP htmlspecialchars() — XSS 방어 · HTML 특수문자 이스케이프 완전 정리

by 왕진 2026. 7. 10.
반응형

 

 

Web Development · PHP 보안 · 문자열 처리

PHP htmlspecialchars() — HTML 특수문자 이스케이프와 XSS 방어

5가지 변환 규칙 · ENT_QUOTES 옵션 · strip_tags와 차이 완전 정리
시작 오늘 분석할 코드

htmlspecialchars()는 HTML 특수문자(< > & " ')를 HTML 엔티티로 변환하는 함수입니다. 사용자 입력을 화면에 그대로 출력할 때 반드시 거쳐야 하는 XSS(크로스 사이트 스크립팅) 방어의 첫 번째 관문입니다.

<?php $string = '<a href="http://www.namgarambooks.co.kr/">남가람북스</a>'; $result = htmlspecialchars($string, ENT_QUOTES); // <, >, &, ", ' 모두를 HTML 엔티티로 변환 // $string을 그대로 출력해도 태그로 해석되지 않음 print $result; ?>
실제 출력 미리보기
❌ htmlspecialchars 없이 출력
남가람북스
→ 링크가 실제로 렌더링됨
✓ htmlspecialchars 적용 후
&lt;a href=&quot;http://...&quot;&gt;남가람북스&lt;/a&gt;
→ 태그가 텍스트로 그대로 표시됨
용어 용어 정리
htmlspecialchars()특수문자를 HTML 엔티티로 변환. 브라우저가 태그로 해석하지 못하게 막음
XSSCross-Site Scripting. 악의적인 사용자가 <script>를 삽입해 실행시키는 공격
HTML 엔티티&lt; &gt; &amp; &quot; &#039; 등 특수문자를 표현하는 HTML 표기법
ENT_QUOTES큰따옴표(")와 작은따옴표(') 모두 변환. 기본값은 큰따옴표만 변환
이스케이프특수한 의미를 가진 문자를 무해한 형태로 변환하는 처리
htmlspecialchars_decode()htmlspecialchars의 역방향 — 엔티티를 다시 특수문자로 복원
strip_tags()HTML 태그 자체를 제거. htmlspecialchars는 태그를 보존하되 무력화
ENT_HTML5HTML5 문서 타입 기준으로 변환. PHP 5.4+ 에서 사용 가능

1 왜 htmlspecialchars()가 필요한가 — XSS 공격 시나리오
사용자 입력을 그대로 출력하면 어떤 일이 일어나는가?

게시판이나 댓글 폼에 사용자가 악의적인 스크립트를 입력하면, 서버가 그것을 그대로 HTML로 출력했을 때 다른 사용자의 브라우저에서 실행됩니다. 이것이 XSS 공격입니다. htmlspecialchars()는 이를 텍스트로 만들어 실행 자체를 막습니다.

⚠️ 위험 — 이스케이프 없이 출력
$name = $_POST['name'];
echo $name;

입력: <script>alert('해킹!')</script>
→ 실제 alert가 실행됨!
✓ 안전 — htmlspecialchars 적용
$name = $_POST['name'];
echo htmlspecialchars($name, ENT_QUOTES);

→ &lt;script&gt;alert(...)&lt;/script&gt;
텍스트로만 표시, 실행 안 됨
⚠️ 사용자 입력($_ POST, $_GET, $_COOKIE 등)은 반드시 출력 전에 htmlspecialchars()를 거쳐야 합니다. 이것은 선택이 아니라 필수입니다.

2 5가지 변환 규칙 — 어떤 문자가 무엇으로 바뀌는가?
& → & / < → < / > → > / " → " / ' → '

htmlspecialchars()는 HTML에서 특별한 의미를 가진 5가지 문자를 엔티티로 변환합니다. 각각이 왜 위험한지, 어떤 엔티티로 바뀌는지 확인해두면 이스케이프 로직을 이해하기 쉽습니다.

원래 문자 HTML 엔티티 변환 이유
& (앰퍼샌드) &amp; 엔티티 시작 문자 — 다른 엔티티와 충돌 방지
< (꺾쇠 열기) &lt; 태그 시작 — <script> 등의 실행 방지
> (꺾쇠 닫기) &gt; 태그 종료 — 태그 구조 탈출 방지
" (큰따옴표) &quot; 속성값 탈출 방지. ENT_QUOTES나 기본값에서 변환
' (작은따옴표) &#039; 속성값 탈출 방지. ENT_QUOTES 지정 시에만 변환
&는 반드시 가장 먼저 변환되어야 합니다. <를 먼저 변환하면 &lt;&가 다시 변환되어 이중 인코딩이 됩니다.

3 ENT_QUOTES — 왜 작은따옴표까지 변환해야 하는가?
속성값 안에서 작은따옴표로 속성 탈출이 가능하기 때문

HTML 속성값을 작은따옴표로 감싸는 경우가 있습니다(<div class='값'>). 이때 이스케이프 없이 작은따옴표가 들어오면 속성을 조기 종료하고 이벤트 핸들러를 삽입할 수 있습니다. ENT_QUOTES는 큰따옴표와 작은따옴표 모두를 안전하게 처리합니다.

// 기본 동작: 큰따옴표만 변환 htmlspecialchars("He said \"hello\""); // → He said &quot;hello&quot; // ENT_QUOTES: 큰따옴표 + 작은따옴표 모두 변환 htmlspecialchars("It's a \"test\"", ENT_QUOTES); // → It&#039;s a &quot;test&quot; // PHP 5.4+ 기본값이 ENT_HTML401로 바뀜 // 가능하면 명시적으로 ENT_QUOTES | ENT_HTML5 지정 htmlspecialchars($input, ENT_QUOTES | ENT_HTML5, 'UTF-8');
※ 실무에서는 항상 ENT_QUOTES를 지정하는 습관을 들이는 것이 안전합니다. 어떤 맥락에서 출력될지 미리 알기 어렵기 때문입니다.

 

반응형

 

4 htmlspecialchars vs strip_tags — 무엇이 다른가?
이스케이프(무력화)와 제거는 완전히 다른 처리

두 함수 모두 XSS 방어에 쓰이지만 접근 방식이 다릅니다. htmlspecialchars()는 태그를 텍스트로 변환해 보존하고, strip_tags()는 태그를 완전히 제거합니다.

$input = '<b>굵게</b>와 <script>alert(1)</script>'; // htmlspecialchars — 태그를 텍스트로 이스케이프 echo htmlspecialchars($input, ENT_QUOTES); // 화면: <b>굵게</b>와 <script>alert(1)</script> // 전체 원문이 텍스트로 표시됨 // strip_tags — 태그 자체를 완전 제거 echo strip_tags($input); // 화면: 굵게와 alert(1) // <b>, <script> 태그가 모두 사라짐
※ 사용자 입력을 원문 그대로 보여줘야 할 때는 htmlspecialchars, 태그를 완전히 없애고 텍스트만 추출할 때는 strip_tags를 사용합니다.

5 인코딩 지정 — 왜 UTF-8을 명시해야 하는가?
PHP 버전에 따라 기본 인코딩이 다르기 때문

PHP 5.4 이전에는 기본 인코딩이 ISO-8859-1이었습니다. 한글이 포함된 경우 인코딩 불일치로 변환이 깨질 수 있습니다. 세 번째 인수로 'UTF-8'을 명시하면 안전합니다.

// 안전한 완전한 형태 (PHP 5.4+) $safe = htmlspecialchars($input, ENT_QUOTES | ENT_HTML5, 'UTF-8'); // 간단한 형태 (PHP 5.4+에서는 기본 UTF-8) $safe = htmlspecialchars($input, ENT_QUOTES);

6 자주 하는 실수
실수 증상 해결
htmlspecialchars 없이 사용자 입력 출력 XSS 공격 성공 — 악성 스크립트 실행 출력 전 반드시 htmlspecialchars($v, ENT_QUOTES) 적용
ENT_QUOTES 생략 작은따옴표로 속성값 탈출 가능 — HTML 속성에 출력 시 위험 항상 ENT_QUOTES 명시
이중 인코딩 이미 이스케이프된 문자열에 다시 적용해 &amp;lt; 등이 됨 입력 시 1회만 적용, DB 저장 후 출력 시 다시 적용하지 않도록 관리
strip_tags와 혼용 strip_tags로 제거 후 htmlspecialchars 적용 — 중복 처리, 의도 불명확 목적에 맞게 하나만 선택: 원문 표시=htmlspecialchars, 태그제거=strip_tags
DB 저장 전에만 처리 DB에 엔티티로 저장 → 검색 어려워짐 DB는 원문 저장, 출력 시에만 htmlspecialchars 적용

핵심 한 줄 요약

목적사용자 입력이 HTML 태그/스크립트로 실행되지 않도록 텍스트화
5가지 변환& → &amp; / < → &lt; / > → &gt; / " → &quot; / ' → &#039;
ENT_QUOTES큰따옴표 + 작은따옴표 모두 변환 — 항상 지정 권장
strip_tags와 차이htmlspecialchars=태그 텍스트화, strip_tags=태그 완전 제거
적용 시점DB 저장 전 아니라 HTML 출력 직전에 적용

Tags

#PHP #htmlspecialchars #XSS방어 #크로스사이트스크립팅 #HTML특수문자 #ENT_QUOTES #html엔티티 #PHP보안 #PHP함수 #PHP학습 #웹개발 #티스토리
▼ 티스토리 태그 입력란 복사용
PHP, htmlspecialchars, XSS방어, 크로스사이트스크립팅, HTML특수문자, ENT_QUOTES, html엔티티, PHP보안, PHP함수, PHP학습, 웹개발, 티스토리
반응형

댓글