From 986c6e59b6438f83e022fb2341b67b11bda366e7 Mon Sep 17 00:00:00 2001 From: gyuu04 Date: Tue, 3 Jun 2025 12:26:03 +0900 Subject: [PATCH] Create redirect_uriBypass.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit redirect_uri 우회 탐지 로직 추가 --- .../src/controller/redirect_uriBypass.ts | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 packages/backend/src/controller/redirect_uriBypass.ts diff --git a/packages/backend/src/controller/redirect_uriBypass.ts b/packages/backend/src/controller/redirect_uriBypass.ts new file mode 100644 index 0000000..8b4b436 --- /dev/null +++ b/packages/backend/src/controller/redirect_uriBypass.ts @@ -0,0 +1,40 @@ +import type { Request, Response } from "caido:utils"; + + +export class RedirectBypassController { + isRedirectUri(req: Request): boolean { + const query = req.getQuery(); + + + // redirect_uri 파라미터 정규식으로 추출 + const redirectUriMatch = query.match(/redirect_uri=([^&]+)/i); + if (!redirectUriMatch) return false; + + + // redirect_uri 파라미터의 URL 문자열을 디코딩 + const redirectUri = decodeURIComponent(redirectUriMatch[1]); + + + // 우회 키워드 + const bypassPatterns = [ + "%ff@", "/", "%2f@", "%0a@", "%0d@", "\\", ".evil.com", "@", "%2f..%2f" + ]; + + + return bypassPatterns.some(pattern => redirectUri.includes(pattern)); + } + + + isCodeIssued(res: Response): boolean { + const location = res.getHeader("Location") || ""; + return location.includes("code="); + } + + + test(req: Request, res: Response): string | false { + if (this.isRedirectUri(req) && this.isCodeIssued(res)) { + return "redirect_uri bypass detected"; + } + return false; + } +}