php, XSS 공격 방어 (feat. htmlspecialchars와 strip_tags 함수)

포스트 썸네일 이미지

웹사이트의 방문자가 게시판에 글을 작성하면서 글 내용에 자바스크립트 코드를 심어 사이트를 공격해 오는 경우가 있다.

이런 것을 XSS라고 하는데, 이번 포스트에서는 이 공격을 무력화시키는 법을 공부해 보겠다.




이전 포스트




생활코딩의 php 수업 영상: 보안 XSS





XSS (Cross-Site Scripting)란?


XSS는 게시판이나 댓글창처럼 사용자가 글을 남길 수 있는 곳에 악의적인 스크립트(주로 JavaScript)를 삽입하는 공격 방식이다.

생활코딩 수업 영상에서는 귀여운 예를 보여줬지만, 사용자의 쿠키(세션 ID)를 탈취하여 로그인을 가로채거나, 가짜 로그인 페이지로 리다이렉트 시키는 등 심각한 피해를 줄 수 있다.





htmlspecialchars()


htmlspecialchars() 함수는 HTML에서 특수한 의미를 가진 문자들을 브라우저가 코드로 해석하지 못하도록 단순 문자로 변환하는 역할을 한다.

이를 이스케이프Escape라고 부른다.

그렇게 문자열 안의 특수문자들(코드를 쓸 때 사용하는 <, >, &, " 등)을 그냥 보이는 그대로 출력해서 XSS 공격을 무력화시켜 준다.




strip_tags()


위의 생활코딩 수업 영상의 9분 28초에 이고잉 님께서 언급하는 내장 함수다.

모든 태그를 문자로 바꿔버리는 htmlspecialchars()와 달리, 특정 태그(예: <a>, <b> 등)만 허용하고 나머지는 모두 제거하고 싶을 때는 strip_tags() 함수를 사용한다.




<?php
$input = "<h1>제목</h1>
<p>본문입니다.</p>
<script>alert('공격');</script>
<a href='#'>링크</a>";

// 1. 모든 태그 제거
echo strip_tags($input);

// 2. 특정 태그(<a>, <h1>)만 허용
echo strip_tags($input, '<a><h1>');
?>

strip_tags() 함수는 문자열에서 HTML 태그를 모두 제거한다.

htmlspecialchars()는 태그를 문자로 변환해서 보여줬지만, strip_tags()는 태그를 아예 삭제해버린다.

이때 두 번째 인자를 사용하면 제외할(허용할) 태그를 지정할 수 있다.





strip_tags()는 안전할까?


영상 속에서 언급하는 함수라서 어쩔 수 없이 정리는 했지만, 사실 시간낭비 같아서 정리하고 싶지 않았다. 🙄

strip_tags()보안상 치명적인 약점이 있다.

바로 태그 안의 속성은 건드리지 않는다는 점이다.


만약 <a> 태그를 허용했다면, 공격자는 다음과 같은 코드를 쓸 수 있다.


<a href="#" onclick="악성코드">클릭하세요</a>


strip_tags()<a> 태그 자체는 허용된 것이므로 통과시키지만, 그 안의 onclick 같은 HTML 요소를 클릭했을 때 실행될 자바스크립트 코드를 담는 이벤트 속성까지 걸러내지는 못한다.

onclick 속성은 버튼뿐만 아니라 이미지, 글자 등 거의 모든 태그에 붙여서 동작을 만들 수 있다.




즉, 글쓰기 시 일부 태그(진하게, 밑줄 등)를 허용하고 싶어도 strip_tags()는 좋은 방법이 아니다.

실제 상용 서비스에서 글을 쓸 때 일부 태그를 허용하고 싶다면, php 내장 함수보다는 HTML Purifier 같은 전문 라이브러리를 사용하는 것이 좋다.




다음 포스트

이 글이 도움이 됐거나 유익했다면 스크롤을 조금만 더 내려서 댓글을 남겨주세요. (비로그인도 가능합니다!)
응원이나 피드백이 담긴 댓글은 제가 계속 블로그를 해나갈 수 있는 원동력이 됩니다. 😊

지인에게 보여주고 싶은 글이었다면 URL을 복사해서 메신저나 소셜 미디어에 공유해 주세요.

댓글 쓰기

0 Comments

문의하기 양식