자바스크립트를 허용해주세요.
[ 자바스크립트 활성화 방법 ]
from Mohon Aktifkan Javascript!
 

[웹] CORS, XSS, CSRF이란 무엇인가?

728x90

 

🔐 1.  서론 

웹 개발을 하다 보면 보안 취약점으로 인해 사용자와 시스템이 위험에 노출될 수가 있습니다, 대표적인 웹 보안 문제로는 CROS, XSS, CSRF가 있으며 각각의 원리와 방어 방법에 대해 이해하는 것이 가장 중요합니다. 이번 개념을 통해 로컬 환경에서 직접 실습하며 다음과 같은 개념을 확인할 수 있습니다.

  • 왜 이런 공격이 발생하는가
  • 어떤 방식으로 확인이 가능한가
  • 어떻게 방어할 수 있는가

🔐 2. CORS 실습 

브라우저는 기본적으로 동일 출처 정책(SOP)를 적용하여 다른 출처에서 요청을 하게되면 자동으로 차단됨니다 이것을 서버에서 CORS 헤더로 직접 허용해줘야 합니다.

 

🌚 환경 세팅

mkdir cxf-test
cd cxf-test
npm init -y
npm install express cors

 

nodejs 세팅이 완료되었다면 프로젝트 루트 폴더안에 index.js를 생성하고 다음과 같은 코드를 작성합니다.

const express = require("express");
const app = express();

app.get("/api/data", (req, res) => res.json({ message: "CORS Test " }));
app.listen(4000);

 

이제 이것을 바탕으로 직접 웹 사이트 공격을 해보겠습니다. 프로젝트 루트에 index.html을 생성해 다음과 같은 코드를 만듭니다.

<button id="fetchBtn">데이터 가져오기</button>
<pre id="result"></pre>

<script>
  document.getElementById("fetchBtn").onclick = async () => {
    try {
      const res = await fetch("http://localhost:4000/api/data", {
        credentials: "include",
      });
      const data = await res.json();
      document.getElementById("result").innerText = JSON.stringify(data);
    } catch (err) {
      console.error("에러발생:", err);
    }
  };
</script>

 

🔐공격 확인

  • 브라우저 콘솔 -> CORS 에러 발생
  • 네트워크 탭 -> 서버 응답은 정상이나 브라우저가 차단한 것 

🔐 방어 적용

const express = require("express");
const cors = require("cors");
const app = express();

// 방어 적용
const allowedOrigin = "http://127.0.0.1:5500";
app.use(
  cors({
    origin: allowedOrigin,
    credentials: true,
  })
);

app.get("/api/data", (req, res) => res.json({ message: "CORS Test " }));
app.listen(4000, () => console.log("Server is running port 4000"));

 

  • origin -> 브라우저에서 HTML을 열 때 origin으로 정확히 맞춤
  • credentials: true -> 쿠키/세션 포함 요청 허용

🔐 방어 확인

  • 브라우저 HTML에서 버튼 클릭 -> JSON 출력 정상 확인
  • 브라우저 콘솔 -> 에러 없음
항목 설명
SOP 브라우저 기본 정책, 다른 origin 요청 차단
CORS  서버에서 허용 origin과 credentials 헤더 설정 필요
origin 브라우저에서 요청하는 URL과 서버 허용 URL이 정확히 일치해야함
credentials  쿠키/세션 포함 요청 시 true 설정 필요, '*'와 동시에 불가

🔐 3. XSS 실습 

XSS(Cross-Site Scripting)은 공격자가 악성 스크립트를 웹페이지에 삽입하고 그것을  사용자의 브라우저에 실행하도록 하는 것입니다. 

  • 목적: 쿠키 탈취, 세션 하이재킹, 화면 변조 등
  • 종류
    • Reflected XSS: 사용자가 입력한 값이 바로 페이지에 반영될 때 발생
    • Stored XSS: 공격 스크립트가 DB에 저장되어 여러 사용자가 접속 시 실행
    • DOM-based XSS: 클라이언트 사이드 JS에서 직접 DOM을 조작하며 발생

🛜 환경 세팅

mkdir xss-test
cd xss-test
npm init -y
npm install express body-parser
const express = require("express");
const bodyParser = require("body-parser");
const app = express();

app.use(bodyParser.urlencoded({ extended: true }));

