웹 보안: 필수 보안 관행

개발팀
3분 읽기
보안OWASP웹개발

웹 보안: 필수 보안 관행

웹 애플리케이션의 보안은 개발 단계부터 고려해야 할 중요한 요소입니다.

OWASP Top 10

1. Injection (SQL, XSS, etc.)

// 나쁜 예: SQL Injection 위험
const query = `SELECT * FROM users WHERE email = '${email}'`;

// 좋은 예: Prepared Statement
const query = 'SELECT * FROM users WHERE email = ?';
db.query(query, [email]);

2. XSS (Cross-Site Scripting) 방지

// 나쁜 예: 사용자 입력을 직접 렌더링
const html = `<p>${userInput}</p>`;

// 좋은 예: 이스케이프 처리
const escapeHtml = (text) => {
  const map = {
    '&': '&amp;',
    '<': '&lt;',
    '>': '&gt;',
    '"': '&quot;',
    "'": '&#039;'
  };
  return text.replace(/[&<>"']/g, m => map[m]);
};

3. CSRF (Cross-Site Request Forgery) 방지

// CSRF 토큰 생성 및 검증
const generateCSRFToken = () => crypto.randomBytes(32).toString('hex');

// 폼에 토큰 포함
<form method="POST">
  <input type="hidden" name="csrf" value="<%= csrfToken %>">
</form>

// 서버에서 검증
if (req.body.csrf !== req.session.csrfToken) {
  return res.status(403).json({ error: 'CSRF token invalid' });
}

인증 보안

// 암호 해싱 (bcrypt 사용)
const bcrypt = require('bcryptjs');

const hashPassword = async (password) => {
  const salt = await bcrypt.genSalt(10);
  return bcrypt.hash(password, salt);
};

const comparePassword = async (password, hash) => {
  return bcrypt.compare(password, hash);
};

JWT 토큰 보안

// JWT 서명 및 검증
const jwt = require('jsonwebtoken');

const generateToken = (userId) => {
  return jwt.sign({ userId }, process.env.JWT_SECRET, {
    expiresIn: '24h',
    algorithm: 'HS256'
  });
};

const verifyToken = (token) => {
  try {
    return jwt.verify(token, process.env.JWT_SECRET);
  } catch (error) {
    return null;
  }
};

환경 변수 관리

# .env 파일 (git에서 제외)
DATABASE_URL=postgresql://user:password@localhost/db
JWT_SECRET=your-secret-key-here
API_KEY=your-api-key

# 절대 커밋하지 마세요!
# .gitignore에 .env 추가
echo ".env" >> .gitignore

HTTPS 및 SSL/TLS

// Express에서 HTTPS 강제
const helmet = require('helmet');

app.use(helmet());
app.use((req, res, next) => {
  if (req.header('x-forwarded-proto') !== 'https') {
    res.redirect(`https://${req.header('host')}${req.url}`);
  }
  next();
});

CORS 정책 설정

const cors = require('cors');

app.use(cors({
  origin: process.env.ALLOWED_ORIGINS?.split(',') || 'http://localhost:3000',
  credentials: true,
  methods: ['GET', 'POST', 'PUT', 'DELETE'],
  allowedHeaders: ['Content-Type', 'Authorization']
}));

Rate Limiting

const rateLimit = require('express-rate-limit');

const limiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15분
  max: 100, // 최대 100 요청
  message: '너무 많은 요청이 발생했습니다.'
});

app.use('/api/', limiter);

입력 검증

const { body, validationResult } = require('express-validator');

app.post('/users', [
  body('email').isEmail().normalizeEmail(),
  body('password').isLength({ min: 8 }),
  body('name').trim().isLength({ min: 1 })
], (req, res) => {
  const errors = validationResult(req);
  if (!errors.isEmpty()) {
    return res.status(400).json({ errors: errors.array() });
  }
  // 검증 통과
});

보안 체크리스트

  • HTTPS/SSL 활성화
  • 암호 해싱 구현
  • CSRF 토큰 사용
  • XSS 방지 (입력 이스케이프)
  • SQL Injection 방지 (Prepared Statements)
  • CORS 정책 설정
  • Rate Limiting 구현
  • 입력 검증 및 새니타이제이션
  • 보안 헤더 설정
  • 의존성 보안 업데이트

웹 보안은 지속적인 관심과 개선이 필요한 영역입니다.

웹 보안: 필수 보안 관행 | 블로그