Compare commits
4 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5c6d9cb600 | ||
|
|
d3a0e8ae84 | ||
|
|
ff6b4f02f8 | ||
|
|
b32d4e02af |
2 changed files with 53 additions and 11 deletions
33
packages/backend/src/controller/clientsecretCheck.ts
Normal file
33
packages/backend/src/controller/clientsecretCheck.ts
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
import type { SDK } from "caido:plugin";
|
||||||
|
import type { Request } from "caido:utils";
|
||||||
|
|
||||||
|
export class ClientSecretController {
|
||||||
|
test(req: Request): boolean {
|
||||||
|
const query = req.getQuery() ?? ""; /* URL에서 검사 */
|
||||||
|
|
||||||
|
const bodyRaw = req.getBody(); /* BODY 에서 검사 */
|
||||||
|
const body = typeof bodyRaw === "string" ? bodyRaw : Array.isArray(bodyRaw) ? bodyRaw.join("&") : "";
|
||||||
|
|
||||||
|
const authRaw = req.getHeader("authorization"); /* authz 헤더 에서 검사 */
|
||||||
|
const auth = typeof authRaw === "string" ? authRaw : Array.isArray(authRaw) ? authRaw.join(" ") : "";
|
||||||
|
|
||||||
|
return (
|
||||||
|
query.includes("client_secret=") ||
|
||||||
|
body.includes("client_secret=") ||
|
||||||
|
auth.toLowerCase().startsWith("basic Y2xpZW50X3NlY3JldA")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async report(sdk: SDK, req: Request): Promise<void> {
|
||||||
|
const url = req.getUrl();
|
||||||
|
|
||||||
|
await sdk.findings.create({
|
||||||
|
title: "Exposed client_secret",
|
||||||
|
description: `The request to \`${url}\` contains a potential exposure of the OAuth2 \`client_secret\`.`,
|
||||||
|
request: req,
|
||||||
|
reporter: "Client_Secret_Finder",
|
||||||
|
dedupeKey: "client_secret_exposure"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -6,7 +6,8 @@ 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 { ClientSecretController } from "./controller/clientsecretCheck";
|
||||||
|
|
||||||
export type API = DefineAPI<{}>;
|
export type API = DefineAPI<{}>;
|
||||||
|
|
||||||
|
|
@ -16,7 +17,8 @@ const csrfCheck = new CsrfCheck();
|
||||||
const pkceCheckController = new PKCECheck();
|
const pkceCheckController = new PKCECheck();
|
||||||
const tokenCheck = new AccessTokenLeakController();
|
const tokenCheck = new AccessTokenLeakController();
|
||||||
const ScopeDetectionController = new ScopeDetection();
|
const ScopeDetectionController = new ScopeDetection();
|
||||||
const nonceCheckController = new NonceCheckController();
|
// const nonceCheckController = new NonceCheckController();
|
||||||
|
const clientSecretController = new ClientSecretController();
|
||||||
|
|
||||||
export function init(sdk: SDK<API>) {
|
export function init(sdk: SDK<API>) {
|
||||||
sdk.events.onInterceptResponse(async (sdk, req: Request, res: Response) => {
|
sdk.events.onInterceptResponse(async (sdk, req: Request, res: Response) => {
|
||||||
|
|
@ -25,19 +27,26 @@ export function init(sdk: SDK<API>) {
|
||||||
await tokenCheck.testReq(sdk, req);
|
await tokenCheck.testReq(sdk, req);
|
||||||
await tokenCheck.testResp(sdk, res, req);
|
await tokenCheck.testResp(sdk, res, req);
|
||||||
await ScopeDetectionController.scan(sdk, req.getUrl());
|
await ScopeDetectionController.scan(sdk, req.getUrl());
|
||||||
|
// await clientSecretController.report(sdk,req);
|
||||||
|
|
||||||
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) => {
|
||||||
|
if (clientSecretController.test(req)) {
|
||||||
|
await clientSecretController.report(sdk,req);
|
||||||
|
}
|
||||||
|
});/*
|
||||||
|
|
||||||
|
await clientSecretController.report(sdk,req);})
|
||||||
const result =
|
const result =
|
||||||
authZCodeGrantController.testReq(req) ||
|
authZCodeGrantController.testReq(req) ||
|
||||||
implicitGrantController.testReq(req);
|
implicitGrantController.testReq(req);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue