Compare commits
5 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1a9d227fe6 | ||
|
|
dfa5392038 | ||
|
|
2e400517a8 | ||
|
|
1736debae1 | ||
|
|
e7de3ee4a7 |
2 changed files with 52 additions and 30 deletions
|
|
@ -1,29 +1,51 @@
|
|||
import type { Request, Response } from "caido:utils";
|
||||
import { TokenLeakCheck } from "./tokenLeakCheck";
|
||||
|
||||
export class NonceCheckController{
|
||||
/**
|
||||
* 응답이 OIDC(OpenID Connect) 플로우인지 확인하는 메서드
|
||||
*/
|
||||
export class NonceCheckController {
|
||||
/**
|
||||
* OIDC 플로우 탐지 로직 (OAuth 2.0과 구분)
|
||||
*/
|
||||
public static isOidcFlow(req: Request, res: Response): boolean {
|
||||
const url = req.getUrl();
|
||||
const query = req.getQuery();
|
||||
const location = res.getHeader("Location");
|
||||
const contentType = res.getHeader("Content-Type");
|
||||
|
||||
public static isOidcFlow(req: Request, res:Response): boolean {
|
||||
if(TokenLeakCheck.extractIdToken(req, res)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
// 1️⃣ Authorization 요청: scope=openid 포함
|
||||
if (url.includes("/authorize") && /response_type=/.test(query) && (/scope=openid/.test(query)) ){
|
||||
return true;
|
||||
}
|
||||
|
||||
// 2️⃣ Token 응답: id_token 필드 포함
|
||||
if (contentType?.includes("application/json")) {
|
||||
const body = res.getBody();
|
||||
const bodyStr = typeof body === "string" ? body : body?.toString?.() ?? "";
|
||||
if (bodyStr && /id_token/.test(bodyStr)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
||||
public static isNonceCheckRequest(req: Request): boolean {
|
||||
const id_token = TokenLeakCheck.decodeIdToken(req);
|
||||
|
||||
// 1. nonce 파라미터가 포함된 요청인지 확인
|
||||
if (id_token && id_token.includes("nonce=")) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import { CsrfCheck } from "./controller/csrfCheck";
|
|||
import { PKCECheck } from "./controller/PKCECheck";
|
||||
import { AccessTokenLeakController } from "./controller/accessTokenDetector";
|
||||
import { ScopeDetection } from "./controller/scopeDetection";
|
||||
// import { NonceCheckController } from "./controller/nonceCheck";
|
||||
import { NonceCheckController } from "./controller/nonceCheck";
|
||||
import { RedirectBypassController } from "./controller/redirect_uriBypass";
|
||||
|
||||
export type API = DefineAPI<{}>;
|
||||
|
|
@ -26,14 +26,14 @@ export function init(sdk: SDK<API>) {
|
|||
await ScopeDetectionController.scan(sdk, req.getUrl());
|
||||
await redirectBypassController.testAsync(sdk, req, res);
|
||||
|
||||
// if (NonceCheckController.isOidcFlow(req, res)) {
|
||||
// await sdk.findings.create({
|
||||
// title: "OIDC Flow Detected",
|
||||
// description: "The request appears to be part of an OIDC flow.",
|
||||
// request: req,
|
||||
// reporter: "",
|
||||
// });
|
||||
// }
|
||||
if (NonceCheckController.isOidcFlow(req, res)) {
|
||||
await sdk.findings.create({
|
||||
title: "OIDC Flow Detected",
|
||||
description: "The request appears to be part of an OIDC flow.",
|
||||
request: req,
|
||||
reporter: "",
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
sdk.events.onInterceptRequest(async (sdk, req: Request) => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue