@j3r3mcdev/oast-server 1.1.0 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/ci.yml +29 -29
- package/.github/workflows/publish.yml +31 -31
- package/README.md +192 -192
- package/dist/listeners/ssrf/__tests__/ssrf.listener.test.js +16 -4
- package/jest.config.js +14 -14
- package/package.json +45 -45
- package/sadmin list shadows +9 -9
- package/src/api/controllers/__tests__/tasks.controller.test.ts +74 -74
- package/src/api/controllers/events.controller.ts +10 -10
- package/src/api/controllers/health.controller.ts +7 -7
- package/src/api/controllers/tasks.controller.ts +41 -41
- package/src/api/dto/__tests__/create-task.dto.test.ts +41 -41
- package/src/api/dto/__tests__/filter-tasks.dto.test.ts +35 -35
- package/src/api/dto/create-task.dto.ts +33 -33
- package/src/api/dto/filter-tasks.dto.ts +33 -33
- package/src/api/services/__tests__/events.service.test.ts +41 -41
- package/src/api/services/__tests__/tasks.service.test.ts +41 -41
- package/src/api/services/events.service.ts +17 -17
- package/src/api/services/tasks.service.ts +79 -79
- package/src/api/sse/events.stream.ts +90 -90
- package/src/core/__tests__/core-router.test.ts +30 -30
- package/src/core/__tests__/core-server.test.ts +44 -44
- package/src/core/__tests__/event.normalizer.test.ts +56 -56
- package/src/core/__tests__/event.router.test.ts +89 -89
- package/src/core/__tests__/logger.test.ts +32 -32
- package/src/core/__tests__/storage-manager.test.ts +74 -74
- package/src/core/event.normalizer.ts +147 -147
- package/src/core/event.router.ts +13 -13
- package/src/core/http/__tests__/adapter-node.test.ts +52 -52
- package/src/core/http/__tests__/body-parser-multipart.test.ts +41 -41
- package/src/core/http/__tests__/body-parser-raw.test.ts +28 -28
- package/src/core/http/__tests__/body-parser-text.test.ts +28 -28
- package/src/core/http/__tests__/compile-path.test.ts +39 -39
- package/src/core/http/__tests__/middleware-pipeline.test.ts +51 -51
- package/src/core/http/__tests__/request.test.ts +34 -34
- package/src/core/http/__tests__/response.test.ts +35 -35
- package/src/core/http/__tests__/router-match.test.ts +171 -171
- package/src/core/http/adapter-node.ts +51 -51
- package/src/core/http/buildRequest.ts +18 -18
- package/src/core/http/compile-path.ts +32 -32
- package/src/core/http/errors.ts +37 -37
- package/src/core/http/http-server.ts +52 -52
- package/src/core/http/middleware.ts +160 -160
- package/src/core/http/request.ts +55 -55
- package/src/core/http/response.ts +93 -93
- package/src/core/http/router.ts +138 -138
- package/src/core/id-generator.ts +8 -8
- package/src/core/logger.ts +113 -113
- package/src/core/router.ts +44 -44
- package/src/core/server.ts +85 -85
- package/src/core/storage.ts +64 -64
- package/src/index.ts +89 -89
- package/src/listeners/api/__tests__/api.controller.test.ts +116 -116
- package/src/listeners/api/__tests__/api.extractor.test.ts +46 -46
- package/src/listeners/api/__tests__/api.listener.test.ts +82 -82
- package/src/listeners/api/__tests__/api.routes.test.ts +155 -155
- package/src/listeners/api/__tests__/api.sse.test.ts +105 -105
- package/src/listeners/api/api.controllers.ts +67 -67
- package/src/listeners/api/api.extractor.ts +43 -43
- package/src/listeners/api/api.listener.ts +50 -50
- package/src/listeners/api/api.routes.ts +76 -76
- package/src/listeners/api/api.sse.ts +38 -38
- package/src/listeners/dns/__tests__/dns.test.ts +118 -118
- package/src/listeners/dns/dns.extractor.ts +14 -14
- package/src/listeners/dns/dns.listener.ts +61 -61
- package/src/listeners/http/__tests__/http.extractor.test.ts +59 -59
- package/src/listeners/http/__tests__/http.listener.test.ts +133 -133
- package/src/listeners/http/http.extractor.ts +15 -15
- package/src/listeners/http/http.listener.ts +110 -110
- package/src/listeners/listener.interface.ts +4 -4
- package/src/listeners/smtp/__tests__/smtp.extractor.test.ts +69 -69
- package/src/listeners/smtp/__tests__/smtp.listener.test.ts +150 -150
- package/src/listeners/smtp/smtp.extractor.ts +18 -18
- package/src/listeners/smtp/smtp.listener.ts +60 -60
- package/src/listeners/ssrf/__tests__/ssrf.extractor.test.ts +41 -41
- package/src/listeners/ssrf/__tests__/ssrf.listener.test.ts +87 -87
- package/src/listeners/ssrf/ssrf.extractor.ts +14 -14
- package/src/listeners/ssrf/ssrf.listener.ts +37 -37
- package/src/listeners/tcp/tcp.extractor.ts +16 -16
- package/src/listeners/tcp/tcp.listener.ts +61 -61
- package/src/listeners/webhook/__tests__/webhook.extractor.test.ts +35 -35
- package/src/listeners/webhook/__tests__/webhook.listener.test.ts +122 -122
- package/src/listeners/webhook/webhook.extractor.ts +12 -12
- package/src/listeners/webhook/webhook.listener.ts +58 -58
- package/src/listeners/websocket/__tests__/websocket.extractor.test.ts +33 -33
- package/src/listeners/websocket/__tests__/websocket.listener.test.ts +90 -90
- package/src/listeners/websocket/websocket.extractor.ts +11 -11
- package/src/listeners/websocket/websocket.listener.ts +40 -40
- package/src/storage-adapters/adapters/__tests__/memory.storage.test.ts +75 -75
- package/src/storage-adapters/adapters/memory.storage.ts +64 -64
- package/src/storage-adapters/storage.interface.ts +26 -26
- package/src/types/event.types.ts +147 -147
- package/tsconfig.json +21 -21
- package/dist/api/controllers/__tests__/tasks.controller.test.d.ts +0 -1
- package/dist/api/controllers/events.controller.d.ts +0 -6
- package/dist/api/controllers/health.controller.d.ts +0 -4
- package/dist/api/controllers/index.d.ts +0 -0
- package/dist/api/controllers/tasks.controller.d.ts +0 -40
- package/dist/api/dto/__tests__/create-task.dto.test.d.ts +0 -1
- package/dist/api/dto/__tests__/filter-tasks.dto.test.d.ts +0 -1
- package/dist/api/dto/create-task.dto.d.ts +0 -9
- package/dist/api/dto/filter-tasks.dto.d.ts +0 -8
- package/dist/api/services/__tests__/events.service.test.d.ts +0 -1
- package/dist/api/services/__tests__/tasks.service.test.d.ts +0 -1
- package/dist/api/services/events.service.d.ts +0 -8
- package/dist/api/services/tasks.service.d.ts +0 -22
- package/dist/api/sse/events.stream.d.ts +0 -25
- package/dist/config/constants.d.ts +0 -0
- package/dist/config/env.d.ts +0 -0
- package/dist/core/__tests__/core-router.test.d.ts +0 -1
- package/dist/core/__tests__/core-server.test.d.ts +0 -1
- package/dist/core/__tests__/event.normalizer.test.d.ts +0 -1
- package/dist/core/__tests__/event.router.test.d.ts +0 -1
- package/dist/core/__tests__/logger.test.d.ts +0 -1
- package/dist/core/__tests__/storage-manager.test.d.ts +0 -1
- package/dist/core/event.normalizer.d.ts +0 -10
- package/dist/core/event.router.d.ts +0 -7
- package/dist/core/http/__tests__/adapter-node.test.d.ts +0 -1
- package/dist/core/http/__tests__/body-parser-multipart.test.d.ts +0 -1
- package/dist/core/http/__tests__/body-parser-raw.test.d.ts +0 -1
- package/dist/core/http/__tests__/body-parser-text.test.d.ts +0 -1
- package/dist/core/http/__tests__/compile-path.test.d.ts +0 -1
- package/dist/core/http/__tests__/middleware-pipeline.test.d.ts +0 -1
- package/dist/core/http/__tests__/request.test.d.ts +0 -1
- package/dist/core/http/__tests__/response.test.d.ts +0 -1
- package/dist/core/http/__tests__/router-match.test.d.ts +0 -1
- package/dist/core/http/adapter-node.d.ts +0 -8
- package/dist/core/http/buildRequest.d.ts +0 -2
- package/dist/core/http/compile-path.d.ts +0 -13
- package/dist/core/http/errors.d.ts +0 -9
- package/dist/core/http/http-server.d.ts +0 -7
- package/dist/core/http/index.d.ts +0 -0
- package/dist/core/http/main.d.ts +0 -0
- package/dist/core/http/middleware.d.ts +0 -12
- package/dist/core/http/request.d.ts +0 -35
- package/dist/core/http/response.d.ts +0 -17
- package/dist/core/http/router.d.ts +0 -28
- package/dist/core/http/utils.d.ts +0 -0
- package/dist/core/id-generator.d.ts +0 -3
- package/dist/core/logger.d.ts +0 -29
- package/dist/core/router.d.ts +0 -16
- package/dist/core/server.d.ts +0 -25
- package/dist/core/storage.d.ts +0 -24
- package/dist/index.d.ts +0 -1
- package/dist/listeners/api/__tests__/api.controller.test.d.ts +0 -1
- package/dist/listeners/api/__tests__/api.extractor.test.d.ts +0 -1
- package/dist/listeners/api/__tests__/api.listener.test.d.ts +0 -1
- package/dist/listeners/api/__tests__/api.routes.test.d.ts +0 -1
- package/dist/listeners/api/__tests__/api.sse.test.d.ts +0 -1
- package/dist/listeners/api/api.controllers.d.ts +0 -9
- package/dist/listeners/api/api.extractor.d.ts +0 -5
- package/dist/listeners/api/api.listener.d.ts +0 -17
- package/dist/listeners/api/api.routes.d.ts +0 -5
- package/dist/listeners/api/api.sse.d.ts +0 -10
- package/dist/listeners/dns/__tests__/dns.test.d.ts +0 -1
- package/dist/listeners/dns/dns.extractor.d.ts +0 -8
- package/dist/listeners/dns/dns.listener.d.ts +0 -15
- package/dist/listeners/http/__tests__/http.extractor.test.d.ts +0 -1
- package/dist/listeners/http/__tests__/http.listener.test.d.ts +0 -1
- package/dist/listeners/http/http.extractor.d.ts +0 -11
- package/dist/listeners/http/http.listener.d.ts +0 -17
- package/dist/listeners/listener.interface.d.ts +0 -4
- package/dist/listeners/smtp/__tests__/smtp.extractor.test.d.ts +0 -1
- package/dist/listeners/smtp/__tests__/smtp.listener.test.d.ts +0 -1
- package/dist/listeners/smtp/smtp.extractor.d.ts +0 -12
- package/dist/listeners/smtp/smtp.listener.d.ts +0 -13
- package/dist/listeners/ssrf/__tests__/ssrf.extractor.test.d.ts +0 -1
- package/dist/listeners/ssrf/__tests__/ssrf.listener.test.d.ts +0 -1
- package/dist/listeners/ssrf/ssrf.extractor.d.ts +0 -10
- package/dist/listeners/ssrf/ssrf.listener.d.ts +0 -8
- package/dist/listeners/tcp/tcp.extractor.d.ts +0 -4
- package/dist/listeners/tcp/tcp.listener.d.ts +0 -18
- package/dist/listeners/webhook/__tests__/webhook.extractor.test.d.ts +0 -1
- package/dist/listeners/webhook/__tests__/webhook.listener.test.d.ts +0 -1
- package/dist/listeners/webhook/webhook.extractor.d.ts +0 -8
- package/dist/listeners/webhook/webhook.listener.d.ts +0 -8
- package/dist/listeners/websocket/__tests__/websocket.extractor.test.d.ts +0 -1
- package/dist/listeners/websocket/__tests__/websocket.listener.test.d.ts +0 -1
- package/dist/listeners/websocket/websocket.extractor.d.ts +0 -10
- package/dist/listeners/websocket/websocket.listener.d.ts +0 -8
- package/dist/storage-adapters/adapters/__tests__/memory.storage.test.d.ts +0 -1
- package/dist/storage-adapters/adapters/memory.storage.d.ts +0 -21
- package/dist/storage-adapters/adapters/redis.storage.d.ts +0 -0
- package/dist/storage-adapters/adapters/sqlite.storage.d.ts +0 -0
- package/dist/storage-adapters/storage.interface.d.ts +0 -18
- package/dist/types/event.types.d.ts +0 -118
- package/dist/utils/token.d.ts +0 -0
package/.github/workflows/ci.yml
CHANGED
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
name: CI
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
branches: ["main"]
|
|
6
|
-
pull_request:
|
|
7
|
-
branches: ["main"]
|
|
8
|
-
|
|
9
|
-
jobs:
|
|
10
|
-
build-and-test:
|
|
11
|
-
runs-on: ubuntu-latest
|
|
12
|
-
|
|
13
|
-
steps:
|
|
14
|
-
- name: Checkout repository
|
|
15
|
-
uses: actions/checkout@v4
|
|
16
|
-
|
|
17
|
-
- name: Setup Node
|
|
18
|
-
uses: actions/setup-node@v4
|
|
19
|
-
with:
|
|
20
|
-
node-version: 20
|
|
21
|
-
|
|
22
|
-
- name: Install dependencies
|
|
23
|
-
run: npm install
|
|
24
|
-
|
|
25
|
-
- name: Run tests
|
|
26
|
-
run: npm test
|
|
27
|
-
|
|
28
|
-
- name: Build project
|
|
29
|
-
run: npm run build
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: ["main"]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: ["main"]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
build-and-test:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
|
|
13
|
+
steps:
|
|
14
|
+
- name: Checkout repository
|
|
15
|
+
uses: actions/checkout@v4
|
|
16
|
+
|
|
17
|
+
- name: Setup Node
|
|
18
|
+
uses: actions/setup-node@v4
|
|
19
|
+
with:
|
|
20
|
+
node-version: 20
|
|
21
|
+
|
|
22
|
+
- name: Install dependencies
|
|
23
|
+
run: npm install
|
|
24
|
+
|
|
25
|
+
- name: Run tests
|
|
26
|
+
run: npm test
|
|
27
|
+
|
|
28
|
+
- name: Build project
|
|
29
|
+
run: npm run build
|
|
@@ -1,31 +1,31 @@
|
|
|
1
|
-
name: Publish to npm
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
tags:
|
|
6
|
-
- "v*.*.*"
|
|
7
|
-
|
|
8
|
-
jobs:
|
|
9
|
-
publish:
|
|
10
|
-
runs-on: ubuntu-latest
|
|
11
|
-
|
|
12
|
-
steps:
|
|
13
|
-
- name: Checkout repository
|
|
14
|
-
uses: actions/checkout@v4
|
|
15
|
-
|
|
16
|
-
- name: Setup Node
|
|
17
|
-
uses: actions/setup-node@v4
|
|
18
|
-
with:
|
|
19
|
-
node-version: 20
|
|
20
|
-
registry-url: "https://registry.npmjs.org"
|
|
21
|
-
|
|
22
|
-
- name: Install dependencies
|
|
23
|
-
run: npm ci
|
|
24
|
-
|
|
25
|
-
- name: Build project
|
|
26
|
-
run: npm run build
|
|
27
|
-
|
|
28
|
-
- name: Publish package
|
|
29
|
-
env:
|
|
30
|
-
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
31
|
-
run: npm publish --access public
|
|
1
|
+
name: Publish to npm
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*.*.*"
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
publish:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
|
|
12
|
+
steps:
|
|
13
|
+
- name: Checkout repository
|
|
14
|
+
uses: actions/checkout@v4
|
|
15
|
+
|
|
16
|
+
- name: Setup Node
|
|
17
|
+
uses: actions/setup-node@v4
|
|
18
|
+
with:
|
|
19
|
+
node-version: 20
|
|
20
|
+
registry-url: "https://registry.npmjs.org"
|
|
21
|
+
|
|
22
|
+
- name: Install dependencies
|
|
23
|
+
run: npm ci
|
|
24
|
+
|
|
25
|
+
- name: Build project
|
|
26
|
+
run: npm run build
|
|
27
|
+
|
|
28
|
+
- name: Publish package
|
|
29
|
+
env:
|
|
30
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
31
|
+
run: npm publish --access public
|
package/README.md
CHANGED
|
@@ -1,192 +1,192 @@
|
|
|
1
|
-
# OAST Server — Multi‑Protocol Out‑of‑Band Interaction Framework
|
|
2
|
-
|
|
3
|
-
Un serveur OAST modulaire, extensible et agnostique, conçu pour capturer, normaliser et diffuser des interactions _out‑of‑band_ provenant de multiples canaux : HTTP, DNS, SMTP, SSRF, Webhook, WebSocket, TCP, API REST et SSE.
|
|
4
|
-
|
|
5
|
-
Ce framework fournit une architecture listener‑based robuste, unifiée et testée, idéale pour les outils de diagnostic, scanners de vulnérabilités, plateformes d’audit ou systèmes de détection avancés.
|
|
6
|
-
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## ✨ Caractéristiques principales
|
|
10
|
-
|
|
11
|
-
- **Architecture modulaire par listeners**
|
|
12
|
-
Chaque protocole est isolé dans son propre module (`http`, `dns`, `smtp`, `ssrf`, `webhook`, `websocket`, `tcp`, `api`).
|
|
13
|
-
|
|
14
|
-
- **Extractors dédiés**
|
|
15
|
-
Chaque listener dispose d’un extractor responsable de la normalisation des données brutes.
|
|
16
|
-
|
|
17
|
-
- **API REST intégrée**
|
|
18
|
-
Permet de récupérer les events, les tasks, les métadonnées et l’état du serveur.
|
|
19
|
-
|
|
20
|
-
- **SSE (Server‑Sent Events)**
|
|
21
|
-
Diffusion en temps réel des interactions capturées.
|
|
22
|
-
|
|
23
|
-
- **Storage agnostique**
|
|
24
|
-
Implémentation par défaut en mémoire, extensible vers Redis, SQLite, PostgreSQL, etc.
|
|
25
|
-
|
|
26
|
-
- **Suite de tests complète**
|
|
27
|
-
118 tests unitaires couvrant extractors, listeners, API, SSE et services.
|
|
28
|
-
|
|
29
|
-
- **Aucune dépendance lourde**
|
|
30
|
-
Pas d’Express, pas de framework web : un cœur minimaliste, rapide et portable.
|
|
31
|
-
|
|
32
|
-
---
|
|
33
|
-
|
|
34
|
-
## 📦 Installation
|
|
35
|
-
|
|
36
|
-
```bash
|
|
37
|
-
npm install @j3r3mcdev/oast-server
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
## 🚀 Démarrage rapide
|
|
41
|
-
|
|
42
|
-
```ts
|
|
43
|
-
import { ApiListener, HttpListener, DnsListener } from "@j3r3mcdev/oast-server";
|
|
44
|
-
|
|
45
|
-
const api = new ApiListener({ port: 8080 });
|
|
46
|
-
const http = new HttpListener({ port: 8000 });
|
|
47
|
-
const dns = new DnsListener({ port: 5353 });
|
|
48
|
-
|
|
49
|
-
api.start();
|
|
50
|
-
http.start();
|
|
51
|
-
dns.start();
|
|
52
|
-
|
|
53
|
-
console.log("OAST server running");
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
## 📡 Protocoles supportés
|
|
57
|
-
|
|
58
|
-
| Protocole | Listener | Description |
|
|
59
|
-
| ------------- | ------------------- | --------------------------------------- |
|
|
60
|
-
| **HTTP** | `HttpListener` | Capture des requêtes HTTP entrantes |
|
|
61
|
-
| **DNS** | `DnsListener` | Résolution DNS OAST (A, AAAA, TXT…) |
|
|
62
|
-
| **SMTP** | `SmtpListener` | Réception d’emails OAST |
|
|
63
|
-
| **SSRF** | `SsrfListener` | Détection d’interactions SSRF |
|
|
64
|
-
| **Webhook** | `WebhookListener` | Réception d’appels webhook |
|
|
65
|
-
| **WebSocket** | `WebSocketListener` | Connexions WebSocket entrantes |
|
|
66
|
-
| **TCP** | `TcpListener` | Connexions TCP brutes |
|
|
67
|
-
| **API + SSE** | `ApiListener` | API REST + diffusion temps réel via SSE |
|
|
68
|
-
|
|
69
|
-
## 🧩 Architecture
|
|
70
|
-
|
|
71
|
-

