This commit is contained in:
sultanofdisco 2025-06-07 04:50:31 +00:00 committed by GitHub
commit 4dd57745d8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 52 additions and 30 deletions

View file

@ -1,29 +1,51 @@
import type { Request, Response } from "caido:utils"; import type { Request, Response } from "caido:utils";
import { TokenLeakCheck } from "./tokenLeakCheck";
export class NonceCheckController{ export class NonceCheckController {
/** /**
* OIDC(OpenID Connect) * OIDC (OAuth 2.0 )
*/ */
public static isOidcFlow(req: Request, res: Response): boolean {
public static isOidcFlow(req: Request, res:Response): boolean { const url = req.getUrl();
if(TokenLeakCheck.extractIdToken(req, res)) { const query = req.getQuery();
return true; const location = res.getHeader("Location");
} const contentType = res.getHeader("Content-Type");
return false;
// 1⃣ Authorization 요청: scope=openid 포함
if (url.includes("/authorize") && /response_type=/.test(query) && (/scope=openid/.test(query)) ){
return true;
} }
// 2⃣ Token 응답: id_token 필드 포함
public static isNonceCheckRequest(req: Request): boolean { if (contentType?.includes("application/json")) {
const id_token = TokenLeakCheck.decodeIdToken(req); const body = res.getBody();
const bodyStr = typeof body === "string" ? body : body?.toString?.() ?? "";
// 1. nonce 파라미터가 포함된 요청인지 확인 if (bodyStr && /id_token/.test(bodyStr)) {
if (id_token && id_token.includes("nonce=")) { return true;
return true; }
}
return false;
} }
// 3⃣ Redirect 응답: Location 헤더에 id_token 포함
if (
(res.getCode() === 302 || res.getCode() === 303) &&
location &&
/id_token=/.test(Array.isArray(location) ? location[0] ?? "" : location ?? "")
) {
return true;
}
// 4⃣ Authorization 요청 + nonce 파라미터 포함
if (url.includes("/authorize") && /nonce=/.test(query)) {
return true;
}
return false;
}
} }

View file

@ -6,7 +6,7 @@ import { CsrfCheck } from "./controller/csrfCheck";
import { PKCECheck } from "./controller/PKCECheck"; import { PKCECheck } from "./controller/PKCECheck";
import { AccessTokenLeakController } from "./controller/accessTokenDetector"; import { AccessTokenLeakController } from "./controller/accessTokenDetector";
import { ScopeDetection } from "./controller/scopeDetection"; import { ScopeDetection } from "./controller/scopeDetection";
// import { NonceCheckController } from "./controller/nonceCheck"; import { NonceCheckController } from "./controller/nonceCheck";
import { RedirectBypassController } from "./controller/redirect_uriBypass"; import { RedirectBypassController } from "./controller/redirect_uriBypass";
export type API = DefineAPI<{}>; export type API = DefineAPI<{}>;
@ -26,14 +26,14 @@ export function init(sdk: SDK<API>) {
await ScopeDetectionController.scan(sdk, req.getUrl()); await ScopeDetectionController.scan(sdk, req.getUrl());
await redirectBypassController.testAsync(sdk, req, res); await redirectBypassController.testAsync(sdk, req, res);
// if (NonceCheckController.isOidcFlow(req, res)) { if (NonceCheckController.isOidcFlow(req, res)) {
// await sdk.findings.create({ await sdk.findings.create({
// title: "OIDC Flow Detected", title: "OIDC Flow Detected",
// description: "The request appears to be part of an OIDC flow.", description: "The request appears to be part of an OIDC flow.",
// request: req, request: req,
// reporter: "", reporter: "",
// }); });
// } }
}); });
sdk.events.onInterceptRequest(async (sdk, req: Request) => { sdk.events.onInterceptRequest(async (sdk, req: Request) => {