app.get("/", (req, res) => {
  res.send(`
     <form method="POST" action="/echo">
        <input name="msg" />
        <button>전송</button>
     </form>      
  `);
});

app.post("/echo", (req, res) => {
  const msg = req.body.msg;
  // 필터링 없이 바로 출력 -> 취약점
  res.send(`<h1>입력 메시지: </h1><p>${msg}</p>`);
});

app.listen(4001, () => console.log("XSS Test Server running on port 4001"));

 

🔐 공격 확인

  • 입력창에 <script>alert("XSS")</script> XSS 입력 
  • 제출 시 브라우저에서 팝업 발생 -> XSS 성공

🔐 방어 적용

const escapeHtml = (str) =>
  str
    .replace(/&/g, "&amp;")
    .replace(/</g, "&lt;")
    .replace(/>/g, "&gt;")
    .replace(/"/g, "&quot;")
    .replace(/'/g, "&#039;");

app.post("/echo", (req, res) => {
  const msg = escapeHtml(req.body.msg);
  // 필터링 없이 바로 출력 -> 취약점, => 방어적용후 <script>alert("XSS")</script>
  res.send(`<h1>입력 메시지: </h1><p>${msg}</p>`);
});

🔐 4. CSRF 실습

CSRF(Cross-Site Request Forgery)는 사용자가 로그인된 상태에 공격자가 만든 요청을 보내 사용자의 권한으로 악의적인 동작을 수행합니다.

 

🛜 환경 세팅

mkdir csrf-test
cd csrf-test
npm init -y
npm install express cookie-parser body-parser
const express = require("express");
const bodyParser = require("body-parser");
const cookieParser = require("cookie-parser");
const app = express();

app.use(bodyParser.urlencoded({ extended: true }));
app.use(cookieParser());

// 로그인 상태 가정
app.get("/login", (req, res) => {
  res.cookie("auth", "123");
  res.send("로그인 완료");
});

// 취약한 이메일 변경
app.post("/change-email", (req, res) => {
  const newEmail = req.body.email;
  // CSRF 취약: auth 쿠키 체크만, 쿠키 X
  res.send(`이메일이 ${newEmail}로 변경되었습니다.`);
});

app.listen(4003, () =>
  console.log("CSRF Email Test Server is running on port 4003")
);

 

🔐 공격 확인

<form action="http://localhost:4003/change-email" method="POST">
  <input type="hidden" name="email" value="attacker@example.com" />
  <input type="submit" value="Click me!" />
</form>
  • 사용자가 로그인 상태에서 공격 페이지를 열고 클릭 -> 이메일이 공격자 주소를 변경함
  • CSRF 성공

🔐 방어 적용 (CSRF 토큰 사용)

const csrf = require("csurf"); // yarn add csurf && npm install csurf
app.use(cookieParser());
app.use(csrf({ cookie: true }));


// 방어 적용
app.get("/change-email-form", (req, res) => {
  res.send(`
         <form method="POST" action="/change-email">
           <input name="email" />
           <input type="hidden" name="_csrf" value="${req.csrfToken()}" />
           <button>이메일 변경</button>
         </form>
        `);
});

// 취약한 이메일 변경
app.post("/change-email", (req, res) => {
  const newEmail = req.body.email;
  // CSRF 취약: auth 쿠키 체크만, 쿠키 X
  res.send(`이메일이 ${newEmail}로 변경되었습니다.`);
});

🛜 핵심 포인트

항목 설명
CSRF 공격 로그인 상태 사용자의 권한을 도용해 요청 수행
취약점 세션 쿠키만 확인, CSRF 토큰 없음
방어 CSRF 토큰 적용 -> 공격 페이지에서 요청 불가
실습 이메일 변경, 계정 설정 등

 

 

GitHub - Koras02/CORS-XSS-CSRF

Contribute to Koras02/CORS-XSS-CSRF development by creating an account on GitHub.

github.com

 

728x90
LIST

'' 카테고리의 다른 글

[알고리즘] 난수란?  (1) 2025.08.31
[Web] SSR이란? 서버 사이드 렌더링  (0) 2025.03.01
[Web] 인터넷 프로토콜의 종류  (0) 2025.02.27
[Web] 상태코드란?  (0) 2025.02.27
[Web] 개발자의 종류에 관해  (0) 2025.02.23