|
|
72
|
-
|
|
73
|
-
Chaque listener contient :
|
|
74
|
-
|
|
75
|
-
- `*.listener.ts` → serveur du protocole
|
|
76
|
-
- `*.extractor.ts` → normalisation des données
|
|
77
|
-
- `__tests__/` → tests unitaires
|
|
78
|
-
|
|
79
|
-
## 🧨 Exemple : Listener HTTP
|
|
80
|
-
|
|
81
|
-
```ts
|
|
82
|
-
import { HttpListener } from "@j3r3mcdev/oast-server";
|
|
83
|
-
|
|
84
|
-
const http = new HttpListener({
|
|
85
|
-
port: 8000,
|
|
86
|
-
onEvent: (event) => {
|
|
87
|
-
console.log("HTTP event:", event);
|
|
88
|
-
},
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
http.start();
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
---
|
|
95
|
-
|
|
96
|
-
# 🧨 **Exemple : Listener DNS**
|
|
97
|
-
|
|
98
|
-
## 🧨 Exemple : Listener DNS
|
|
99
|
-
|
|
100
|
-
```ts
|
|
101
|
-
import { DnsListener } from "@j3r3mcdev/oast-server";
|
|
102
|
-
|
|
103
|
-
const dns = new DnsListener({
|
|
104
|
-
port: 5353,
|
|
105
|
-
onEvent: (event) => {
|
|
106
|
-
console.log("DNS event:", event);
|
|
107
|
-
},
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
dns.start();
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
---
|
|
114
|
-
|
|
115
|
-
# 🧨 **Exemple : SSE (temps réel)**
|
|
116
|
-
|
|
117
|
-
```md
|
|
118
|
-
## 🧨 Exemple : SSE (temps réel)
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
```ts
|
|
122
|
-
const stream = new EventSource(
|
|
123
|
-
"http://localhost:8080/stream?channels=http,dns",
|
|
124
|
-
);
|
|
125
|
-
|
|
126
|
-
stream.onmessage = (msg) => {
|
|
127
|
-
const event = JSON.parse(msg.data);
|
|
128
|
-
console.log("Event reçu :", event);
|
|
129
|
-
};
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
---
|
|
133
|
-
|
|
134
|
-
# 🧨 **Exemple : API REST**
|
|
135
|
-
|
|
136
|
-
## 🧨 Exemple : API REST
|
|
137
|
-
|
|
138
|
-
### Récupérer les events
|
|
139
|
-
|
|
140
|
-
```bash
|
|
141
|
-
curl http://localhost:8080/events
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
### Créer une tâche
|
|
145
|
-
|
|
146
|
-
```bash
|
|
147
|
-
curl -X POST http://localhost:8080/tasks \
|
|
148
|
-
-H "Content-Type: application/json" \
|
|
149
|
-
-d '{"type":"scan","payload":{"url":"http://example.com"}}'
|
|
150
|
-
```
|
|
151
|
-
|
|
152
|
-
---
|
|
153
|
-
|
|
154
|
-
# 🧱 **Storage** (Markdown PRO)
|
|
155
|
-
|
|
156
|
-
## 🧱 Storage
|
|
157
|
-
|
|
158
|
-
Par défaut : **in‑memory**
|
|
159
|
-
|
|
160
|
-
Vous pouvez implémenter votre propre storage :
|
|
161
|
-
|
|
162
|
-
```ts
|
|
163
|
-
export interface StorageAdapter {
|
|
164
|
-
save(event: OastEvent): Promise<void>;
|
|
165
|
-
list(filters: any): Promise<OastEvent[]>;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
class MyStorage implements StorageAdapter {
|
|
169
|
-
private events = [];
|
|
170
|
-
async save(e) {
|
|
171
|
-
this.events.push(e);
|
|
172
|
-
}
|
|
173
|
-
async list() {
|
|
174
|
-
return this.events;
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
```
|
|
178
|
-
|
|
179
|
-
---
|
|
180
|
-
|
|
181
|
-
# 🧪 **Tests** (Markdown PRO)
|
|
182
|
-
|
|
183
|
-
## 🧪 Tests
|
|
184
|
-
|
|
185
|
-
- **37 suites**
|
|
186
|
-
- **118 tests**
|
|
187
|
-
- **100% verts**
|
|
188
|
-
- Tests d’intégration réservés à l’outil d’audit (non inclus dans la lib)
|
|
189
|
-
|
|
190
|
-
## 📘 Licence
|
|
191
|
-
|
|
192
|
-
MIT
|
|
1
|
+
# OAST Server — Multi‑Protocol Out‑of‑Band Interaction Framework
|
|
2
|
+
|
|
3
|
+
Un serveur OAST modulaire, extensible et agnostique, conçu pour capturer, normaliser et diffuser des interactions _out‑of‑band_ provenant de multiples canaux : HTTP, DNS, SMTP, SSRF, Webhook, WebSocket, TCP, API REST et SSE.
|
|
4
|
+
|
|
5
|
+
Ce framework fournit une architecture listener‑based robuste, unifiée et testée, idéale pour les outils de diagnostic, scanners de vulnérabilités, plateformes d’audit ou systèmes de détection avancés.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## ✨ Caractéristiques principales
|
|
10
|
+
|
|
11
|
+
- **Architecture modulaire par listeners**
|
|
12
|
+
Chaque protocole est isolé dans son propre module (`http`, `dns`, `smtp`, `ssrf`, `webhook`, `websocket`, `tcp`, `api`).
|
|
13
|
+
|
|
14
|
+
- **Extractors dédiés**
|
|
15
|
+
Chaque listener dispose d’un extractor responsable de la normalisation des données brutes.
|
|
16
|
+
|
|
17
|
+
- **API REST intégrée**
|
|
18
|
+
Permet de récupérer les events, les tasks, les métadonnées et l’état du serveur.
|
|
19
|
+
|
|
20
|
+
- **SSE (Server‑Sent Events)**
|
|
21
|
+
Diffusion en temps réel des interactions capturées.
|
|
22
|
+
|
|
23
|
+
- **Storage agnostique**
|
|
24
|
+
Implémentation par défaut en mémoire, extensible vers Redis, SQLite, PostgreSQL, etc.
|
|
25
|
+
|
|
26
|
+
- **Suite de tests complète**
|
|
27
|
+
118 tests unitaires couvrant extractors, listeners, API, SSE et services.
|
|
28
|
+
|
|
29
|
+
- **Aucune dépendance lourde**
|
|
30
|
+
Pas d’Express, pas de framework web : un cœur minimaliste, rapide et portable.
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## 📦 Installation
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npm install @j3r3mcdev/oast-server
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## 🚀 Démarrage rapide
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
import { ApiListener, HttpListener, DnsListener } from "@j3r3mcdev/oast-server";
|
|
44
|
+
|
|
45
|
+
const api = new ApiListener({ port: 8080 });
|
|
46
|
+
const http = new HttpListener({ port: 8000 });
|
|
47
|
+
const dns = new DnsListener({ port: 5353 });
|
|
48
|
+
|
|
49
|
+
api.start();
|
|
50
|
+
http.start();
|
|
51
|
+
dns.start();
|
|
52
|
+
|
|
53
|
+
console.log("OAST server running");
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## 📡 Protocoles supportés
|
|
57
|
+
|
|
58
|
+
| Protocole | Listener | Description |
|
|
59
|
+
| ------------- | ------------------- | --------------------------------------- |
|
|
60
|
+
| **HTTP** | `HttpListener` | Capture des requêtes HTTP entrantes |
|
|
61
|
+
| **DNS** | `DnsListener` | Résolution DNS OAST (A, AAAA, TXT…) |
|
|
62
|
+
| **SMTP** | `SmtpListener` | Réception d’emails OAST |
|
|
63
|
+
| **SSRF** | `SsrfListener` | Détection d’interactions SSRF |
|
|
64
|
+
| **Webhook** | `WebhookListener` | Réception d’appels webhook |
|
|
65
|
+
| **WebSocket** | `WebSocketListener` | Connexions WebSocket entrantes |
|
|
66
|
+
| **TCP** | `TcpListener` | Connexions TCP brutes |
|
|
67
|
+
| **API + SSE** | `ApiListener` | API REST + diffusion temps réel via SSE |
|
|
68
|
+
|
|
69
|
+
## 🧩 Architecture
|
|
70
|
+
|
|
71
|
+

|
|
72
|
+
|
|
73
|
+
Chaque listener contient :
|
|
74
|
+
|
|
75
|
+
- `*.listener.ts` → serveur du protocole
|
|
76
|
+
- `*.extractor.ts` → normalisation des données
|
|
77
|
+
- `__tests__/` → tests unitaires
|
|
78
|
+
|
|
79
|
+
## 🧨 Exemple : Listener HTTP
|
|
80
|
+
|
|
81
|
+
```ts
|
|
82
|
+
import { HttpListener } from "@j3r3mcdev/oast-server";
|
|
83
|
+
|
|
84
|
+
const http = new HttpListener({
|
|
85
|
+
port: 8000,
|
|
86
|
+
onEvent: (event) => {
|
|
87
|
+
console.log("HTTP event:", event);
|
|
88
|
+
},
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
http.start();
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
# 🧨 **Exemple : Listener DNS**
|
|
97
|
+
|
|
98
|
+
## 🧨 Exemple : Listener DNS
|
|
99
|
+
|
|
100
|
+
```ts
|
|
101
|
+
import { DnsListener } from "@j3r3mcdev/oast-server";
|
|
102
|
+
|
|
103
|
+
const dns = new DnsListener({
|
|
104
|
+
port: 5353,
|
|
105
|
+
onEvent: (event) => {
|
|
106
|
+
console.log("DNS event:", event);
|
|
107
|
+
},
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
dns.start();
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
# 🧨 **Exemple : SSE (temps réel)**
|
|
116
|
+
|
|
117
|
+
```md
|
|
118
|
+
## 🧨 Exemple : SSE (temps réel)
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
```ts
|
|
122
|
+
const stream = new EventSource(
|
|
123
|
+
"http://localhost:8080/stream?channels=http,dns",
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
stream.onmessage = (msg) => {
|
|
127
|
+
const event = JSON.parse(msg.data);
|
|
128
|
+
console.log("Event reçu :", event);
|
|
129
|
+
};
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
# 🧨 **Exemple : API REST**
|
|
135
|
+
|
|
136
|
+
## 🧨 Exemple : API REST
|
|
137
|
+
|
|
138
|
+
### Récupérer les events
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
curl http://localhost:8080/events
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Créer une tâche
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
curl -X POST http://localhost:8080/tasks \
|
|
148
|
+
-H "Content-Type: application/json" \
|
|
149
|
+
-d '{"type":"scan","payload":{"url":"http://example.com"}}'
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
# 🧱 **Storage** (Markdown PRO)
|
|
155
|
+
|
|
156
|
+
## 🧱 Storage
|
|
157
|
+
|
|
158
|
+
Par défaut : **in‑memory**
|
|
159
|
+
|
|
160
|
+
Vous pouvez implémenter votre propre storage :
|
|
161
|
+
|
|
162
|
+
```ts
|
|
163
|
+
export interface StorageAdapter {
|
|
164
|
+
save(event: OastEvent): Promise<void>;
|
|
165
|
+
list(filters: any): Promise<OastEvent[]>;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
class MyStorage implements StorageAdapter {
|
|
169
|
+
private events = [];
|
|
170
|
+
async save(e) {
|
|
171
|
+
this.events.push(e);
|
|
172
|
+
}
|
|
173
|
+
async list() {
|
|
174
|
+
return this.events;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
# 🧪 **Tests** (Markdown PRO)
|
|
182
|
+
|
|
183
|
+
## 🧪 Tests
|
|
184
|
+
|
|
185
|
+
- **37 suites**
|
|
186
|
+
- **118 tests**
|
|
187
|
+
- **100% verts**
|
|
188
|
+
- Tests d’intégration réservés à l’outil d’audit (non inclus dans la lib)
|
|
189
|
+
|
|
190
|
+
## 📘 Licence
|
|
191
|
+
|
|
192
|
+
MIT
|
|
@@ -14,8 +14,10 @@ globals_1.jest.mock("../../../core/event.normalizer");
|
|
|
14
14
|
let router;
|
|
15
15
|
let port;
|
|
16
16
|
let listener;
|
|
17
|
-
(0, globals_1.beforeEach)((
|
|
18
|
-
router = {
|
|
17
|
+
(0, globals_1.beforeEach)(() => {
|
|
18
|
+
router = {
|
|
19
|
+
dispatch: globals_1.jest.fn(),
|
|
20
|
+
};
|
|
19
21
|
port = 12000 + Math.floor(Math.random() * 2000);
|
|
20
22
|
ssrf_extractor_1.SsrfExtractor.extract.mockReturnValue({
|
|
21
23
|
ip: "1.2.3.4",
|
|
@@ -38,8 +40,6 @@ globals_1.jest.mock("../../../core/event.normalizer");
|
|
|
38
40
|
},
|
|
39
41
|
});
|
|
40
42
|
listener = new ssrf_listener_1.SsrfListener(router, port);
|
|
41
|
-
// 🔥 On attend que le serveur soit prêt
|
|
42
|
-
listener["server"].on("listening", done);
|
|
43
43
|
});
|
|
44
44
|
(0, globals_1.afterEach)(() => {
|
|
45
45
|
listener.stop();
|
|
@@ -49,6 +49,18 @@ globals_1.jest.mock("../../../core/event.normalizer");
|
|
|
49
49
|
const req = http_1.default.request({ hostname: "localhost", port, path: "/ssrf", method: "GET" }, (res) => {
|
|
50
50
|
(0, globals_1.expect)(res.statusCode).toBe(200);
|
|
51
51
|
(0, globals_1.expect)(router.dispatch).toHaveBeenCalledTimes(1);
|
|
52
|
+
(0, globals_1.expect)(router.dispatch).toHaveBeenCalledWith({
|
|
53
|
+
id: "123",
|
|
54
|
+
type: "ssrf",
|
|
55
|
+
timestamp: 111,
|
|
56
|
+
sourceIp: "1.2.3.4",
|
|
57
|
+
request: {
|
|
58
|
+
method: "GET",
|
|
59
|
+
path: "/ssrf",
|
|
60
|
+
headers: {},
|
|
61
|
+
query: {},
|
|
62
|
+
},
|
|
63
|
+
});
|
|
52
64
|
resolve();
|
|
53
65
|
});
|
|
54
66
|
req.end();
|
package/jest.config.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
const { createDefaultPreset } = require("ts-jest");
|
|
2
|
-
|
|
3
|
-
const tsJestTransformCfg = createDefaultPreset().transform;
|
|
4
|
-
|
|
5
|
-
/** @type {import("jest").Config} **/
|
|
6
|
-
module.exports = {
|
|
7
|
-
testEnvironment: "node",
|
|
8
|
-
transform: {
|
|
9
|
-
...tsJestTransformCfg,
|
|
10
|
-
},
|
|
11
|
-
|
|
12
|
-
// 🔥 Empêche Jest d'exécuter les tests compilés dans dist/
|
|
13
|
-
testPathIgnorePatterns: ["/dist/"],
|
|
14
|
-
};
|
|
1
|
+
const { createDefaultPreset } = require("ts-jest");
|
|
2
|
+
|
|
3
|
+
const tsJestTransformCfg = createDefaultPreset().transform;
|
|
4
|
+
|
|
5
|
+
/** @type {import("jest").Config} **/
|
|
6
|
+
module.exports = {
|
|
7
|
+
testEnvironment: "node",
|
|
8
|
+
transform: {
|
|
9
|
+
...tsJestTransformCfg,
|
|
10
|
+
},
|
|
11
|
+
|
|
12
|
+
// 🔥 Empêche Jest d'exécuter les tests compilés dans dist/
|
|
13
|
+
testPathIgnorePatterns: ["/dist/"],
|
|
14
|
+
};
|
package/package.json
CHANGED
|
@@ -1,45 +1,45 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@j3r3mcdev/oast-server",
|
|
3
|
-
"version": "1.1.
|
|
4
|
-
"description": "Modular OAST callback server for security auditing",
|
|
5
|
-
"main": "dist/index.js",
|
|
6
|
-
"types": "dist/index.d.ts",
|
|
7
|
-
"scripts": {
|
|
8
|
-
"dev": "ts-node-dev --respawn --transpile-only src/core/server.ts",
|
|
9
|
-
"build": "tsc -p tsconfig.json",
|
|
10
|
-
"start": "node dist/core/server.js",
|
|
11
|
-
"clean": "rimraf dist",
|
|
12
|
-
"test": "jest --passWithNoTests"
|
|
13
|
-
},
|
|
14
|
-
"keywords": [
|
|
15
|
-
"oast",
|
|
16
|
-
"security",
|
|
17
|
-
"ssrf",
|
|
18
|
-
"callback",
|
|
19
|
-
"audit",
|
|
20
|
-
"pentest"
|
|
21
|
-
],
|
|
22
|
-
"author": "Jérémy",
|
|
23
|
-
"license": "MIT",
|
|
24
|
-
"dependencies": {
|
|
25
|
-
"body-parser": "^1.20.2",
|
|
26
|
-
"cors": "^2.8.5",
|
|
27
|
-
"dotenv": "^16.4.5",
|
|
28
|
-
"express": "^4.19.2",
|
|
29
|
-
"ioredis": "^5.4.1",
|
|
30
|
-
"ws": "^8.21.0"
|
|
31
|
-
},
|
|
32
|
-
"devDependencies": {
|
|
33
|
-
"@types/body-parser": "^1.19.5",
|
|
34
|
-
"@types/cors": "^2.8.17",
|
|
35
|
-
"@types/express": "^4.17.21",
|
|
36
|
-
"@types/jest": "^29.5.14",
|
|
37
|
-
"@types/node": "^20.12.7",
|
|
38
|
-
"@types/ws": "^8.18.1",
|
|
39
|
-
"jest": "^29.7.0",
|
|
40
|
-
"rimraf": "^5.0.5",
|
|
41
|
-
"ts-jest": "^29.4.11",
|
|
42
|
-
"ts-node-dev": "^2.0.0",
|
|
43
|
-
"typescript": "^5.4.5"
|
|
44
|
-
}
|
|
45
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@j3r3mcdev/oast-server",
|
|
3
|
+
"version": "1.1.1",
|
|
4
|
+
"description": "Modular OAST callback server for security auditing",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"dev": "ts-node-dev --respawn --transpile-only src/core/server.ts",
|
|
9
|
+
"build": "tsc -p tsconfig.json",
|
|
10
|
+
"start": "node dist/core/server.js",
|
|
11
|
+
"clean": "rimraf dist",
|
|
12
|
+
"test": "jest --passWithNoTests"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"oast",
|
|
16
|
+
"security",
|
|
17
|
+
"ssrf",
|
|
18
|
+
"callback",
|
|
19
|
+
"audit",
|
|
20
|
+
"pentest"
|
|
21
|
+
],
|
|
22
|
+
"author": "Jérémy",
|
|
23
|
+
"license": "MIT",
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"body-parser": "^1.20.2",
|
|
26
|
+
"cors": "^2.8.5",
|
|
27
|
+
"dotenv": "^16.4.5",
|
|
28
|
+
"express": "^4.19.2",
|
|
29
|
+
"ioredis": "^5.4.1",
|
|
30
|
+
"ws": "^8.21.0"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@types/body-parser": "^1.19.5",
|
|
34
|
+
"@types/cors": "^2.8.17",
|
|
35
|
+
"@types/express": "^4.17.21",
|
|
36
|
+
"@types/jest": "^29.5.14",
|
|
37
|
+
"@types/node": "^20.12.7",
|
|
38
|
+
"@types/ws": "^8.18.1",
|
|
39
|
+
"jest": "^29.7.0",
|
|
40
|
+
"rimraf": "^5.0.5",
|
|
41
|
+
"ts-jest": "^29.4.11",
|
|
42
|
+
"ts-node-dev": "^2.0.0",
|
|
43
|
+
"typescript": "^5.4.5"
|
|
44
|
+
}
|
|
45
|
+
}
|