release: 2026-03-25 (보안 수정 - 프록시 캐시 권한 우회 방지) #31
@ -80,5 +80,8 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"env": {
|
||||||
|
"CLAUDE_BOT_TOKEN": "ac15488ad66463bd5c4e3be1fa6dd5b2743813c5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -142,8 +142,10 @@ public class AuthController {
|
|||||||
})
|
})
|
||||||
@GetMapping("/check")
|
@GetMapping("/check")
|
||||||
public ResponseEntity<Void> checkProxyAuth(HttpServletRequest request, HttpServletResponse response) {
|
public ResponseEntity<Void> checkProxyAuth(HttpServletRequest request, HttpServletResponse response) {
|
||||||
|
String targetUri = request.getHeader("X-Original-URI");
|
||||||
|
|
||||||
String proxyCacheToken = getCookieValue(request, "gc_proxy_auth");
|
String proxyCacheToken = getCookieValue(request, "gc_proxy_auth");
|
||||||
if (jwtTokenProvider.validateProxyCacheToken(proxyCacheToken) != null) {
|
if (jwtTokenProvider.validateProxyCacheToken(proxyCacheToken, targetUri) != null) {
|
||||||
return ResponseEntity.ok().build();
|
return ResponseEntity.ok().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,7 +156,6 @@ public class AuthController {
|
|||||||
|
|
||||||
Long userId = jwtTokenProvider.getUserIdFromToken(sessionToken);
|
Long userId = jwtTokenProvider.getUserIdFromToken(sessionToken);
|
||||||
String email = jwtTokenProvider.getEmailFromToken(sessionToken);
|
String email = jwtTokenProvider.getEmailFromToken(sessionToken);
|
||||||
String targetUri = request.getHeader("X-Original-URI");
|
|
||||||
|
|
||||||
User user = userRepository.findByIdWithRoles(userId).orElse(null);
|
User user = userRepository.findByIdWithRoles(userId).orElse(null);
|
||||||
if (user == null || user.getStatus() != com.gcsc.guide.entity.UserStatus.ACTIVE) {
|
if (user == null || user.getStatus() != com.gcsc.guide.entity.UserStatus.ACTIVE) {
|
||||||
@ -166,7 +167,7 @@ public class AuthController {
|
|||||||
return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
|
return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
String cacheToken = jwtTokenProvider.generateProxyCacheToken(userId);
|
String cacheToken = jwtTokenProvider.generateProxyCacheToken(userId, targetUri);
|
||||||
ResponseCookie cacheCookie = ResponseCookie.from("gc_proxy_auth", cacheToken)
|
ResponseCookie cacheCookie = ResponseCookie.from("gc_proxy_auth", cacheToken)
|
||||||
.path("/")
|
.path("/")
|
||||||
.httpOnly(true)
|
.httpOnly(true)
|
||||||
|
|||||||
@ -68,26 +68,34 @@ public class JwtTokenProvider {
|
|||||||
return expirationMs;
|
return expirationMs;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String generateProxyCacheToken(Long userId) {
|
public String generateProxyCacheToken(Long userId, String targetUri) {
|
||||||
long expiry = Instant.now().plusMillis(expirationMs).getEpochSecond();
|
long expiry = Instant.now().plusMillis(expirationMs).getEpochSecond();
|
||||||
String payload = userId + ":" + expiry;
|
String uriHash = hmacSha256(targetUri != null ? targetUri : "");
|
||||||
|
String payload = userId + ":" + uriHash + ":" + expiry;
|
||||||
String hmac = hmacSha256(payload);
|
String hmac = hmacSha256(payload);
|
||||||
return payload + ":" + hmac;
|
return payload + ":" + hmac;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Long validateProxyCacheToken(String token) {
|
public Long validateProxyCacheToken(String token, String targetUri) {
|
||||||
if (token == null || token.isBlank()) {
|
if (token == null || token.isBlank()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
String[] parts = token.split(":");
|
String[] parts = token.split(":");
|
||||||
if (parts.length != 3) {
|
if (parts.length != 4) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
long userId = Long.parseLong(parts[0]);
|
long userId = Long.parseLong(parts[0]);
|
||||||
long expiry = Long.parseLong(parts[1]);
|
String uriHash = parts[1];
|
||||||
String expectedHmac = hmacSha256(userId + ":" + expiry);
|
long expiry = Long.parseLong(parts[2]);
|
||||||
if (!expectedHmac.equals(parts[2])) {
|
|
||||||
|
String expectedUriHash = hmacSha256(targetUri != null ? targetUri : "");
|
||||||
|
if (!expectedUriHash.equals(uriHash)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String expectedHmac = hmacSha256(userId + ":" + uriHash + ":" + expiry);
|
||||||
|
if (!expectedHmac.equals(parts[3])) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (Instant.now().getEpochSecond() > expiry) {
|
if (Instant.now().getEpochSecond() > expiry) {
|
||||||
|
|||||||
불러오는 중...
Reference in New Issue
Block a user