μλ°μ€ν¬λ¦½νΈ μ ν리μΌμ΄μ μ XSS λ° CSRF μ·¨μ½μ μ μ΄ν΄νκ³ μλ°©νμ¬, μ μΈκ³ μ¬μ©μλ₯Ό μν κ°λ ₯ν 보μμ 보μ₯νλ μ’ ν© κ°μ΄λμ λλ€.
μλ°μ€ν¬λ¦½νΈ 보μ: XSSμ CSRF λ°©μ΄ λ§μ€ν°νκΈ°
μ€λλ μνΈ μ°κ²°λ λμ§νΈ νκ²½μμ μΉ μ ν리μΌμ΄μ 보μμ 무μλ³΄λ€ μ€μν©λλ€. μΉμ μΈμ΄μΈ μλ°μ€ν¬λ¦½νΈλ μνΈμμ©μ μ΄κ³ λμ μΈ μ¬μ©μ κ²½νμ ꡬμΆνλ λ° κ²°μ μ μΈ μν μ ν©λλ€. νμ§λ§ μ μ€νκ² λ€λ£¨μ§ μμΌλ©΄ μ μ¬μ μΈ λ³΄μ μ·¨μ½μ μ λ ΈμΆν μλ μμ΅λλ€. μ΄ μ’ ν© κ°μ΄λλ κ°μ₯ λ리 νΌμ§ λ κ°μ§ μΉ λ³΄μ μνμΈ μ¬μ΄νΈ κ° μ€ν¬λ¦½ν (XSS)κ³Ό μ¬μ΄νΈ κ° μμ² μμ‘°(CSRF)μ λν΄ κΉμ΄ νκ³ λ€λ©°, λ€μν λ°°κ²½κ³Ό μ λ¬Έ μ§μμ κ°μ§ μ μΈκ³ μ¬μ©μλ₯Ό μν΄ μλ°μ€ν¬λ¦½νΈ μ ν리μΌμ΄μ μμ μ΄λ₯Ό λ°©μ§νλ μ€μ©μ μΈ μ λ΅μ μ 곡ν©λλ€.
μ¬μ΄νΈ κ° μ€ν¬λ¦½ν (XSS) μ΄ν΄νκΈ°
μ¬μ΄νΈ κ° μ€ν¬λ¦½ν (XSS)μ μ μ± μ€ν¬λ¦½νΈκ° μ λ’°ν μ μλ μ μμ μΈ μΉμ¬μ΄νΈμ μ£Όμ λλ μΈμ μ 곡격μ ν μ νμ λλ€. XSS 곡격μ 곡격μκ° μΉ μ ν리μΌμ΄μ μ μ¬μ©νμ¬ μΌλ°μ μΌλ‘ λΈλΌμ°μ μΈ‘ μ€ν¬λ¦½νΈ ννμ μ μ± μ½λλ₯Ό λ€λ₯Έ μ΅μ’ μ¬μ©μμκ² μ μ‘ν λ λ°μν©λλ€. μ΄λ¬ν 곡격μ νμ©νλ κ²°ν¨μ λ§€μ° λ리 νΌμ Έ μμΌλ©°, μΉ μ ν리μΌμ΄μ μ΄ μ¬μ©μμ μ λ ₯μ κ²μ¦νκ±°λ μΈμ½λ©νμ§ μκ³ μμ±νλ μΆλ ₯ λ΄μμ μ¬μ©νλ λͺ¨λ κ³³μμ λ°μν μ μμ΅λλ€.
μ¬μ©μκ° λΈλ‘κ·Έ κ²μλ¬Όμ λκΈμ λ¨κΈΈ μ μλ μλ리μ€λ₯Ό μμν΄ λ³΄μΈμ. μ μ ν μ μ (sanitization)κ° μλ€λ©΄, 곡격μλ μμ μ λκΈμ μ μ± μλ°μ€ν¬λ¦½νΈ μ½λλ₯Ό μ£Όμ ν μ μμ΅λλ€. λ€λ₯Έ μ¬μ©μκ° ν΄λΉ λΈλ‘κ·Έ κ²μλ¬Όμ λ³Ό λ, μ΄ μ μ± μ€ν¬λ¦½νΈλ κ·Έλ€μ λΈλΌμ°μ μμ μ€νλμ΄ μ μ¬μ μΌλ‘ μΏ ν€λ₯Ό νμΉκ±°λ νΌμ± μ¬μ΄νΈλ‘ 리λλ μ νκ±°λ κ³μ μ νμ·¨ν μλ μμ΅λλ€. μ΄λ μ¬μ©μμ μ§λ¦¬μ μμΉλ λ¬Ένμ λ°°κ²½μ κ΄κ³μμ΄ μ μΈκ³ μ¬μ©μμκ² μν₯μ λ―ΈμΉ μ μμ΅λλ€.
XSS 곡격μ μ ν
- μ μ₯ν(μ§μμ ) XSS: μ μ± μ€ν¬λ¦½νΈκ° λ°μ΄ν°λ² μ΄μ€, λ©μμ§ ν¬λΌ λλ λκΈ νλμ κ°μ΄ λμ μλ²μ μꡬμ μΌλ‘ μ μ₯λ©λλ€. μ¬μ©μκ° μν₯μ λ°λ νμ΄μ§λ₯Ό λ°©λ¬Έν λλ§λ€ μ€ν¬λ¦½νΈκ° μ€νλ©λλ€. μ΄λ λ§μ μ¬μ©μμκ² μν₯μ λ―ΈμΉ μ μκΈ° λλ¬Έμ κ°μ₯ μνν μ νμ λλ€. μμ: ν¬λΌμ μ μ₯λ μ μ± λκΈμ΄ ν΄λΉ ν¬λΌμ 보λ μ¬μ©μλ₯Ό κ°μΌμν€λ κ²½μ°.
- λ°μ¬ν(λΉμ§μμ ) XSS: μ μ± μ€ν¬λ¦½νΈκ° URLμ΄λ λ€λ₯Έ μμ² λ§€κ°λ³μμ μ£Όμ λμ΄ μ¬μ©μμκ² λ€μ λ°μ¬λ©λλ€. μ¬μ©μλ μ μ± λ§ν¬λ₯Ό ν΄λ¦νκ±°λ κ³΅κ²©μ΄ ν¬ν¨λ μμμ μ μΆνλλ‘ μ λλμ΄μΌ ν©λλ€. μμ: 쿼리 λ§€κ°λ³μμ μ μ± μλ°μ€ν¬λ¦½νΈκ° μ£Όμ λ λ§ν¬κ° ν¬ν¨λ νΌμ± μ΄λ©μΌ.
- DOM κΈ°λ° XSS: μ·¨μ½μ μ΄ μλ² μΈ‘ μ½λκ° μλ ν΄λΌμ΄μΈνΈ μΈ‘ μλ°μ€ν¬λ¦½νΈ μ½λ μ체μ μ‘΄μ¬ν©λλ€. 곡격μ μ€ν¬λ¦½νΈκ° μ’ μ’ μ¬μ©μ μ 곡 λ°μ΄ν°λ₯Ό μ¬μ©νμ¬ μμ νμ§ μμ λ°©μμΌλ‘ DOM(λ¬Έμ κ°μ²΄ λͺ¨λΈ)μ μμ ν λ λ°μν©λλ€. μμ: μλ°μ€ν¬λ¦½νΈ μ ν리μΌμ΄μ μ΄ `document.URL`μ μ¬μ©νμ¬ λ°μ΄ν°λ₯Ό μΆμΆνκ³ μ μ ν μ μ μμ΄ νμ΄μ§μ μ£Όμ νλ κ²½μ°.
XSS 곡격 λ°©μ΄: κΈλ‘λ² μ κ·Όλ²
XSSλ‘λΆν° 보νΈνλ €λ©΄ μλ² μΈ‘κ³Ό ν΄λΌμ΄μΈνΈ μΈ‘ 보μ μ‘°μΉλ₯Ό λͺ¨λ ν¬ν¨νλ λ€μΈ΅μ μΈ μ κ·Ό λ°©μμ΄ νμν©λλ€. λ€μμ λͺ κ°μ§ μ£Όμ μ λ΅μ λλ€:
- μ λ ₯ κ° κ²μ¦: λͺ¨λ μ¬μ©μ μ λ ₯μ μλ² μΈ‘μμ κ²μ¦νμ¬ μμ νμκ³Ό κΈΈμ΄λ₯Ό μ€μνλμ§ νμΈν©λλ€. μμ¬μ€λ¬μ΄ λ¬Έμλ ν¨ν΄μ΄ ν¬ν¨λ μ λ ₯μ κ±°λΆν©λλ€. μ¬κΈ°μλ μμ, URL, μΏ ν€ λ° APIμ λ°μ΄ν° κ²μ¦μ΄ ν¬ν¨λ©λλ€. κ²μ¦ κ·μΉμ ꡬνν λ μ΄λ¦ μ§μ κ·μΉμ΄λ μ£Όμ νμμ λ¬Ένμ μ°¨μ΄λ₯Ό κ³ λ €νμΈμ.
- μΆλ ₯ μΈμ½λ©(μ΄μ€μΌμ΄ν): λͺ¨λ μ¬μ©μ μ 곡 λ°μ΄ν°λ₯Ό HTMLμ νμνκΈ° μ μ μΈμ½λ©ν©λλ€. μ΄λ κ² νλ©΄ μ μ¬μ μΌλ‘ μ ν΄ν λ¬Έμκ° μμ ν HTML μν°ν°λ‘ λ³νλ©λλ€. μλ₯Ό λ€μ΄, `<`λ `<`κ° λκ³ `>`λ `>`κ° λ©λλ€. λ°μ΄ν°κ° μ¬μ©λ νΉμ 컨ν μ€νΈ(μ: HTML, μλ°μ€ν¬λ¦½νΈ, CSS)μ λ§κ² μ¬λ°λ₯΄κ² μΈμ½λ©λλλ‘ μν©μ λ§λ μΈμ½λ©μ μ¬μ©νμΈμ. λ§μ μλ² μΈ‘ νλ μμν¬λ λ΄μ₯ μΈμ½λ© ν¨μλ₯Ό μ 곡ν©λλ€. μλ°μ€ν¬λ¦½νΈμμλ DOMPurify λλ μ μ¬ν λΌμ΄λΈλ¬λ¦¬λ₯Ό μ¬μ©νμ¬ HTMLμ μ μ νμΈμ.
- μ½ν μΈ λ³΄μ μ μ± (CSP): μ격ν μ½ν μΈ λ³΄μ μ μ± (CSP)μ ꡬννμ¬ λΈλΌμ°μ κ° λ‘λν μ μλ 리μμ€λ₯Ό μ μ΄ν©λλ€. CSPλ μ€ν¬λ¦½νΈ, μ€νμΌμνΈ, μ΄λ―Έμ§ λ° κΈ°ν 리μμ€λ₯Ό λ‘λν μ μλ μμ€λ₯Ό μ§μ νμ¬ XSS 곡격μ λ°©μ§νλ λ° λμμ΄ λ©λλ€. `Content-Security-Policy` HTTP ν€λ λλ `` νκ·Έλ₯Ό μ¬μ©νμ¬ CSPλ₯Ό μ μν μ μμ΅λλ€. μμ CSP μ§μλ¬Έ: `Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; img-src 'self' data:;` ν©λ²μ μΈ κΈ°λ₯μ μ μ§νλ©΄μ κ°λ ₯ν 보μμ μ 곡νλλ‘ CSPλ₯Ό μ μ€νκ² κ΅¬μ±νμΈμ. CSP κ·μΉμ μ μν λ CDN μ¬μ©μ μ§μμ μ°¨μ΄λ₯Ό κ³ λ €νμΈμ.
- μλ μ΄μ€μΌμ΄νμ μ 곡νλ νλ μμν¬ μ¬μ©: React, Angular, Vue.jsμ κ°μ μ΅μ μλ°μ€ν¬λ¦½νΈ νλ μμν¬λ μλ μ΄μ€μΌμ΄ν λ° μ¬μ©μ μ 곡 λ°μ΄ν°λ‘ μ§μ μ μΈ DOM μ‘°μμ λ°©μ§νλ ν νλ¦Ώ μμ€ν κ³Ό κ°μ λ΄μ₯ XSS λ³΄νΈ λ©μ»€λμ¦μ μ 곡ν©λλ€. μ΄λ¬ν κΈ°λ₯μ νμ©νμ¬ XSS μ·¨μ½μ μ μνμ μ΅μννμΈμ.
- λΌμ΄λΈλ¬λ¦¬ λ° νλ μμν¬ μ κΈ° μ λ°μ΄νΈ: μλ°μ€ν¬λ¦½νΈ λΌμ΄λΈλ¬λ¦¬ λ° νλ μμν¬λ₯Ό μ΅μ 보μ ν¨μΉλ‘ μ λ°μ΄νΈνμΈμ. μ·¨μ½μ μ μ’ μ’ μ΅μ λ²μ μμ λ°κ²¬λκ³ μμ λλ―λ‘, μ΅μ μνλ₯Ό μ μ§νλ κ²μ μμ ν μ ν리μΌμ΄μ μ μ μ§νλ λ° νμμ μ λλ€.
- μ¬μ©μ κ΅μ‘: μ¬μ©μμκ² μμ¬μ€λ¬μ΄ λ§ν¬λ₯Ό ν΄λ¦νκ±°λ μ λ’°ν μ μλ μΉμ¬μ΄νΈμ λ―Όκ°ν μ 보λ₯Ό μ λ ₯νλ κ²μ λν΄ μ£Όμνλλ‘ κ΅μ‘νμΈμ. νΌμ± 곡격μ μ’ μ’ μ΄λ©μΌμ΄λ μμ λ―Έλμ΄λ₯Ό ν΅ν΄ μ¬μ©μλ₯Ό λμμΌλ‘ νλ―λ‘, μΈμμ λμ΄λ κ²μ μ¬μ©μκ° XSS 곡격μ ν¬μμμ΄ λλ κ²μ λ°©μ§νλ λ° λμμ΄ λ μ μμ΅λλ€.
- HTTPOnly μΏ ν€ μ¬μ©: λ―Όκ°ν μΏ ν€μ HTTPOnly νλκ·Έλ₯Ό μ€μ νμ¬ ν΄λΌμ΄μΈνΈ μΈ‘ μ€ν¬λ¦½νΈκ° μ κ·Όνμ§ λͺ»νλλ‘ ν©λλ€. μ΄λ μΏ ν€ νμ·¨λ₯Ό μλνλ XSS 곡격μ μνμ μννλ λ° λμμ΄ λ©λλ€.
μ€μ©μ μΈ XSS λ°©μ΄ μμ
μ¬μ©μκ° μ μΆν λ©μμ§λ₯Ό νμνλ μλ°μ€ν¬λ¦½νΈ μ ν리μΌμ΄μ μ μκ°ν΄ 보μΈμ. XSSλ₯Ό λ°©μ§νκΈ° μν΄ λ€μκ³Ό κ°μ κΈ°μ μ μ¬μ©ν μ μμ΅λλ€:
// ν΄λΌμ΄μΈνΈ μΈ‘ (DOMPurify μ¬μ©)
const message = document.getElementById('userMessage').value;
const cleanMessage = DOMPurify.sanitize(message);
document.getElementById('displayMessage').innerHTML = cleanMessage;
// μλ² μΈ‘ (Node.js μμ , express-validator λ° escape μ¬μ©)
const { body, validationResult } = require('express-validator');
app.post('/submit-message', [
body('message').trim().escape(),
], (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
const message = req.body.message;
// λ°μ΄ν°λ² μ΄μ€μ λ©μμ§λ₯Ό μμ νκ² μ μ₯
});
μ΄ μμ λ ν΄λΌμ΄μΈνΈ μΈ‘μμ DOMPurifyλ₯Ό μ¬μ©νκ³ μλ² μΈ‘μμ express-validatorμ μ΄μ€μΌμ΄ν ν¨μλ₯Ό μ¬μ©νμ¬ μ¬μ©μ μ λ ₯μ μ μ νλ λ°©λ²μ 보μ¬μ€λλ€. μ΅λ 보μμ μν΄ νμ ν΄λΌμ΄μΈνΈ μΈ‘κ³Ό μλ² μΈ‘ λͺ¨λμμ λ°μ΄ν°λ₯Ό κ²μ¦νκ³ μ μ ν΄μΌ νλ€λ κ²μ κΈ°μ΅νμΈμ.
μ¬μ΄νΈ κ° μμ² μμ‘°(CSRF) μ΄ν΄νκΈ°
μ¬μ΄νΈ κ° μμ² μμ‘°(CSRF)λ μ΅μ’ μ¬μ©μκ° νμ¬ μΈμ¦λ μΉ μ ν리μΌμ΄μ μμ μμΉ μλ μμ μ μ€ννλλ‘ κ°μνλ 곡격μ λλ€. CSRF 곡격μ 곡격μκ° μμ‘°λ μμ²μ λν μλ΅μ λ³Ό μ μκΈ° λλ¬Έμ λ°μ΄ν° νμ·¨κ° μλ μν λ³κ²½ μμ²μ ꡬ체μ μΌλ‘ λμμΌλ‘ ν©λλ€. μ¬ν 곡ν(μ΄λ©μΌμ΄λ μ±ν μ ν΅ν΄ λ§ν¬λ₯Ό 보λ΄λ λ±)μ μ½κ°μ λμμΌλ‘, 곡격μλ μΉ μ ν리μΌμ΄μ μ¬μ©μλ₯Ό μμ¬ μμ μ΄ μ νν μμ μ μ€ννκ² ν μ μμ΅λλ€. νΌν΄μκ° μΌλ° μ¬μ©μμΈ κ²½μ°, μ±κ³΅μ μΈ CSRF 곡격μ μ¬μ©μκ° μκΈ μ΄μ²΄, μ΄λ©μΌ μ£Όμ λ³κ²½ λ±κ³Ό κ°μ μν λ³κ²½ μμ²μ μννλλ‘ κ°μν μ μμ΅λλ€. νΌν΄μκ° κ΄λ¦¬μ κ³μ μΈ κ²½μ°, CSRFλ μ 체 μΉ μ ν리μΌμ΄μ μ μμμν¬ μ μμ΅λλ€.
μ¨λΌμΈ λ± νΉ κ³μ μ λ‘κ·ΈμΈν μ¬μ©μλ₯Ό μμν΄ λ³΄μΈμ. 곡격μλ μ¬μ©μμ κ³μ’μμ μμ μ κ³μ’λ‘ μκΈμ μ΄μ²΄νλ μμ²μ μλμΌλ‘ μ μΆνλ μμμ΄ ν¬ν¨λ μ μ± μΉμ¬μ΄νΈλ₯Ό λ§λ€ μ μμ΅λλ€. μ¬μ©μκ° λ± νΉ κ³μ μ λ‘κ·ΈμΈν μνμμ μ΄ μ μ± μΉμ¬μ΄νΈλ₯Ό λ°©λ¬Ένλ©΄, λΈλΌμ°μ λ μλμΌλ‘ μνμ μμ²μ 보λ΄κ³ , μνμ μ¬μ©μκ° μΈμ¦λμκΈ° λλ¬Έμ μ΄μ²΄λ₯Ό μ²λ¦¬ν κ²μ λλ€. μ΄κ²μ λ¨μνλ μμ§λ§, CSRFμ ν΅μ¬ μ리λ₯Ό 보μ¬μ€λλ€.
CSRF 곡격 λ°©μ΄: κΈλ‘λ² μ κ·Όλ²
CSRF λ°©μ΄λ μμ²μ΄ μ μ± μ¬μ΄νΈκ° μλ μ¬μ©μλ‘λΆν° μ§μ μΌλ‘ λΉλ‘―λ κ²μμ 보μ₯νλ κ²μ ν¬ν¨ν©λλ€. λ€μμ λͺ κ°μ§ μ£Όμ μ λ΅μ λλ€:
- CSRF ν ν°(λκΈ°ν ν ν° ν¨ν΄): CSRF 곡격μ λ°©μ΄νλ κ°μ₯ μΌλ°μ μ΄κ³ ν¨κ³Όμ μΈ λ°©λ²μ CSRF ν ν°μ μ¬μ©νλ κ²μ λλ€. CSRF ν ν°μ μλ²μμ μμ±λμ΄ μμμ΄λ μμ²μ ν¬ν¨λλ κ³ μ νκ³ μμΈ‘ λΆκ°λ₯νλ©° λΉλ°μ€λ¬μ΄ κ°μ λλ€. μ¬μ©μκ° μμμ μ μΆνλ©΄ μλ²λ CSRF ν ν°μ΄ μ‘΄μ¬νκ³ μμ±ν κ°κ³Ό μΌμΉνλμ§ νμΈν©λλ€. ν ν°μ΄ μκ±°λ μΌμΉνμ§ μμΌλ©΄ μμ²μ΄ κ±°λΆλ©λλ€. μ΄λ 곡격μκ° μ¬λ°λ₯Έ CSRF ν ν°μ μ»μ μ μκΈ° λλ¬Έμ μμ² μμ‘°λ₯Ό λ°©μ§ν©λλ€. λ§μ μΉ νλ μμν¬λ λ΄μ₯λ CSRF λ³΄νΈ λ©μ»€λμ¦μ μ 곡ν©λλ€. CSRF ν ν°μ΄ μ¬μ©μ μΈμ λΉ κ³ μ νκ³ XSS 곡격μΌλ‘λΆν° μ μ νκ² λ³΄νΈλλμ§ νμΈνμΈμ. μμ: μλ²μμ μμμ ν ν°μ μμ±νκ³ μ¬μ©μ μΈμ μ μ μ₯ν λ€μ, μμμ μ¨κ²¨μ§ νλλ‘ ν¬ν¨μν€κ³ μμμ΄ μ μΆλ λ ν ν°μ νμΈν©λλ€.
- SameSite μΏ ν€: HTTP μΏ ν€μ `SameSite` μμ±μ μ¬μ΄νΈ κ° μμ²κ³Ό ν¨κ» μΏ ν€κ° μ μ‘λλ λ°©μμ μ μ΄νλ λ©μ»€λμ¦μ μ 곡ν©λλ€. `SameSite=Strict`λ‘ μ€μ νλ©΄ λͺ¨λ μ¬μ΄νΈ κ° μμ²κ³Ό ν¨κ» μΏ ν€κ° μ μ‘λλ κ²μ λ°©μ§νμ¬ κ°λ ₯ν CSRF 보νΈλ₯Ό μ 곡ν©λλ€. `SameSite=Lax`λ μ΅μμ νμ(μ: λ§ν¬ ν΄λ¦)κ³Ό ν¨κ» μΏ ν€λ₯Ό μ μ‘νλλ‘ νμ©νμ§λ§ λ€λ₯Έ μ¬μ΄νΈ κ° μμ²μλ νμ©νμ§ μμ΅λλ€. `SameSite=None; Secure`λ μ¬μ΄νΈ κ° μμ²κ³Ό ν¨κ» μΏ ν€λ₯Ό μ μ‘νλλ‘ νμ©νμ§λ§ HTTPSλ₯Ό ν΅ν΄μλ§ κ°λ₯ν©λλ€. μ΄μ λΈλΌμ°μ λ `SameSite` μμ±μ μ§μνμ§ μμ μ μμΌλ―λ‘ λ€λ₯Έ CSRF λ°©μ΄ κΈ°μ κ³Ό ν¨κ» μ¬μ©ν΄μΌ ν©λλ€.
- μ΄μ€ μ μΆ μΏ ν€ ν¨ν΄: μ΄ ν¨ν΄μ μΏ ν€μ μμμ κ°μ μ€μ νκ³ λμΌν κ°μ μμμ μ¨κ²¨μ§ νλλ‘ ν¬ν¨νλ κ²μ ν¬ν¨ν©λλ€. μμμ΄ μ μΆλ λ μλ²λ μΏ ν€ κ°κ³Ό μμ νλ κ°μ΄ μΌμΉνλμ§ νμΈν©λλ€. 곡격μλ λ€λ₯Έ λλ©μΈμμ μΏ ν€ κ°μ μ½μ μ μκΈ° λλ¬Έμ μ΄ λ°©λ²μ΄ μλν©λλ€. μ΄ λ°©λ²μ λΈλΌμ°μ μ λμΌ μΆμ² μ μ± (Same-Origin Policy)μ μμ‘΄νλ©°, κ²½μ°μ λ°λΌ μ°νλ μ μμΌλ―λ‘ CSRF ν ν°μ μ¬μ©νλ κ²λ³΄λ€ λ κ°λ ₯ν©λλ€.
- Referer ν€λ κ²μ¦: μμ²μ `Referer` ν€λλ₯Ό νμΈνμ¬ μμ²μ μμ μΆμ²μ μΌμΉνλμ§ νμΈν©λλ€. κ·Έλ¬λ `Referer` ν€λλ 곡격μμ μν΄ μ½κ² μμ‘°λ μ μμΌλ―λ‘ CSRF 보νΈμ μ μΌν μλ¨μΌλ‘ μμ‘΄ν΄μλ μ λ©λλ€. μΆκ°μ μΈ λ°©μ΄ κ³μΈ΅μΌλ‘ μ¬μ©ν μ μμ΅λλ€.
- λ―Όκ°ν μμ μ λν μ¬μ©μ μνΈμμ©: μκΈ μ΄μ²΄λ λΉλ°λ²νΈ λ³κ²½κ³Ό κ°μ λ§€μ° λ―Όκ°ν μμ μ κ²½μ°, μ¬μ©μμκ² μ¬μΈμ¦μ μꡬνκ±°λ ν΄λν°μ΄λ μ΄λ©μΌλ‘ μ μ‘λ μΌνμ© λΉλ°λ²νΈ(OTP)λ₯Ό μ λ ₯νλ κ²κ³Ό κ°μ μΆκ° μ‘°μΉλ₯Ό μννλλ‘ μꡬνμΈμ. μ΄λ μΆκ°μ μΈ λ³΄μ κ³μΈ΅μ μΆκ°νκ³ κ³΅κ²©μκ° μμ²μ μμ‘°νκΈ° μ΄λ ΅κ² λ§λλλ€.
- μν λ³κ²½ μμ μ GET μμ² μ¬μ© νΌνκΈ°: GET μμ²μ λ°μ΄ν°λ₯Ό κ²μνλ λ° μ¬μ©ν΄μΌ νλ©°, μ ν리μΌμ΄μ μ μνλ₯Ό μμ νλ μμ μ μννλ λ° μ¬μ©ν΄μλ μ λ©λλ€. μν λ³κ²½ μμ μλ POST, PUT λλ DELETE μμ²μ μ¬μ©νμΈμ. μ΄λ κ² νλ©΄ 곡격μκ° κ°λ¨ν λ§ν¬λ μ΄λ―Έμ§λ₯Ό μ¬μ©νμ¬ μμ²μ μμ‘°νκΈ°κ° λ μ΄λ €μμ§λλ€.
μ€μ©μ μΈ CSRF λ°©μ΄ μμ
μ¬μ©μκ° μ΄λ©μΌ μ£Όμλ₯Ό μ λ°μ΄νΈν μ μλ μΉ μ ν리μΌμ΄μ μ μκ°ν΄ 보μΈμ. CSRFλ₯Ό λ°©μ§νκΈ° μν΄ λ€μκ³Ό κ°μ΄ CSRF ν ν°μ μ¬μ©ν μ μμ΅λλ€:
// μλ² μΈ‘ (Node.js μμ , csurf μ¬μ©)
const csrf = require('csurf');
const cookieParser = require('cookie-parser');
const app = express();
app.use(cookieParser());
app.use(csrf({ cookie: true }));
app.get('/profile', (req, res) => {
res.render('profile', { csrfToken: req.csrfToken() });
});
app.post('/update-email', (req, res) => {
// CSRF ν ν° νμΈ
if (req.csrfToken() !== req.body._csrf) {
return res.status(403).send('CSRF token validation failed');
}
// μ΄λ©μΌ μ£Όμ μ
λ°μ΄νΈ
});
// ν΄λΌμ΄μΈνΈ μΈ‘ (HTML μμ)
μ΄ μμ λ Node.jsμμ `csurf` λ―Έλ€μ¨μ΄λ₯Ό μ¬μ©νμ¬ CSRF ν ν°μ μμ±νκ³ νμΈνλ λ°©λ²μ 보μ¬μ€λλ€. CSRF ν ν°μ μμμ μ¨κ²¨μ§ νλλ‘ ν¬ν¨λλ©°, μλ²λ μμμ΄ μ μΆλ λ ν ν°μ νμΈν©λλ€.
μ΄μ²΄μ μΈ λ³΄μ μ κ·Όλ²μ μ€μμ±
XSS λ° CSRF μ·¨μ½μ μ λ°©μ§νλ €λ©΄ μΉ μ ν리μΌμ΄μ κ°λ° λΌμ΄νμ¬μ΄ν΄μ λͺ¨λ μΈ‘λ©΄μ ν¬κ΄νλ ν¬κ΄μ μΈ λ³΄μ μ λ΅μ΄ νμν©λλ€. μ¬κΈ°μλ μμ ν μ½λ© κ΄ν, μ κΈ°μ μΈ λ³΄μ κ°μ¬, μΉ¨ν¬ ν μ€νΈ λ° μ§μμ μΈ λͺ¨λν°λ§μ΄ ν¬ν¨λ©λλ€. μ μ μ μ΄κ³ λ€μΈ΅μ μΈ μ κ·Ό λ°©μμ μ±νν¨μΌλ‘μ¨ λ³΄μ μΉ¨ν΄ μνμ ν¬κ² μ€μ΄κ³ μ¬μ©μλ₯Ό μνμΌλ‘λΆν° 보νΈν μ μμ΅λλ€. λ¨μΌ κΈ°μ λ§μΌλ‘λ μλ²½ν 보μμ 보μ₯ν μ μλ€λ μ μ κΈ°μ΅νμΈμ. μ΄λ¬ν λ°©λ²λ€μ μ‘°ν©νλ κ²μ΄ κ°μ₯ κ°λ ₯ν λ°©μ΄λ₯Ό μ 곡ν©λλ€.
κΈλ‘λ² λ³΄μ νμ€ λ° λ¦¬μμ€ νμ©
λͺλͺ κ΅μ 기ꡬ λ° μ΄λμ ν°λΈλ μΉ λ³΄μ λͺ¨λ² μ¬λ‘μ λν κ·μ€ν 리μμ€μ μ§μΉ¨μ μ 곡ν©λλ€. μ£Όλͺ©ν λ§ν μλ λ€μκ³Ό κ°μ΅λλ€:
- OWASP(Open Web Application Security Project): OWASPλ κ°μ₯ μ€μν μΉ μ ν리μΌμ΄μ 보μ μνμ μλ³νλ OWASP Top Tenμ ν¬ν¨νμ¬ μΉ μ ν리μΌμ΄μ 보μμ λν λ¬΄λ£ λ° μ€ν μμ€ λ¦¬μμ€λ₯Ό μ 곡νλ λΉμ리 λ¨μ²΄μ λλ€.
- NIST(λ―Έκ΅ κ΅λ¦½νμ€κΈ°μ μ°κ΅¬μ): NISTλ μμ ν μννΈμ¨μ΄ κ°λ° λ° μ·¨μ½μ κ΄λ¦¬μ λν μ§μΉ¨μ ν¬ν¨νμ¬ μ¬μ΄λ² 보μμ λν νμ€ λ° κ°μ΄λλΌμΈμ κ°λ°ν©λλ€.
- ISO(κ΅μ νμ€ν기ꡬ): ISOλ μ 보 보μ κ΄λ¦¬ μμ€ν (ISMS)μ λν κ΅μ νμ€μ κ°λ°νμ¬ μ‘°μ§μ΄ 보μ μνλ₯Ό κ΄λ¦¬νκ³ κ°μ ν μ μλ νλ μμν¬λ₯Ό μ 곡ν©λλ€.
μ΄λ¬ν 리μμ€μ νμ€μ νμ©ν¨μΌλ‘μ¨ μΉ μ ν리μΌμ΄μ μ΄ μ κ³ λͺ¨λ² μ¬λ‘μ λΆν©νκ³ μ μΈκ³ μ¬μ©μμ 보μ μꡬ μ¬νμ μΆ©μ‘±νλλ‘ λ³΄μ₯ν μ μμ΅λλ€.
κ²°λ‘
μλ°μ€ν¬λ¦½νΈ μ ν리μΌμ΄μ μ XSS λ° CSRF 곡격μΌλ‘λΆν° 보νΈνλ κ²μ μ¬μ©μλ₯Ό 보νΈνκ³ μΉ νλ«νΌμ 무결μ±μ μ μ§νλ λ° νμμ μ λλ€. μ΄λ¬ν μ·¨μ½μ μ λ³Έμ§μ μ΄ν΄νκ³ μ΄ κ°μ΄λμ μ€λͺ λ μλ°© μ λ΅μ ꡬνν¨μΌλ‘μ¨ λ³΄μ μΉ¨ν΄ μνμ ν¬κ² μ€μ΄κ³ λ μμ νκ³ νλ ₯μ μΈ μΉ μ ν리μΌμ΄μ μ ꡬμΆν μ μμ΅λλ€. μ΅μ 보μ μν λ° λͺ¨λ² μ¬λ‘μ λν μ 보λ₯Ό μ§μμ μΌλ‘ νμ νκ³ μλ‘μ΄ λ¬Έμ μ λμ²νκΈ° μν΄ λ³΄μ μ‘°μΉλ₯Ό μ§μμ μΌλ‘ μ‘°μ ν΄μΌ ν©λλ€. μΉ λ³΄μμ λν μ μ μ μ΄κ³ μ΄μ²΄μ μΈ μ κ·Ό λ°©μμ μ€λλ λμμμ΄ μ§ννλ λμ§νΈ νκ²½μμ μ ν리μΌμ΄μ μ μμ κ³Ό μ λ’°μ±μ 보μ₯νλ λ° μ€μν©λλ€.
μ΄ κ°μ΄λλ XSS λ° CSRF μ·¨μ½μ μ μ΄ν΄νκ³ μλ°©νκΈ° μν κ²¬κ³ ν κΈ°λ°μ μ 곡ν©λλ€. μ§ννλ μνμΌλ‘λΆν° μ ν리μΌμ΄μ κ³Ό μ¬μ©μλ₯Ό 보νΈνκΈ° μν΄ μ΅μ 보μ λͺ¨λ² μ¬λ‘λ₯Ό κ³μ λ°°μ°κ³ μ΅μ μνλ₯Ό μ μ§νμμμ€. 보μμ μΌνμ± ν΄κ²°μ± μ΄ μλ μ§μμ μΈ κ³Όμ μμ κΈ°μ΅νμΈμ.