Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions packages/workflows/src/http-method-checker/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# HTTP Method Checker

## Author
- **Name:** [Ads Dawson](https://github.com/GangGreenTemperTatum)

## Description
This workflow dynamically probes HTTP endpoints by sending an `OPTIONS` request to detect discrepancies between the HTTP methods advertised by the server and the method originally used. It helps identify misconfigured HTTP methods exposed on the target.

## Features
- Sends `OPTIONS` request to the same host and path as the original request.
- Parses `Allow` and `Access-Control-Allow-Methods` headers.
- Flags requests where the original HTTP method is not listed in the allowed methods.
- Creates findings with detailed metadata for easier triage.

## Usage
Import this workflow into Caido and run it during your HTTP request analysis. It automatically sends the probe and generates findings if discrepancies are found.
172 changes: 172 additions & 0 deletions packages/workflows/src/http-method-checker/definition.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
{
"description": "Passively probes each proxied HTTP request with a subsequent HTTP OPTIONS request and reports when the OPTIONS response includes allowed methods beyond the original request method.",
"edition": 2,
"graph": {
"edges": [
{
"source": {
"exec_alias": "exec",
"node_id": 2
},
"target": {
"exec_alias": "exec",
"node_id": 3
}
},
{
"source": {
"exec_alias": "exec",
"node_id": 3
},
"target": {
"exec_alias": "exec",
"node_id": 1
}
},
{
"source": {
"exec_alias": "exec",
"node_id": 0
},
"target": {
"exec_alias": "exec",
"node_id": 5
}
},
{
"source": {
"exec_alias": "true",
"node_id": 5
},
"target": {
"exec_alias": "exec",
"node_id": 2
}
}
],
"nodes": [
{
"alias": "on_intercept_request",
"definition_id": "caido/on-intercept-request",
"display": {
"x": -10,
"y": -110
},
"id": 0,
"inputs": [],
"name": "On intercept request",
"version": "0.1.0"
},
{
"alias": "passive_end",
"definition_id": "caido/passive-end",
"display": {
"x": -10,
"y": 260
},
"id": 1,
"inputs": [],
"name": "Passive End",
"version": "0.1.0"
},
{
"alias": "javascript",
"definition_id": "caido/http-code-js",
"display": {
"x": -10,
"y": 80
},
"id": 2,
"inputs": [
{
"alias": "request",
"value": {
"data": "$on_intercept_request.request",
"kind": "ref"
}
},
{
"alias": "code",
"value": {
"data": "",
"kind": "string"
}
}
],
"name": "OPTIONS Request Probe",
"version": "0.1.0"
},
{
"alias": "create_finding",
"definition_id": "caido/finding-create",
"display": {
"x": -10,
"y": 170
},
"id": 3,
"inputs": [
{
"alias": "title",
"value": {
"data": "Create Finding",
"kind": "string"
}
},
{
"alias": "reporter",
"value": {
"data": "HTTP Method Checker",
"kind": "string"
}
},
{
"alias": "dedupe_key",
"value": {
"data": "`${host}|${path}|${origMethod}|${allowHeader}`, ",
"kind": "string"
}
},
{
"alias": "request",
"value": {
"data": "$options_probe.data",
"kind": "ref"
}
},
{
"alias": "description",
"value": {
"data": "$options_probe.data",
"kind": "ref"
}
}
],
"name": "Create Finding",
"version": "0.1.0"
},
{
"alias": "in_scope",
"definition_id": "caido/in-scope",
"display": {
"x": -10,
"y": -10
},
"id": 5,
"inputs": [
{
"alias": "request",
"value": {
"data": "$on_intercept_request.request",
"kind": "ref"
}
}
],
"name": "In Scope",
"version": "0.1.0"
}
]
},
"id": "ce244451-262d-4c01-89d0-358b8fc58a2b",
"kind": "passive",
"name": "HTTP Method Checker"
}
33 changes: 33 additions & 0 deletions packages/workflows/src/http-method-checker/javascript.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/**
* @param {HttpInput} input
* @param {SDK} sdk
* @returns {MaybePromise<Data | undefined>}
*/
export async function run({ request, response }, sdk) {
if (!request) return;

const orig = request.getMethod();
const spec = request.toSpec();
spec.setMethod("OPTIONS");

// Send the dynamic OPTIONS probe to the same host/path
const probe = await sdk.requests.send(spec);

if (probe.response) {
const headers = probe.response.getHeaders();
const allow = headers["allow"]?.[0] || "";
const cors = headers["access-control-allow-methods"]?.[0] || "";
const methods = (allow || cors).split(/\s*,\s*/);

if (methods.length && !methods.includes(orig)) {
const dedupeKey = `${request.getHost()}|${request.getPath()}|${orig}|${methods.join(",")}`;
await sdk.findings.create({
title: "Extraneous HTTP methods exposed",
description: `OPTIONS listed methods [${methods.join(", ")}], original: ${orig}`,
request,
response: probe.response,
dedupeKey
});
}
}
}
10 changes: 10 additions & 0 deletions packages/workflows/src/http-method-checker/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"author": {
"name": "Ads Dawson"
},
"url": "https://github.com/caido-community/workflows/packages/workflows/http-method-checker/README.md",
"description": "Detects HTTP methods exposed by dynamically probing endpoints with OPTIONS requests.",
"id": "http-method-checker",
"name": "HTTP Method Checker",
"version": "0.1.0"
}