Merge pull request #17 from whs-authz-authn-project/gyu
[Add] RedirectBypassController 및 실행 로직 추가
This commit is contained in:
commit
14164ceb83
2 changed files with 16 additions and 7 deletions
|
|
@ -1,40 +1,46 @@
|
||||||
import type { Request, Response } from "caido:utils";
|
import type { Request, Response } from "caido:utils";
|
||||||
|
import type { SDK } from "caido:plugin";
|
||||||
|
|
||||||
export class RedirectBypassController {
|
export class RedirectBypassController {
|
||||||
isRedirectUri(req: Request): boolean {
|
isRedirectUri(req: Request): boolean {
|
||||||
const query = req.getQuery();
|
const query = req.getQuery();
|
||||||
|
|
||||||
|
|
||||||
// redirect_uri 파라미터 정규식으로 추출
|
// redirect_uri 파라미터 정규식으로 추출
|
||||||
const redirectUriMatch = query.match(/redirect_uri=([^&]+)/i);
|
const redirectUriMatch = query.match(/redirect_uri=([^&]+)/i);
|
||||||
if (!redirectUriMatch) return false;
|
if (!redirectUriMatch) return false;
|
||||||
|
|
||||||
|
|
||||||
// redirect_uri 파라미터의 URL 문자열을 디코딩
|
// redirect_uri 파라미터의 URL 문자열을 디코딩
|
||||||
const redirectUri = decodeURIComponent(redirectUriMatch[1]);
|
const redirectUri = decodeURIComponent(redirectUriMatch[1]);
|
||||||
|
|
||||||
|
|
||||||
// 우회 키워드
|
// 우회 키워드
|
||||||
const bypassPatterns = [
|
const bypassPatterns = [
|
||||||
"%ff@", "/", "%2f@", "%0a@", "%0d@", "\\", ".evil.com", "@", "%2f..%2f"
|
"%ff@", "/", "%2f@", "%0a@", "%0d@", "\\", ".evil.com", "@", "%2f..%2f"
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
return bypassPatterns.some(pattern => redirectUri.includes(pattern));
|
return bypassPatterns.some(pattern => redirectUri.includes(pattern));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
isCodeIssued(res: Response): boolean {
|
isCodeIssued(res: Response): boolean {
|
||||||
const location = res.getHeader("Location") || "";
|
const location = res.getHeader("Location") || "";
|
||||||
return location.includes("code=");
|
return location.includes("code=");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
test(req: Request, res: Response): string | false {
|
test(req: Request, res: Response): string | false {
|
||||||
if (this.isRedirectUri(req) && this.isCodeIssued(res)) {
|
if (this.isRedirectUri(req) && this.isCodeIssued(res)) {
|
||||||
return "redirect_uri bypass detected";
|
return "redirect_uri bypass detected";
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async testAsync(sdk: SDK, req: Request, res: Response) {
|
||||||
|
const result = this.test(req, res);
|
||||||
|
if (result) {
|
||||||
|
await sdk.findings.create({
|
||||||
|
title: "Redirect URI Bypass Detected",
|
||||||
|
description: result,
|
||||||
|
request: req,
|
||||||
|
reporter: "gyu",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ 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";
|
||||||
|
|
||||||
export type API = DefineAPI<{}>;
|
export type API = DefineAPI<{}>;
|
||||||
|
|
||||||
|
|
@ -15,6 +16,7 @@ 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 redirectBypassController = new RedirectBypassController();
|
||||||
|
|
||||||
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) => {
|
||||||
|
|
@ -23,6 +25,7 @@ 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 redirectBypassController.testAsync(sdk, req, res);
|
||||||
|
|
||||||
// if (NonceCheckController.isOidcFlow(req, res)) {
|
// if (NonceCheckController.isOidcFlow(req, res)) {
|
||||||
// await sdk.findings.create({
|
// await sdk.findings.create({
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue