OWASP Top 10:2025. 4๋ ๋ง์ ๊ฐ์ ๋ ์น ๋ณด์ ์ํ ํ์ค. ์๋ก ์ถ๊ฐ๋ ๊ณต๊ธ๋ง·์์ธ ์ฒ๋ฆฌ ํญ๋ชฉ๋ถํฐ 1์ ์ ๊ทผ ์ ์ด๊น์ง, ๋ฐฑ์๋ ๊ฐ๋ฐ์๊ฐ ์์์ผ ํ 10๊ฐ์ง๋ฅผ ์ค์ ๊ณต๊ฒฉ ์์์ ๋์ ์ฝ๋๋ก ์ ๋ฆฌํ๋ค.
๋ค์ด๊ฐ๋ฉฐ
2025๋
11์, OWASP๊ฐ 4๋
๋ง์ Top 10์ ๊ฐ์ ํ๋ค.
OWASP Top 10์ ์น ์ ํ๋ฆฌ์ผ์ด์
๋ณด์ ์ํ์ ๋น๋์ ์ํฅ๋ ๊ธฐ์ค์ผ๋ก ์ถ๋ฆฐ ์ฌ์ค์์ ์
๊ณ ํ์ค ๋ฌธ์๋ค.
2021๋
ํ์ ๊ธฐ์ค์ผ๋ก ์ฝ๋๋ฅผ ์ง์จ ์ฌ๋์ด๋ผ๋ฉด, ์ด๋ฒ์ ๋ฐ๋ ํญ๋ชฉ๋ค์ ํ ๋ฒ ์ง๊ณ ๋์ด๊ฐ ํ์๊ฐ ์๋ค.
๋ณด์์ "๋์ค์ ๋ถ์ด๋ ๊ธฐ๋ฅ"์ด ์๋๋ผ ์ค๊ณ ๋จ๊ณ๋ถํฐ ๊ณ ๋ คํ๋ ๊ธฐ๋ณธ๊ฐ์ด๋ค. OWASP Top 10์ ๊ทธ ์ถ๋ฐ์ ์ด๋ค.
์ด ๊ธ์์๋ 2025๋
ํ 10๊ฐ์ง ํญ๋ชฉ์ ๋ฌด์์ด ๋ฐ๋์๋์ง์ ํจ๊ป, ๊ฐ ํญ๋ชฉ์ ์ค์ ๊ณต๊ฒฉ ์์ + ๋์ ๋ฐฉ๋ฒ์ ์ฝ๋๋ก ์ ๋ฆฌํ๋ค.
์์๋ Java/Spring ๊ธฐ์ค์ด๋ค.
์ฐธ๊ณ — "2023๋ ์๋ ๊ฐ์ ๋์ง ์์๋?"
ํท๊ฐ๋ฆฌ๊ธฐ ์ฌ์ด๋ฐ, OWASP์๋ ์ฌ๋ฌ ์ข ๋ฅ์ Top 10์ด ์๋ค.
์ด ๊ธ์ด ๋ค๋ฃจ๋ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ฉ OWASP Top 10์ 2017 → 2021 → 2025 ์์ผ๋ก ๊ฐ์ ๋๊ณ ,
๊ทธ ์ฌ์ด(2023๋ )์ ๋์จ ๊ฒ์ API ์ ์ฉ์ธ OWASP API Security Top 10 2023์ผ๋ก ๋ณ๊ฐ์ ๋ฌธ์๋ค.
API ๋ฒ์ ์ ๋ณ๋ ๊ธ์์ ๋ค๋ฃฌ๋ค.
2021 → 2025, ๋ฌด์์ด ๋ฐ๋์๋
์ด๋ฒ ๊ฐ์ ์ ํต์ฌ์ "์ฆ์์ด ์๋๋ผ ๊ทผ๋ณธ ์์ธ"์ ์ด์ ์ ๋ง์ถ ๊ฒ์ด๋ค. ํฐ ๋ณํ๋ ์ธ ๊ฐ์ง๋ค.
- ์ ๊ท 2๊ฐ: A03 ์ํํธ์จ์ด ๊ณต๊ธ๋ง ์คํจ, A10 ์์ธ ์ํฉ ์ฒ๋ฆฌ ๋ฏธํก
- ํตํฉ: ๊ธฐ์กด ๋จ๋ ํญ๋ชฉ์ด๋ SSRF(์๋ฒ ์ธก ์์ฒญ ์์กฐ)๊ฐ A01 ์ ๊ทผ ์ ์ด๋ก ํก์๋จ
- ํ์ฅ: ๊ธฐ์กด "์ทจ์ฝํ๊ณ ์ค๋๋ ์ปดํฌ๋ํธ"๊ฐ "์ํํธ์จ์ด ๊ณต๊ธ๋ง ์คํจ"๋ก ๋ฒ์ ํ๋
์ ์ฒด ์์๋ ๋ค์๊ณผ ๊ฐ๋ค.
| ์์ | ํญ๋ชฉ | 2021 ๋๋น |
| A01 | Broken Access Control (์ ๊ทผ ์ ์ด ์คํจ) | 1์ ์ ์ง (+SSRF ํก์) |
| A02 | Security Misconfiguration (๋ณด์ ์ค์ ์ค๋ฅ) | 5์ → 2์ โฒ |
| A03 | Software Supply Chain Failures (๊ณต๊ธ๋ง ์คํจ) | ํ์ฅ โฒ |
| A04 | Cryptographic Failures (์ํธํ ์คํจ) | 2์ → 4์ โผ |
| A05 | Injection (์ธ์ ์ ) | 3์ → 5์ โผ |
| A06 | Insecure Design (์์ ํ์ง ์์ ์ค๊ณ) | 4์ → 6์ โผ |
| A07 | Authentication Failures (์ธ์ฆ ์คํจ) | 7์ ์ ์ง |
| A08 | Software or Data Integrity Failures (๋ฌด๊ฒฐ์ฑ ์คํจ) | 8์ ์ ์ง |
| A09 | Security Logging & Alerting Failures (๋ก๊น ·์๋ฆผ ์คํจ) | 9์ ์ ์ง |
| A10 | Mishandling of Exceptional Conditions (์์ธ ์ฒ๋ฆฌ ๋ฏธํก) | ์ ๊ท โ |
A01. Broken Access Control — ์ ๊ทผ ์ ์ด ์คํจ
3๋ ์ฐ์ 1์. ๊ฐ์ฅ ํํ๊ณ , ๊ฐ์ฅ ์ํํ๋ค. ์ธ์ฆ(๋ก๊ทธ์ธ)์ ๋์ง๋ง ์ธ๊ฐ(๊ถํ)๊ฐ ๋ถ์คํ ๊ฒฝ์ฐ๋ค.
// ์ทจ์ฝ: ๋ณธ์ธ ํ์ธ ์์ด ํ๋ผ๋ฏธํฐ์ id๋ฅผ ๊ทธ๋๋ก ์ ๋ขฐ
@GetMapping("/api/orders/{orderId}")
public Order getOrder(@PathVariable Long orderId) {
return orderRepository.findById(orderId).orElseThrow();
// orderId๋ง ๋ฐ๊พธ๋ฉด ๋จ์ ์ฃผ๋ฌธ๋ ์กฐํ๋๋ค (IDOR ์ทจ์ฝ์ )
}
orderId=1001์ 1002๋ก ๋ฐ๊พธ๋ฉด ๋จ์ ์ฃผ๋ฌธ์ด ๋ณด์ธ๋ค. ์ด๊ฑธ IDOR(Insecure Direct Object Reference)๋ผ๊ณ ํ๋ค.
// ๋์: ๋ฆฌ์์ค์ ์์ ์๊ฐ ์์ฒญ์ ๋ณธ์ธ์ธ์ง ๊ฒ์ฆ
@GetMapping("/api/orders/{orderId}")
public Order getOrder(@PathVariable Long orderId,
@AuthenticationPrincipal UserDetails user) {
Order order = orderRepository.findById(orderId).orElseThrow();
if (!order.getUserId().equals(user.getId())) {
throw new AccessDeniedException("๋ณธ์ธ์ ์ฃผ๋ฌธ๋ง ์กฐํํ ์ ์์ต๋๋ค");
}
return order;
}
๋์ ์์ฝ: ๋ชจ๋ ๋ฆฌ์์ค ์ ๊ทผ์ ์์ ๊ถ·๊ถํ์ ๊ฒ์ฆํ๋ค. ๊ธฐ๋ณธ์ "๊ฑฐ๋ถ", ๋ช
์์ ์ผ๋ก ํ์ฉ๋ ๊ฒ๋ง ํต๊ณผ์ํจ๋ค(deny by default).
์ด๋ฒ ํ๋ถํฐ SSRF๋ ์ด ์นดํ
๊ณ ๋ฆฌ์ ํฌํจ๋๋ฏ๋ก, ์ธ๋ถ URL์ ๋ฐ์ ์๋ฒ๊ฐ ์์ฒญ์ ๋ณด๋ผ ๋๋ ๋ด๋ถ๋ง·๋ฉํ๋ฐ์ดํฐ ์ฃผ์(์: 196.254.169.254)๋ฅผ ์ฐจ๋จํด์ผ ํ๋ค.
A02. Security Misconfiguration — ๋ณด์ ์ค์ ์ค๋ฅ
5์์์ 2์๋ก ํฌ๊ฒ ์ฌ๋๋ค. ์ค์ ๊ธฐ๋ฐ ๋์์ด ๋๋ฉด์ misconfiguration๋ ํจ๊ป ๋์๋ค.
๊ธฐ๋ณธ ๋น๋ฐ๋ฒํธ, ๋ถํ์ํ๊ฒ ์ด๋ฆฐ ๋๋ฒ๊ทธ ๋ชจ๋, ๊ณผ๋ํ ์๋ฌ ๋
ธ์ถ ๋ฑ์ด ํด๋น๋๋ค.
# ์ทจ์ฝ: ์ด์ ํ๊ฒฝ์์ ์์ธ ์๋ฌ์ ๋๋ฒ๊ทธ ๋
ธ์ถ
server:
error:
include-stacktrace: always # ์คํํธ๋ ์ด์ค๊ฐ ์ฌ์ฉ์์๊ฒ ๋
ธ์ถ
spring:
h2:
console:
enabled: true # ์ด์์ H2 ์ฝ์์ด ์ด๋ ค ์์
# ๋์: ์ด์ ํ๋กํ์ผ์์๋ ์ต์ ์ ๋ณด๋ง
server:
error:
include-stacktrace: never
include-message: never
spring:
h2:
console:
enabled: false
๋์ ์์ฝ: ์ด์/๊ฐ๋ฐ ์ค์ ์ ํ๋กํ์ผ๋ก ๋ถ๋ฆฌํ๊ณ , ๊ธฐ๋ณธ ๊ณ์ ·์ํ ํ์ด์ง·๋ถํ์ํ ํฌํธ๋ฅผ ์ ๊ฑฐํ๋ค.
๋ณด์ ํค๋(HSTS, X-Content-Type-Options ๋ฑ)๋ฅผ ๊ธฐ๋ณธ ์ ์ฉํ๋ค.
A03. Software Supply Chain Failures — ๊ณต๊ธ๋ง ์คํจ (์ ๊ท)
์ด๋ฒ์ ๊ฐ์ฅ ์ฃผ๋ชฉ๋ฐ์ ์ ๊ท ํญ๋ชฉ. ๋ด๊ฐ ์ง ์ฝ๋๊ฐ ์๋๋ผ ๋ด๊ฐ ๊ฐ์ ธ๋ค ์ด ์์กด์ฑ์์ ์ฌ๊ณ ๊ฐ ๋๋ค.
์คํ์์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ, ๋น๋ ์์คํ
, ๋ฐฐํฌ ์ธํ๋ผ ์ ์ฒด๊ฐ ๊ณต๊ฒฉ ํ๋ฉด์ด๋ค. Log4Shell์ด ๋ํ์ ์ฌ๋ก๋ค.
# ๋์ 1: ์์กด์ฑ ์ทจ์ฝ์ ์ค์บ์ ๋น๋์ ํฌํจ
./gradlew dependencyCheckAnalyze # OWASP Dependency-Check
# ๋์ 2: ์๋ ค์ง ์ทจ์ฝ์ ํ์ธ
npm audit
// ๋์ 3: ์์กด์ฑ ๋ฒ์ ๊ณ ์ + ์ถ์ฒ ๊ฒ์ฆ
dependencies {
implementation("org.springframework.boot:spring-boot-starter-web:3.4.1")
// ๋ฒ์ ์ ๋ช
์์ ์ผ๋ก ๊ณ ์ (latest, + ๊ฐ์ ๋์ ๋ฒ์ ๊ธ์ง)
}
๋์ ์์ฝ: ์์กด์ฑ ๋ฒ์ ์ ๊ณ ์ ํ๊ณ , CI์ ์ทจ์ฝ์ ์ค์บ(Dependency-Check, Snyk, Dependabot)์ ๋ฃ๋๋ค.
SBOM(์ํํธ์จ์ด ์์ฌ ๋ช
์ธ์)์ ๊ด๋ฆฌํด ๋ฌด์์ ์ฐ๊ณ ์๋์ง ์ถ์ ํ๋ค.
A04. Cryptographic Failures — ์ํธํ ์คํจ
๋ฏผ๊ฐ ๋ฐ์ดํฐ๋ฅผ ํ๋ฌธ์ผ๋ก ์ ์ฅํ๊ฑฐ๋, ์ฝํ ์๊ณ ๋ฆฌ์ฆ์ ์ฐ๋ ๊ฒฝ์ฐ๋ค. ๋น๋ฐ๋ฒํธ๋ฅผ ๋จ์ ํด์ฑํ๋ ๊ฒ ๋ํ์ ์ค์๋ค.
// ์ทจ์ฝ: SHA-256 ๋จ์ ํด์ฑ (๋ ์ธ๋ณด์ฐ ํ
์ด๋ธ์ ์ทจ์ฝ, ๋๋ฌด ๋น ๋ฆ)
String hashed = DigestUtils.sha256Hex(password);
// ๋์: bcrypt ๊ฐ์ ๋๋ฆฐ ํด์ + ์๋ ์ํธ
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(); // ์ํธ ์๋ ์์ฑ, ์๋์ ์ผ๋ก ๋๋ฆผ
}
// ์ฌ์ฉ
String hashed = passwordEncoder.encode(rawPassword);
boolean matches = passwordEncoder.matches(rawPassword, hashed);
๋์ ์์ฝ: ๋น๋ฐ๋ฒํธ๋ bcrypt/Argon2 ๊ฐ์ ์ ์ํ ํด์๋ก ์ ์ฅํ๋ค.
์ ์ก ๊ตฌ๊ฐ์ TLS, ์ ์ฅ ๋ฐ์ดํฐ๋ AES-256์ผ๋ก ์ํธํํ๋ค.
MD5·SHA-1·DES ๊ฐ์ ์ฝํ ์๊ณ ๋ฆฌ์ฆ์ ์ฐ์ง ์๋๋ค.
A05. Injection — ์ธ์ ์
SQL Injection, XSS ๋ฑ์ ํฌํจํ๋ค. ์ฌ์ฉ์ ์ ๋ ฅ์ ์ฝ๋/์ฟผ๋ฆฌ์ ์ผ๋ถ๋ก ์ ๋ขฐํ ๋ ๋ฐ์ํ๋ค.
// ์ทจ์ฝ: ๋ฌธ์์ด ๊ฒฐํฉ์ผ๋ก ์ฟผ๋ฆฌ ์์ฑ
String sql = "SELECT * FROM users WHERE email = '" + email + "'";
// email์ "' OR '1'='1" ๋ฅผ ๋ฃ์ผ๋ฉด ์ ์ฒด ํ์ด ๋
ธ์ถ๋๋ค
// ๋์: ํ๋ผ๋ฏธํฐ ๋ฐ์ธ๋ฉ (PreparedStatement / JPA)
@Query("SELECT u FROM User u WHERE u.email = :email")
User findByEmail(@Param("email") String email); // ๊ฐ์ผ๋ก๋ง ์ฒ๋ฆฌ๋จ
๋์ ์์ฝ: ์ฟผ๋ฆฌ๋ ํญ์ ํ๋ผ๋ฏธํฐ ๋ฐ์ธ๋ฉ์ผ๋ก ๋ง๋ ๋ค.
๋ฌธ์์ด ๊ฒฐํฉ ๊ธ์ง. ORM์ ์จ๋ ๋ค์ดํฐ๋ธ ์ฟผ๋ฆฌ·JPQL ๋์ ๊ฒฐํฉ์์ ๋ซ๋ฆด ์ ์์ผ๋ ์ฃผ์ํ๋ค. XSS๋ ์ถ๋ ฅ ์ ์ด์ค์ผ์ดํ ์ฒ๋ฆฌํ๋ค.
A06. Insecure Design — ์์ ํ์ง ์์ ์ค๊ณ
์ฝ๋ ๋ฒ๊ทธ๊ฐ ์๋๋ผ ์ค๊ณ ์์ฒด์ ๊ฒฐํจ์ด๋ค. ์๋ฅผ ๋ค์ด ๋น๋ฐ๋ฒํธ ์ฌ์ค์ ์ ํ์ ์ ํ์ด ์์ผ๋ฉด, ๊ตฌํ์ด ์๋ฒฝํด๋ ๋ฌด์ฐจ๋ณ ๋์ ์ ๋ซ๋ฆฐ๋ค.
// ๋์ ์: ๋ฏผ๊ฐํ ๊ธฐ๋ฅ์ ๋น์จ ์ ํ(rate limit) ์ค๊ณ ๋ฐ์
@RateLimiter(name = "passwordReset", fallbackMethod = "tooManyRequests")
public void requestPasswordReset(String email) {
// ๋ถ๋น Nํ๋ก ์ ํ → ๋ฌด์ฐจ๋ณ ์๋ ์ฐจ๋จ
}
๋์ ์์ฝ: ์ค๊ณ ๋จ๊ณ์์ ์ํ ๋ชจ๋ธ๋ง(threat modeling)์ ํ๋ค.
"์ด ๊ธฐ๋ฅ์ด ์
์ฉ๋๋ฉด ์ด๋ป๊ฒ ๋ ๊น"๋ฅผ ๋จผ์ ๋ฌป๊ณ , ๋น์จ ์ ํ·๋ค๋จ๊ณ ์ธ์ฆ·์ต์ ๊ถํ์ ์ค๊ณ์ ํฌํจํ๋ค.
A07. Authentication Failures — ์ธ์ฆ ์คํจ
์ฝํ ๋น๋ฐ๋ฒํธ ํ์ฉ, ์ธ์ ๊ด๋ฆฌ ๋ฏธํก, ๋ฌด์ฐจ๋ณ ๋์ ๋ฐฉ์ด ๋ถ์ฌ ๋ฑ. ์ด์ ๊ธ์ JWT ์ธ์ฆ๊ณผ๋ ์ง๊ฒฐ๋๋ค.
// ๋์: ๋ก๊ทธ์ธ ์คํจ ํ์ ์ ํ + ๊ณ์ ์ ๊ธ
public void login(String email, String password) {
if (loginAttemptService.isBlocked(email)) {
throw new LockedException("๋ก๊ทธ์ธ ์๋๊ฐ ๋๋ฌด ๋ง์ต๋๋ค. ์ ์ ํ ๋ค์ ์๋ํ์ธ์");
}
if (!passwordEncoder.matches(password, user.getPassword())) {
loginAttemptService.recordFailure(email); // ์คํจ ์นด์ดํธ
throw new BadCredentialsException("์ธ์ฆ ์คํจ");
}
loginAttemptService.reset(email);
}
๋์ ์์ฝ: ๋ค๋จ๊ณ ์ธ์ฆ(MFA)์ ์ ๊ณตํ๊ณ , ๋ก๊ทธ์ธ ์คํจ ์ ํ·์ธ์
ํ์์์·์์ ํ ํ ํฐ ๊ด๋ฆฌ๋ฅผ ์ ์ฉํ๋ค.
๊ฒ์ฆ๋ ์ธ์ฆ ํ๋ ์์ํฌ(Spring Security ๋ฑ)๋ฅผ ์ฐ๋ ๊ฒ์ด ์ง์ ๊ตฌํ๋ณด๋ค ์์ ํ๋ค.
A08. Software or Data Integrity Failures — ๋ฌด๊ฒฐ์ฑ ์คํจ
๊ฒ์ฆ๋์ง ์์ ์ถ์ฒ์ ์ฝ๋·๋ฐ์ดํฐ๋ฅผ ์ ๋ขฐํ ๋ ๋ฐ์ํ๋ค.
์๋ช
๊ฒ์ฆ ์๋ ์๋ ์
๋ฐ์ดํธ, ์ ๋ขฐํ ์ ์๋ ๋ฐ์ดํฐ์ ์ญ์ง๋ ฌํ ๋ฑ์ด ํด๋น๋๋ค.
// ์ทจ์ฝ: ์ ๋ขฐํ ์ ์๋ ๋ฐ์ดํฐ๋ฅผ ๊ทธ๋๋ก ์ญ์ง๋ ฌํ
ObjectInputStream in = new ObjectInputStream(untrustedInput);
Object obj = in.readObject(); // ์ญ์ง๋ ฌํ ๊ฐ์ ฏ ๊ณต๊ฒฉ์ ์ทจ์ฝ
๋์ ์์ฝ: ์ธ๋ถ ๋ฐ์ดํฐ๋ ์ญ์ง๋ ฌํํ์ง ์๊ฑฐ๋, ํ์ฉ ๋ชฉ๋ก(allowlist) ๊ธฐ๋ฐ์ผ๋ก๋ง ์ฒ๋ฆฌํ๋ค.
์
๋ฐ์ดํธ·์ํฐํฉํธ๋ ๋์งํธ ์๋ช
์ผ๋ก ๋ฌด๊ฒฐ์ฑ์ ๊ฒ์ฆํ๋ค. CI/CD ํ์ดํ๋ผ์ธ์ ์ ๊ทผ ๊ถํ๋ ํต์ ํ๋ค.
A09. Security Logging & Alerting Failures — ๋ก๊น ·์๋ฆผ ์คํจ
์ด๋ฒ์ ์ด๋ฆ์ด "๋ชจ๋ํฐ๋ง"์์ "์๋ฆผ"์ผ๋ก ๋ฐ๋์๋ค.
๋ก๊ทธ๋ง ์๊ณ ์๋ฆผ์ด ์์ผ๋ฉด ์นจํด๋ฅผ ์ ๋ ๋ฐ๊ฒฌํ์ง ๋ชปํ๋ค๋ ์ ์ ๊ฐ์กฐํ ๊ฒ์ด๋ค.
// ๋์: ๋ณด์ ์ด๋ฒคํธ๋ฅผ ๊ตฌ์กฐํํด์ ๊ธฐ๋ก + ์๋ฆผ ์ฐ๋
log.warn("AUTH_FAILURE user={} ip={} attempts={}",
email, clientIp, attemptCount);
// ์๊ณ์น ์ด๊ณผ ์ Slack/PagerDuty๋ก ์๋ฆผ ๋ฐ์กํ๋๋ก ์ฐ๋
๋์ ์์ฝ: ๋ก๊ทธ์ธ ์คํจ, ๊ถํ ๊ฑฐ๋ถ, ์
๋ ฅ ๊ฒ์ฆ ์คํจ ๊ฐ์ ๋ณด์ ์ด๋ฒคํธ๋ฅผ ๊ธฐ๋กํ๋ค.
๋จ, ๋ก๊ทธ์ ๋น๋ฐ๋ฒํธ·ํ ํฐ·๊ฐ์ธ์ ๋ณด๋ฅผ ๋จ๊ธฐ์ง ์๋๋ค.
๊ทธ๋ฆฌ๊ณ ํต์ฌ์ ์๊ณ์น ์ด๊ณผ ์ ์ค์ ๋ก ์๋ฆผ์ด ๊ฐ๋๋ก ์ฐ๋ํ๋ ๊ฒ์ด๋ค.
A10. Mishandling of Exceptional Conditions — ์์ธ ์ฒ๋ฆฌ ๋ฏธํก (์ ๊ท)
์ด๋ฒ์ ์๋ก ์ถ๊ฐ๋ ํญ๋ชฉ. ์๋ชป๋ ์๋ฌ ์ฒ๋ฆฌ, ๋ ผ๋ฆฌ ์ค๋ฅ, "์คํจ ์ ์ด๋ฆผ(fail open)" ๊ฐ์ ๋น์ ์ ์ํฉ ๋์ ๊ฒฐํจ์ด๋ค.
// ์ทจ์ฝ: ๊ถํ ๊ฒ์ฌ ์ค ์์ธ๊ฐ ๋๋ฉด ํต๊ณผ์์ผ ๋ฒ๋ฆผ (fail open)
public boolean hasPermission(User user, Resource res) {
try {
return permissionService.check(user, res);
} catch (Exception e) {
return true; // ์์ธ ์ ํ์ฉ → ์น๋ช
์
}
}
// ๋์: ์คํจ ์ ์์ ํ ์ชฝ์ผ๋ก ๋ซ๋๋ค (fail secure)
public boolean hasPermission(User user, Resource res) {
try {
return permissionService.check(user, res);
} catch (Exception e) {
log.error("๊ถํ ๊ฒ์ฌ ์คํจ, ์ ๊ทผ ๊ฑฐ๋ถ ์ฒ๋ฆฌ", e);
return false; // ์์ธ ์ ๊ฑฐ๋ถ (fail closed)
}
}
๋์ ์์ฝ: ๋ณด์ ๊ฒฐ์ ์ ์์ธ๊ฐ ๋๋ฉด ๊ฑฐ๋ถ ์ชฝ์ผ๋ก ๋ซ๋๋ค(fail secure).
์๋ฌ ๋ฉ์์ง์ ๋ด๋ถ ์ ๋ณด๋ฅผ ๋
ธ์ถํ์ง ์๊ณ , ๋ชจ๋ ๋น์ ์ ๊ฒฝ๋ก๋ฅผ ๋ช
์์ ์ผ๋ก ์ฒ๋ฆฌํ๋ค.
๋ง์น๋ฉฐ
OWASP Top 10:2025์ ๋ฉ์์ง๋ ๋ถ๋ช
ํ๋ค. ์ฆ์์ด ์๋๋ผ ๊ทผ๋ณธ ์์ธ์ ๋ณด๋ผ.
๊ณต๊ธ๋ง ์คํจ์ ์์ธ ์ฒ๋ฆฌ ๋ฏธํก์ด ์๋ก ๋ค์ด์จ ๊ฒ๋, ๊ฐ๋ณ ๋ฒ๊ทธ๋ณด๋ค "์ค๊ณ์ ํ๋ก์ธ์ค ์ฐจ์์ ๊ฒฐํจ"์ด ๋ ์ํํด์ก๋ค๋ ์ ํธ๋ค.
10๊ฐ์ง๋ฅผ ๋ค ํ ๋ฒ์ ์ ์ฉํ ํ์๋ ์๋ค. ์ฐ์ ์์๋ ๋ถ๋ช
ํ๋ค.
์ ๊ทผ ์ ์ด(A01), ๋ณด์ ์ค์ (A02), ์์กด์ฑ ๊ด๋ฆฌ(A03)๋ถํฐ ์ ๊ฒํ๋ ๊ฒ ํจ์จ์ ์ด๋ค.
์ด ์
์ด ์ง๊ธ ๊ฐ์ฅ ํํ๊ฒ ๋ซ๋ฆฌ๋ ์ง์ ์ด๋ค.
๋ณด์์ ํ ๋ฒ ์ง๊ณ ๋๋๋ ๊ฒ ์๋๋ผ ๊ณ์ ์ ๊ฒํ๋ ๊ณผ์ ์ด๋ค.
์ ๊ธฐ๋ฅ์ ์ถ๊ฐํ ๋๋ง๋ค "์ด๊ฒ ์
์ฉ๋๋ฉด ์ด๋ป๊ฒ ๋ ๊น"๋ฅผ ํ ๋ฒ์ฉ ๋ ์ฌ๋ฆฌ๋ ์ต๊ด์ด, ๊ทธ ์ด๋ค ๋๊ตฌ๋ณด๋ค ํจ๊ณผ์ ์ธ ๋ฐฉ์ด๋ค.
์ฐธ๊ณ ์ถ์ฒ
- OWASP Top 10:2025 ๊ณต์ — https://owasp.org/Top10/2025/
- OWASP Cheat Sheet Series — https://cheatsheetseries.owasp.org/
- Spring Security Reference — https://docs.spring.io/spring-security/reference/
'๐ก๏ธ Security Notes' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
| XSS์ CSRF โ ํท๊ฐ๋ฆฌ๋ ๋ ๊ณต๊ฒฉ, ๋ฌด์์ด ๋ค๋ฅธ๊ฐ (0) | 2026.06.08 |
|---|---|
| OWASP API Security Top 10(2023) (0) | 2026.06.02 |