PHP에서 XSS(Cross-Site Scripting) 공격을 방지하기 위해 다음 사항을 고려해야 합니다.
1. XSS란?
XSS는 공격자가 악성 스크립트를 웹 페이지에 삽입하여 다른 사용자에게 실행시키는 공격 기법입니다.
공격 시나리오
- 스토어드 XSS: 공격 스크립트를 데이터베이스에 저장하여 여러 사용자에게 실행.
- 리플렉티드 XSS: 공격 스크립트를 요청 URL 등에 포함하여 즉시 실행.
- DOM 기반 XSS: 클라이언트 측에서 DOM 조작을 통해 발생.
2. XSS 방지 원칙
2.1 입력 데이터 검증
- 모든 입력 데이터를 신뢰하지 않는다.
- 필요하지 않은 HTML, 스크립트 입력을 차단.
2.2 출력 시 필터링
- HTML, URL, JavaScript, CSS 등 컨텍스트에 맞는 필터링 적용
-- HTML: htmlspecialchars() 또는 htmlentities()
-- URL: urlencode() 또는 rawurlencode()
-- JavaScript: JSON 형태로 인코딩
2.3 콘텐츠 보안 정책 (CSP)
브라우저에서 실행 가능한 스크립트를 제한.
3. PHP에서 XSS 방지 실무 소스
3.1 프로젝트 구조
(1) index.php - 사용자 입력 폼
(2) process.php - 데이터 처리 및 결과 출력
(3) utils.php - 보조 함수 제공
3.2 입력 폼 (index.php)
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>XSS 방지 데모</title>
</head>
<body>
<h1>XSS 방지 데모</h1>
<form action="process.php" method="POST">
<label for="username">사용자 이름:</label>
<input type="text" id="username" name="username" required>
<br><br>
<label for="comment">댓글:</label>
<textarea id="comment" name="comment" rows="5" required></textarea>
<br><br>
<button type="submit">전송</button>
</form>
</body>
</html>
3.3 데이터 처리 (process.php)
<?php
require 'utils.php';
// 데이터 수신
$username = $_POST['username'] ?? '';
$comment = $_POST['comment'] ?? '';
// HTML 엔티티 처리 (XSS 방지)
$username = escapeHtml($username);
$comment = escapeHtml($comment);
// 결과 출력
?>
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>처리 결과</title>
</head>
<body>
<h1>처리 결과</h1>
<p>사용자 이름: <?= $username ?></p>
<p>댓글:</p>
<pre><?= $comment ?></pre>
<br>
<a href="index.php">돌아가기</a>
</body>
</html>
3.4 보조 함수 (utils.php)
<?php
/**
* HTML 특수문자를 엔티티로 변환
* @param string $string 사용자 입력 데이터
* @return string 변환된 문자열
*/
function escapeHtml(string $string): string {
return htmlspecialchars($string, ENT_QUOTES | ENT_HTML5, 'UTF-8');
}
/**
* URL 인코딩 (출력 시 URL 컨텍스트에서 사용)
* @param string $string URL 파라미터 값
* @return string 인코딩된 URL
*/
function escapeUrl(string $string): string {
return rawurlencode($string);
}
/**
* JSON 출력용 이스케이프
* @param string $string JavaScript 출력에 사용할 데이터
* @return string JSON 안전하게 변환된 문자열
*/
function escapeJs(string $string): string {
return json_encode($string, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT);
}
4. 보안 체크리스트
4.1 XSS 방지에 꼭 해야 할 것
(1) 입력 검증: 허용된 데이터만 입력 가능하도록 제한.
(2) 출력 컨텍스트에 따른 필터링
- HTML 컨텍스트: htmlspecialchars()
- URL 컨텍스트: rawurlencode()
- JavaScript 컨텍스트: json_encode()
(3) HTTP 응답 헤더 설정
Content-Security-Policy로 인라인 스크립트 제한.
header("Content-Security-Policy: default-src 'self'; script-src 'self';");
5. 실행 결과
(1) 입력 예 (index.php)
- 사용자 이름: <script>alert('XSS');</script>
- 댓글: <b>Hello, World!</b>
(2) 출력 결과 (process.php)
<p>사용자 이름: <script>alert('XSS');</script></p>
<p>댓글:</p>
<pre><b>Hello, World!</b></pre>
<script> 및 <b> 태그가 그대로 텍스트로 출력되며, 스크립트가 실행되지 않습니다.
6. 확장 적용
(1) 데이터베이스 연동
- 입력값을 저장하기 전에 필터링 및 검증.
- 데이터 조회 후 출력 시 컨텍스트에 맞는 필터링 적용.
(2) 로그 데이터 처리
로그 파일이나 API 응답에 삽입 시에도 동일한 원칙 적용.
(3) 템플릿 엔진
Twig 또는 Blade와 같은 템플릿 엔진은 기본적으로 출력 시 HTML 특수문자를 이스케이프 처리.
7. 요약
- 핵심은 입력 검증과 출력 필터링이다.
- XSS 방지는 단순한 엔코딩 이상의 고려가 필요하며, 웹 애플리케이션의 모든 단계에서 구현해야 한다.
With ChatGPT
'PHP > 포스팅' 카테고리의 다른 글
[PHP] CSRF 공격 방지 데이터 베이스 활용 (0) | 2024.12.26 |
---|---|
[PHP] CSRF 공격 방지 (0) | 2024.12.26 |
[PHP] GET 방식 폼 양식의 데이터 처리 (0) | 2024.12.26 |
[PHP] POST 방식 폼 양식의 데이터 처리 (0) | 2024.12.25 |
[PHP] 함수의 매개변수 (0) | 2024.12.01 |