실전 예제로 배우는 OWASP Top 10
웹 애플리케이션을 구축했고 이제 보안이 걱정되시나요? OWASP Top 10은 중요한 웹 애플리케이션 보안 위험 목록으로 널리 알려져 있습니다. 하지만 목록을 읽는 것과 이러한 위험이 실제 코드에서 어떻게 나타나는지 이해하는 것은 별개입니다. 이 글에서는 OWASP Top 10 각 카테고리를 실제 예제와 함께 살펴보고 이를 완화하기 위한 구체적인 단계를 제시합니다.
1. 접근 제어 취약점 (Broken Access Control)
접근 제어 취약점은 사용자가 의도된 권한을 벗어나 행동할 수 있을 때 발생합니다. 예를 들어, 사용자가 URL 매개변수를 변경하여 다른 사용자의 계정에 접근할 수 있습니다.
// 취약점: 요청된 사용자 ID가 인증된 사용자의 것인지 확인하지 않음
app.get('/api/user/:id', (req, res) => {
const user = getUserById(req.params.id);
res.json(user);
});
완화 방법: 서버 측에서 접근 제어 검사를 시행하세요. 역할 기반 또는 속성 기반 접근 제어를 사용하고 기본적으로 거부하세요.
2. 암호화 실패 (Cryptographic Failures)
비밀번호 및 신용 카드 번호와 같은 민감한 데이터는 전송 중 및 저장 시 암호화되어야 합니다. 약한 알고리즘을 사용하거나 비밀을 하드코딩하는 것은 흔한 실수입니다.
# 취약점: 비밀번호 해싱에 MD5 사용
import hashlib
hash = hashlib.md5(password.encode()).hexdigest()
완화 방법: bcrypt 또는 Argon2와 같은 강력한 솔트 해싱 알고리즘을 사용하세요. 전송 중인 데이터에는 항상 HTTPS(TLS)를 사용하세요.
3. 인젝션 (Injection)
SQL 인젝션과 같은 인젝션 결함은 신뢰할 수 없는 데이터가 명령이나 쿼리의 일부로 인터프리터에 전송될 때 발생합니다.
// 취약점: SQL 쿼리에서 문자열 연결
$sql = "SELECT * FROM users WHERE username = '" . $_GET['username'] . "'";
완화 방법: 매개변수화된 쿼리 또는 준비된 문을 사용하세요. 사용자 입력을 쿼리에 직접 연결하지 마세요.
4. 안전하지 않은 설계 (Insecure Design)
안전하지 않은 설계는 제어 설계가 누락되었거나 비효율적인 경우를 말합니다. 예를 들어, 이메일 존재 여부를 노출하는 비밀번호 복구 시스템은 공격자에게 도움이 될 수 있습니다.
완화 방법: 설계 단계에서 위협 모델링을 수행하고, 안전한 설계 패턴을 사용하며, 속도 제한 및 기타 제어를 구현하세요.
5. 보안 구성 오류 (Security Misconfiguration)
기본 계정을 활성화된 상태로 두거나, 사용자에게 스택 추적을 표시하거나, 클라우드 스토리지 권한을 잘못 구성하는 경우가 포함됩니다.
# 취약점: 프로덕션에서 디버그 모드 활성화
DEBUG = True
완화 방법: 구성을 강화하고, 사용하지 않는 기능을 제거하며, 구성 검사를 자동화하세요.
6. 취약하고 오래된 구성 요소 (Vulnerable and Outdated Components)
알려진 취약점이 있는 라이브러리를 사용하는 것은 문을 열어두는 것과 같습니다. 예를 들어, 인기 라이브러리의 오래된 버전에는 원격 코드 실행 결함이 있을 수 있습니다.
완화 방법: 정기적으로 종속성을 업데이트하고, OWASP Dependency-Check와 같은 도구를 사용하며, CVE를 모니터링하세요.
7. 식별 및 인증 실패 (Identification and Authentication Failures)
약한 인증은 공격자가 비밀번호를 추측하거나 세션을 하이재킹할 수 있게 합니다.
// 취약점: 실패한 시도 후 계정 잠금 없음
if (passwordMatches) {
loginUser();
} else {
// 오류만 표시, 속도 제한 없음
}
완화 방법: 다중 인증을 구현하고, 강력한 비밀번호 정책을 시행하며, 안전한 세션 관리를 사용하세요.
8. 소프트웨어 및 데이터 무결성 실패 (Software and Data Integrity Failures)
이 카테고리는 소프트웨어 업데이트에 신뢰할 수 없는 소스를 사용하거나 신뢰할 수 없는 데이터를 역직렬화하는 경우를 포함합니다.
// 취약점: 신뢰할 수 없는 데이터 역직렬화
$data = unserialize($_POST['data']);
완화 방법: 디지털 서명을 확인하고, 무결성 검사를 사용하며, 신뢰할 수 없는 데이터의 역직렬화를 피하세요.
9. 보안 로깅 및 모니터링 실패 (Security Logging and Monitoring Failures)
적절한 로깅이 없으면 침해를 감지할 수 없습니다. 예를 들어, 실패한 로그인 시도를 기록하지 않는 경우입니다.
완화 방법: 보안 관련 이벤트를 로깅하고, 경고를 설정하며, 사고 대응 계획을 수립하세요.
10. 서버 측 요청 위조 (SSRF)
SSRF는 공격자가 서버가 의도하지 않은 위치로 요청을 보내도록 할 수 있을 때 발생합니다.
// 취약점: 검증 없이 사용자 입력에서 URL 가져오기
fetch(req.query.url).then(...)
완화 방법: URL을 검증 및 정리하고, 허용 목록을 사용하며, 서버 권한을 제한하세요.
비교 표
| 위험 | 예시 | 완화 방법 |
|---|---|---|
| 접근 제어 취약점 | URL 조작을 통한 다른 사용자 데이터 접근 | 서버 측 접근 검사 시행 |
| 암호화 실패 | 비밀번호를 평문으로 저장 | 강력한 해싱 및 TLS 사용 |
| 인젝션 | 정리되지 않은 입력을 통한 SQL 인젝션 | 매개변수화된 쿼리 |
| 안전하지 않은 설계 | 비밀번호 복구가 이메일 존재 여부 노출 | 위협 모델링 및 안전한 패턴 |
| 보안 구성 오류 | 프로덕션에서 디버그 모드 켜짐 | 구성 강화 |
| 취약한 구성 요소 | 알려진 CVE가 있는 오래된 라이브러리 | 정기 업데이트 및 종속성 검사 |
| 인증 실패 | 로그인에 속도 제한 없음 | MFA 및 강력한 정책 |
| 무결성 실패 | 신뢰할 수 없는 데이터 역직렬화 | 서명 확인 및 안전하지 않은 역직렬화 회피 |
| 로깅 실패 | 실패한 로그인에 대한 로그 없음 | 로깅 및 모니터링 구현 |
| SSRF | 사용자 제공 URL 가져오기 | URL 검증 및 허용 목록 사용 |
자주 묻는 질문
OWASP Top 10이란 무엇인가요?
OWASP Top 10은 Open Web Application Security Project (OWASP)에서 발행하는 가장 중요한 웹 애플리케이션 보안 위험 목록으로 정기적으로 업데이트됩니다.
OWASP Top 10은 얼마나 자주 업데이트되나요?
새로운 위협과 기술 변화를 반영하기 위해 주기적으로 업데이트됩니다. 마지막 주요 업데이트는 2021년이었습니다.
OWASP Top 10만으로 보안이 충분한가요?
아니요, 시작점일 뿐입니다. 포괄적인 보안 프로그램에는 안전한 코딩 관행, 정기적인 테스트, 지속적인 모니터링이 포함됩니다.
애플리케이션 보안을 더 강화하려면 Nginx 로그 분석기와 같은 도구를 사용하여 서버 로그에서 의심스러운 활동을 모니터링하고 탐지하는 것을 고려하세요.