Merge branch 'main' into feature/access-token-detector
This commit is contained in:
commit
a2b7d44ec0
5 changed files with 135 additions and 28 deletions
83
packages/backend/src/controller/scopeDetection.ts
Normal file
83
packages/backend/src/controller/scopeDetection.ts
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
import type { SDK } from "caido:plugin";
|
||||
import { RequestSpec } from "caido:utils";
|
||||
|
||||
export class ScopeDetection {
|
||||
async scan(
|
||||
sdk: SDK,
|
||||
url: string
|
||||
): Promise<{ data: string }> {
|
||||
sdk.console.log(`들어온 url : ${url}`); // url이 잘 들어왔는지 확인함요
|
||||
|
||||
// url이 string이 아니고 , 값이 없거나 그럴 때 유효한 값 넣으라고 출력.
|
||||
if (!url || typeof url !== "string") {
|
||||
sdk.console.log("이상한 url 입력함.");
|
||||
return { data: "알맞은 URL을 입력하세요." };
|
||||
}
|
||||
|
||||
try {
|
||||
const spec = new RequestSpec(url); // url에 GET 요청 보낼거긔.
|
||||
spec.setMethod("GET");
|
||||
spec.setHeader("User-Agent", "Caido Scanner");
|
||||
spec.setHeader("Accept", "*/*");
|
||||
sdk.console.log(`요청 URL: ${url}`);
|
||||
|
||||
const res = await sdk.requests.send(spec); // 요청 보내고 응답 받음.
|
||||
sdk.console.log('[SCAN] 응답 :', res);
|
||||
sdk.console.log(`[SCAN] 요청 성공:${(res as any).status}`);
|
||||
sdk.console.log(`[SCAN] body: ${(res as any).body ? (res as any).body.toString().substring(0, 100) : "없음"}`);
|
||||
|
||||
const html = (res as any).body ? (res as any).body.toString() : "";
|
||||
|
||||
// <a href= 형태 링크 찾을거임.
|
||||
const anchorRegex = /<a\s+[^>]*href="([^"]+)"[^>]*>/gi;
|
||||
const anchors: string[] = [];
|
||||
let match;
|
||||
while ((match = anchorRegex.exec(html)) !== null) { // html에서 a href 찾아 배열에 저장함.
|
||||
if (typeof match[1] === "string") {
|
||||
anchors.push(match[1]);
|
||||
}
|
||||
}
|
||||
sdk.console.log(`찾아진 a href 개수: ${anchors.length}`);
|
||||
|
||||
// 5. scope 탐지
|
||||
const results: string[] = [];
|
||||
anchors.forEach((href) => { // 추출한 a href 링크 하나씩 검사드감.
|
||||
try {
|
||||
const absHref = new URL(href, url).href; // 상대경로라면 url 기준으로 절대 URL 바꿔줌줌
|
||||
sdk.console.log(`[SCAN] 절대 URL 변환: ${href} -> ${absHref}`); //
|
||||
|
||||
if (/oauth|authorize|login|accounts|auth/i.test(absHref)) { // url에 이런 OAuth 키워드가 있는지 필터링.
|
||||
let u: URL;
|
||||
try {
|
||||
u = new URL(absHref); // 필터링된 url을 url 객체로 파싱. 정식 url인 경우 변수 u에 저장.
|
||||
} catch (err) { // 파싱 실패하면
|
||||
sdk.console.log(
|
||||
`URL 파싱 실패 : ${absHref} (${err instanceof Error ? err.message : err})`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const scope = u.searchParams.get("scope"); // url에 scope있긔?scope값 가져와.
|
||||
if (scope && /all|\*/i.test(scope)) { // scope가 존재하고 all, *있다면.
|
||||
results.push(`위험한 scope 발견: ${scope}\n -> ${absHref}`); // results에 경고 메시지 전달.
|
||||
}
|
||||
} catch (err) {
|
||||
sdk.console.log(`searchParams.get 실패`);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
sdk.console.log(
|
||||
`URL 파싱 실패 (absHref 단계): ${href} (${e instanceof Error ? e.message : e})`
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
const resultStr = results.join("\n") || "위험한 scope가 발견되지 않았습니다.";
|
||||
return { data: resultStr }; // 성공했는지 실패했는지 App.vue한테 전달할 메시지.
|
||||
} catch (e) {
|
||||
sdk.console.log(`백엔드 에러: ${e instanceof Error ? e.message : e}`);
|
||||
return { data: "백엔드 에러: " + (e instanceof Error ? e.message : String(e)) }; // App.vue에 전달할 메시지.
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@ import type { Request, Response } from "caido:utils";
|
|||
import { CsrfCheck } from "./controller/csrfCheck";
|
||||
import { PKCECheck } from "./controller/PKCECheck";
|
||||
import { AccessTokenLeakController } from "./controller/accessTokenDetector";
|
||||
import { ScopeDetection } from "./controller/scopeDetection";
|
||||
|
||||
export type API = DefineAPI<{}>;
|
||||
|
||||
|
|
@ -13,6 +14,7 @@ const csrfCheck = new CsrfCheck();
|
|||
// const authZCodeGrantController = new AuthZCodeGrantController();
|
||||
const pkceCheckController = new PKCECheck();
|
||||
const tokenCheck = new AccessTokenLeakController();
|
||||
const ScopeDetectionController = new ScopeDetection();
|
||||
|
||||
export function init(sdk: SDK<API>) {
|
||||
// sdk.events.onInterceptRequest(async (sdk, req: Request) => {
|
||||
|
|
@ -34,6 +36,7 @@ export function init(sdk: SDK<API>) {
|
|||
await pkceCheckController.test(sdk, req);
|
||||
await tokenCheck.testReq(sdk, req);
|
||||
await tokenCheck.testResp(sdk, resp, req);
|
||||
await ScopeDetectionController.scan(sdk, req.getUrl());
|
||||
// sdk.events.onInterceptRequest(async (sdk, req: Request) => {
|
||||
// const result =
|
||||
// authZCodeGrantController.testReq(req) ||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue