briar-pentest 0.3.0__tar.gz
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.
- briar_pentest-0.3.0/LICENSE +18 -0
- briar_pentest-0.3.0/PKG-INFO +178 -0
- briar_pentest-0.3.0/README.md +138 -0
- briar_pentest-0.3.0/briar/__init__.py +2 -0
- briar_pentest-0.3.0/briar/__main__.py +3 -0
- briar_pentest-0.3.0/briar/agents/__init__.py +25 -0
- briar_pentest-0.3.0/briar/agents/analyzer.py +81 -0
- briar_pentest-0.3.0/briar/agents/api.py +94 -0
- briar_pentest-0.3.0/briar/agents/auth.py +141 -0
- briar_pentest-0.3.0/briar/agents/authz.py +95 -0
- briar_pentest-0.3.0/briar/agents/csrf.py +76 -0
- briar_pentest-0.3.0/briar/agents/injection.py +120 -0
- briar_pentest-0.3.0/briar/agents/rce.py +109 -0
- briar_pentest-0.3.0/briar/agents/recon.py +104 -0
- briar_pentest-0.3.0/briar/agents/secrets.py +37 -0
- briar_pentest-0.3.0/briar/agents/ssrf.py +99 -0
- briar_pentest-0.3.0/briar/agents/traversal.py +91 -0
- briar_pentest-0.3.0/briar/agents/upload.py +85 -0
- briar_pentest-0.3.0/briar/agents/xss.py +96 -0
- briar_pentest-0.3.0/briar/charts/__init__.py +0 -0
- briar_pentest-0.3.0/briar/charts/generator.py +55 -0
- briar_pentest-0.3.0/briar/cli.py +377 -0
- briar_pentest-0.3.0/briar/config.py +35 -0
- briar_pentest-0.3.0/briar/core/__init__.py +2 -0
- briar_pentest-0.3.0/briar/core/http.py +115 -0
- briar_pentest-0.3.0/briar/core/validator.py +78 -0
- briar_pentest-0.3.0/briar/core/workspace.py +72 -0
- briar_pentest-0.3.0/briar/exploits/__init__.py +2 -0
- briar_pentest-0.3.0/briar/exploits/browser.py +86 -0
- briar_pentest-0.3.0/briar/providers/__init__.py +24 -0
- briar_pentest-0.3.0/briar/providers/anthropic.py +25 -0
- briar_pentest-0.3.0/briar/providers/custom.py +13 -0
- briar_pentest-0.3.0/briar/providers/deepseek.py +22 -0
- briar_pentest-0.3.0/briar/providers/google.py +15 -0
- briar_pentest-0.3.0/briar/providers/groq.py +24 -0
- briar_pentest-0.3.0/briar/providers/mistral.py +24 -0
- briar_pentest-0.3.0/briar/providers/ollama.py +42 -0
- briar_pentest-0.3.0/briar/providers/openai.py +24 -0
- briar_pentest-0.3.0/briar/providers/openrouter.py +15 -0
- briar_pentest-0.3.0/briar/providers/together.py +12 -0
- briar_pentest-0.3.0/briar/providers/xai.py +15 -0
- briar_pentest-0.3.0/briar/reports/__init__.py +0 -0
- briar_pentest-0.3.0/briar/reports/generator.py +164 -0
- briar_pentest-0.3.0/briar/reports/obsidian.py +88 -0
- briar_pentest-0.3.0/briar/slides/__init__.py +0 -0
- briar_pentest-0.3.0/briar/slides/pptx_gen.py +150 -0
- briar_pentest-0.3.0/briar/web.py +148 -0
- briar_pentest-0.3.0/briar/worker.py +69 -0
- briar_pentest-0.3.0/briar_pentest.egg-info/PKG-INFO +178 -0
- briar_pentest-0.3.0/briar_pentest.egg-info/SOURCES.txt +55 -0
- briar_pentest-0.3.0/briar_pentest.egg-info/dependency_links.txt +1 -0
- briar_pentest-0.3.0/briar_pentest.egg-info/entry_points.txt +2 -0
- briar_pentest-0.3.0/briar_pentest.egg-info/requires.txt +13 -0
- briar_pentest-0.3.0/briar_pentest.egg-info/top_level.txt +1 -0
- briar_pentest-0.3.0/pyproject.toml +48 -0
- briar_pentest-0.3.0/setup.cfg +4 -0
- briar_pentest-0.3.0/setup.py +27 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
GNU AFFERO GENERAL PUBLIC LICENSE
|
|
2
|
+
Version 3, 19 November 2007
|
|
3
|
+
|
|
4
|
+
Copyright (C) 2026 Stiimy (Keran JOBLON)
|
|
5
|
+
|
|
6
|
+
Briar — Autonomous AI Pentester
|
|
7
|
+
This program is free software: you can redistribute it and/or modify
|
|
8
|
+
it under the terms of the GNU Affero General Public License as published
|
|
9
|
+
by the Free Software Foundation, either version 3 of the License, or
|
|
10
|
+
(at your option) any later version.
|
|
11
|
+
|
|
12
|
+
This program is distributed in the hope that it will be useful,
|
|
13
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15
|
+
GNU Affero General Public License for more details.
|
|
16
|
+
|
|
17
|
+
You should have received a copy of the GNU Affero General Public License
|
|
18
|
+
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: briar-pentest
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: Autonomous AI Pentester — find vulnerabilities before hackers do
|
|
5
|
+
Home-page: https://github.com/Stiimy/briar
|
|
6
|
+
Author: Stiimy
|
|
7
|
+
Author-email: Stiimy <keran.joblon@outlook.fr>
|
|
8
|
+
License: AGPL-3.0
|
|
9
|
+
Project-URL: Homepage, https://github.com/Stiimy/briar
|
|
10
|
+
Project-URL: Repository, https://github.com/Stiimy/briar
|
|
11
|
+
Project-URL: Issues, https://github.com/Stiimy/briar/issues
|
|
12
|
+
Keywords: security,pentest,vulnerability,owasp,ai,ollama
|
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Intended Audience :: Information Technology
|
|
16
|
+
Classifier: License :: OSI Approved :: GNU Affero General Public License v3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
20
|
+
Classifier: Topic :: Security
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
License-File: LICENSE
|
|
24
|
+
Requires-Dist: requests>=2.31
|
|
25
|
+
Requires-Dist: click>=8.1
|
|
26
|
+
Requires-Dist: rich>=13.7
|
|
27
|
+
Requires-Dist: fastapi>=0.115
|
|
28
|
+
Requires-Dist: uvicorn>=0.30
|
|
29
|
+
Provides-Extra: full
|
|
30
|
+
Requires-Dist: python-docx>=1.1; extra == "full"
|
|
31
|
+
Requires-Dist: openpyxl>=3.1; extra == "full"
|
|
32
|
+
Requires-Dist: python-pptx>=0.6; extra == "full"
|
|
33
|
+
Requires-Dist: matplotlib>=3.8; extra == "full"
|
|
34
|
+
Requires-Dist: plotly>=5.18; extra == "full"
|
|
35
|
+
Requires-Dist: selenium>=4.15; extra == "full"
|
|
36
|
+
Dynamic: author
|
|
37
|
+
Dynamic: home-page
|
|
38
|
+
Dynamic: license-file
|
|
39
|
+
Dynamic: requires-python
|
|
40
|
+
|
|
41
|
+
# 🥀 Briar — Autonomous AI Pentester
|
|
42
|
+
|
|
43
|
+
> *Find vulnerabilities before hackers do. Free. Open Source. No Docker required.*
|
|
44
|
+
|
|
45
|
+
[](https://python.org)
|
|
46
|
+
[](LICENSE)
|
|
47
|
+
[](https://ollama.ai)
|
|
48
|
+
[](https://github.com/Stiimy/briar/releases)
|
|
49
|
+
|
|
50
|
+
Briar is an autonomous AI pentester. It scans web applications, injects real payloads, validates exploits, and generates professional security reports — powered by **11 AI providers** including a completely free local mode via Ollama.
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Quick Start
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
pip install briar
|
|
58
|
+
briar setup # Pick your AI provider (Ollama = free)
|
|
59
|
+
briar scan -u https://target.com --quick
|
|
60
|
+
briar serve # Web dashboard → http://localhost:8233
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Features
|
|
66
|
+
|
|
67
|
+
| Category | Details |
|
|
68
|
+
|----------|---------|
|
|
69
|
+
| 🤖 **11 AI Providers** | Ollama (free, local), OpenAI, Claude, DeepSeek, Groq, Mistral, xAI/Grok, Google/Gemini, OpenRouter, Together, Custom |
|
|
70
|
+
| 🛡️ **10 OWASP Agents** | Recon, Injection, XSS, SSRF, Auth, AuthZ, CSRF, Upload, Traversal, RCE, API, Secrets |
|
|
71
|
+
| 🎯 **No Exploit, No Report** | Every High/Critical finding is replayed and confirmed before reporting |
|
|
72
|
+
| 🔌 **Blackbox + Whitebox** | Works with just a URL. Add `-r /path/to/source` for code-aware analysis |
|
|
73
|
+
| 📡 **Port Scanning** | 24 common ports scanned during recon phase |
|
|
74
|
+
| 📄 **Reports** | Markdown, Word (.docx), Excel (.xlsx), Obsidian vault + canvas mindmap |
|
|
75
|
+
| 🎨 **Slides** | PowerPoint (.pptx) + HTML presentation |
|
|
76
|
+
| 📊 **Charts** | Severity pie chart, agent bar chart |
|
|
77
|
+
| 🌐 **Dashboard** | Web UI on port 8233 (FastAPI) with scan launcher |
|
|
78
|
+
| 💾 **Workspaces** | Resume interrupted scans, checkpoint after every agent |
|
|
79
|
+
| ⚙️ **YAML Config** | Authenticated scanning, login flows, custom rules (avoid/focus paths) |
|
|
80
|
+
| 🐳 **No Docker Required** | Native Python. pip install and go. Docker optional for server mode. |
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## Usage
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
# Quick scan (4 agents)
|
|
88
|
+
briar scan -u https://target.com --quick
|
|
89
|
+
|
|
90
|
+
# Standard scan (8 agents)
|
|
91
|
+
briar scan -u https://target.com
|
|
92
|
+
|
|
93
|
+
# Deep scan (all 12 agents + browser exploits)
|
|
94
|
+
briar scan -u https://target.com --deep
|
|
95
|
+
|
|
96
|
+
# With source code (whitebox mode)
|
|
97
|
+
briar scan -u https://target.com -r /path/to/repo
|
|
98
|
+
|
|
99
|
+
# With DeepSeek provider (set env var first)
|
|
100
|
+
export DEEPSEEK_API_KEY=sk-xxx
|
|
101
|
+
briar scan -u https://target.com -p deepseek
|
|
102
|
+
|
|
103
|
+
# With config file (authenticated scanning)
|
|
104
|
+
briar scan -c juice-shop.yaml
|
|
105
|
+
|
|
106
|
+
# Resume an interrupted scan
|
|
107
|
+
briar scan --resume workspace-name
|
|
108
|
+
|
|
109
|
+
# List saved workspaces
|
|
110
|
+
briar workspaces
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## Config File (YAML)
|
|
116
|
+
|
|
117
|
+
```yaml
|
|
118
|
+
# juice-shop.yaml — example for OWASP Juice Shop
|
|
119
|
+
target:
|
|
120
|
+
url: http://localhost:3000
|
|
121
|
+
|
|
122
|
+
provider: deepseek
|
|
123
|
+
mode: deep
|
|
124
|
+
output: ./reports/juice-shop
|
|
125
|
+
|
|
126
|
+
authentication:
|
|
127
|
+
login_url: /rest/user/login
|
|
128
|
+
method: json
|
|
129
|
+
credentials:
|
|
130
|
+
email: test@test.com
|
|
131
|
+
password: test123
|
|
132
|
+
success_condition: "status=200"
|
|
133
|
+
|
|
134
|
+
rules:
|
|
135
|
+
avoid:
|
|
136
|
+
- path: /logout
|
|
137
|
+
- path: /score-board
|
|
138
|
+
focus:
|
|
139
|
+
- path: /api
|
|
140
|
+
- path: /rest
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## Architecture
|
|
146
|
+
|
|
147
|
+
```
|
|
148
|
+
briar/
|
|
149
|
+
├── agents/ 12 security agents (recon, injection, xss, ssrf,
|
|
150
|
+
│ auth, authz, csrf, upload, traversal, rce, api, secrets)
|
|
151
|
+
├── providers/ 11 AI backends (Ollama, OpenAI, Claude, DeepSeek, ...)
|
|
152
|
+
├── core/ HTTP client, exploit validator, workspace manager
|
|
153
|
+
├── exploits/ Selenium browser exploits + CLI payload injector
|
|
154
|
+
├── reports/ Markdown, Word, Excel, Obsidian generators
|
|
155
|
+
├── charts/ Pie chart + bar chart (matplotlib)
|
|
156
|
+
├── slides/ PowerPoint + HTML slide decks
|
|
157
|
+
├── cli.py Main CLI (click + rich)
|
|
158
|
+
├── web.py FastAPI dashboard (port 8233)
|
|
159
|
+
├── worker.py Background job queue worker
|
|
160
|
+
└── config.py YAML config loader
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## Install from Source
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
git clone https://github.com/Stiimy/briar
|
|
169
|
+
cd briar
|
|
170
|
+
pip install -e .
|
|
171
|
+
briar setup
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
> *"No exploit, no report."* — Briar validates every High/Critical finding before you see it.
|
|
177
|
+
|
|
178
|
+
**License:** AGPL-3.0 — Free. Forever.
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# 🥀 Briar — Autonomous AI Pentester
|
|
2
|
+
|
|
3
|
+
> *Find vulnerabilities before hackers do. Free. Open Source. No Docker required.*
|
|
4
|
+
|
|
5
|
+
[](https://python.org)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
[](https://ollama.ai)
|
|
8
|
+
[](https://github.com/Stiimy/briar/releases)
|
|
9
|
+
|
|
10
|
+
Briar is an autonomous AI pentester. It scans web applications, injects real payloads, validates exploits, and generates professional security reports — powered by **11 AI providers** including a completely free local mode via Ollama.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Quick Start
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
pip install briar
|
|
18
|
+
briar setup # Pick your AI provider (Ollama = free)
|
|
19
|
+
briar scan -u https://target.com --quick
|
|
20
|
+
briar serve # Web dashboard → http://localhost:8233
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Features
|
|
26
|
+
|
|
27
|
+
| Category | Details |
|
|
28
|
+
|----------|---------|
|
|
29
|
+
| 🤖 **11 AI Providers** | Ollama (free, local), OpenAI, Claude, DeepSeek, Groq, Mistral, xAI/Grok, Google/Gemini, OpenRouter, Together, Custom |
|
|
30
|
+
| 🛡️ **10 OWASP Agents** | Recon, Injection, XSS, SSRF, Auth, AuthZ, CSRF, Upload, Traversal, RCE, API, Secrets |
|
|
31
|
+
| 🎯 **No Exploit, No Report** | Every High/Critical finding is replayed and confirmed before reporting |
|
|
32
|
+
| 🔌 **Blackbox + Whitebox** | Works with just a URL. Add `-r /path/to/source` for code-aware analysis |
|
|
33
|
+
| 📡 **Port Scanning** | 24 common ports scanned during recon phase |
|
|
34
|
+
| 📄 **Reports** | Markdown, Word (.docx), Excel (.xlsx), Obsidian vault + canvas mindmap |
|
|
35
|
+
| 🎨 **Slides** | PowerPoint (.pptx) + HTML presentation |
|
|
36
|
+
| 📊 **Charts** | Severity pie chart, agent bar chart |
|
|
37
|
+
| 🌐 **Dashboard** | Web UI on port 8233 (FastAPI) with scan launcher |
|
|
38
|
+
| 💾 **Workspaces** | Resume interrupted scans, checkpoint after every agent |
|
|
39
|
+
| ⚙️ **YAML Config** | Authenticated scanning, login flows, custom rules (avoid/focus paths) |
|
|
40
|
+
| 🐳 **No Docker Required** | Native Python. pip install and go. Docker optional for server mode. |
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Usage
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
# Quick scan (4 agents)
|
|
48
|
+
briar scan -u https://target.com --quick
|
|
49
|
+
|
|
50
|
+
# Standard scan (8 agents)
|
|
51
|
+
briar scan -u https://target.com
|
|
52
|
+
|
|
53
|
+
# Deep scan (all 12 agents + browser exploits)
|
|
54
|
+
briar scan -u https://target.com --deep
|
|
55
|
+
|
|
56
|
+
# With source code (whitebox mode)
|
|
57
|
+
briar scan -u https://target.com -r /path/to/repo
|
|
58
|
+
|
|
59
|
+
# With DeepSeek provider (set env var first)
|
|
60
|
+
export DEEPSEEK_API_KEY=sk-xxx
|
|
61
|
+
briar scan -u https://target.com -p deepseek
|
|
62
|
+
|
|
63
|
+
# With config file (authenticated scanning)
|
|
64
|
+
briar scan -c juice-shop.yaml
|
|
65
|
+
|
|
66
|
+
# Resume an interrupted scan
|
|
67
|
+
briar scan --resume workspace-name
|
|
68
|
+
|
|
69
|
+
# List saved workspaces
|
|
70
|
+
briar workspaces
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Config File (YAML)
|
|
76
|
+
|
|
77
|
+
```yaml
|
|
78
|
+
# juice-shop.yaml — example for OWASP Juice Shop
|
|
79
|
+
target:
|
|
80
|
+
url: http://localhost:3000
|
|
81
|
+
|
|
82
|
+
provider: deepseek
|
|
83
|
+
mode: deep
|
|
84
|
+
output: ./reports/juice-shop
|
|
85
|
+
|
|
86
|
+
authentication:
|
|
87
|
+
login_url: /rest/user/login
|
|
88
|
+
method: json
|
|
89
|
+
credentials:
|
|
90
|
+
email: test@test.com
|
|
91
|
+
password: test123
|
|
92
|
+
success_condition: "status=200"
|
|
93
|
+
|
|
94
|
+
rules:
|
|
95
|
+
avoid:
|
|
96
|
+
- path: /logout
|
|
97
|
+
- path: /score-board
|
|
98
|
+
focus:
|
|
99
|
+
- path: /api
|
|
100
|
+
- path: /rest
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## Architecture
|
|
106
|
+
|
|
107
|
+
```
|
|
108
|
+
briar/
|
|
109
|
+
├── agents/ 12 security agents (recon, injection, xss, ssrf,
|
|
110
|
+
│ auth, authz, csrf, upload, traversal, rce, api, secrets)
|
|
111
|
+
├── providers/ 11 AI backends (Ollama, OpenAI, Claude, DeepSeek, ...)
|
|
112
|
+
├── core/ HTTP client, exploit validator, workspace manager
|
|
113
|
+
├── exploits/ Selenium browser exploits + CLI payload injector
|
|
114
|
+
├── reports/ Markdown, Word, Excel, Obsidian generators
|
|
115
|
+
├── charts/ Pie chart + bar chart (matplotlib)
|
|
116
|
+
├── slides/ PowerPoint + HTML slide decks
|
|
117
|
+
├── cli.py Main CLI (click + rich)
|
|
118
|
+
├── web.py FastAPI dashboard (port 8233)
|
|
119
|
+
├── worker.py Background job queue worker
|
|
120
|
+
└── config.py YAML config loader
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## Install from Source
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
git clone https://github.com/Stiimy/briar
|
|
129
|
+
cd briar
|
|
130
|
+
pip install -e .
|
|
131
|
+
briar setup
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
> *"No exploit, no report."* — Briar validates every High/Critical finding before you see it.
|
|
137
|
+
|
|
138
|
+
**License:** AGPL-3.0 — Free. Forever.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from .analyzer import SecurityAnalyzer
|
|
2
|
+
from .recon import ReconAgent
|
|
3
|
+
from .injection import InjectionAgent
|
|
4
|
+
from .xss import XSSAgent
|
|
5
|
+
from .ssrf import SSRFAgent
|
|
6
|
+
from .auth import AuthAgent
|
|
7
|
+
from .authz import AuthZAgent
|
|
8
|
+
from .csrf import CSRFAgent
|
|
9
|
+
from .upload import UploadAgent
|
|
10
|
+
from .traversal import TraversalAgent
|
|
11
|
+
from .rce import RCEAgent
|
|
12
|
+
from .api import APIAgent
|
|
13
|
+
from .secrets import SecretsAgent
|
|
14
|
+
|
|
15
|
+
AGENTS = {
|
|
16
|
+
"recon": ReconAgent, "injection": InjectionAgent, "xss": XSSAgent, "ssrf": SSRFAgent,
|
|
17
|
+
"auth": AuthAgent, "authz": AuthZAgent, "csrf": CSRFAgent,
|
|
18
|
+
"upload": UploadAgent, "traversal": TraversalAgent,
|
|
19
|
+
"rce": RCEAgent, "api": APIAgent, "secrets": SecretsAgent,
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
def run_agent(name, provider="ollama", **kwargs):
|
|
23
|
+
if name not in AGENTS:
|
|
24
|
+
return {"error": f"Agent '{name}' not found. Available: {list(AGENTS.keys())}"}
|
|
25
|
+
return AGENTS[name](provider).scan(**kwargs)
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"""Briar AI Analysis Engine — the brain of the pentest 🧠"""
|
|
2
|
+
from typing import Optional
|
|
3
|
+
from briar.providers import get_provider
|
|
4
|
+
|
|
5
|
+
SECURITY_ANALYST_PROMPT = """You are an elite security researcher performing a penetration test.
|
|
6
|
+
Analyze the target and identify vulnerabilities. For each finding, provide:
|
|
7
|
+
|
|
8
|
+
1. VULNERABILITY TYPE (OWASP category)
|
|
9
|
+
2. SEVERITY (Critical/High/Medium/Low)
|
|
10
|
+
3. CVSS SCORE (0.0-10.0)
|
|
11
|
+
4. ENDPOINT / LOCATION
|
|
12
|
+
5. DESCRIPTION (what the vuln is)
|
|
13
|
+
6. EXPLOIT STEPS (how to reproduce)
|
|
14
|
+
7. IMPACT (what an attacker can do)
|
|
15
|
+
8. REMEDIATION (how to fix)
|
|
16
|
+
|
|
17
|
+
Be specific. Include exact URLs, parameters, payloads. Think like an attacker."""
|
|
18
|
+
|
|
19
|
+
class SecurityAnalyzer:
|
|
20
|
+
"""Core AI security analysis engine"""
|
|
21
|
+
|
|
22
|
+
def __init__(self, provider: str = "ollama", model: Optional[str] = None):
|
|
23
|
+
self.provider = get_provider(provider, model=model) if model else get_provider(provider)
|
|
24
|
+
|
|
25
|
+
def analyze_endpoint(self, url: str, method: str = "GET", source_hint: str = "") -> dict:
|
|
26
|
+
"""Analyze a single endpoint for vulnerabilities"""
|
|
27
|
+
prompt = f"""Analyze this endpoint for security vulnerabilities:
|
|
28
|
+
|
|
29
|
+
URL: {url}
|
|
30
|
+
Method: {method}
|
|
31
|
+
{f'Source code context: {source_hint}' if source_hint else ''}
|
|
32
|
+
|
|
33
|
+
List ALL potential vulnerabilities you find. For each one, provide the full details as specified."""
|
|
34
|
+
|
|
35
|
+
messages = [{"role": "user", "content": prompt}]
|
|
36
|
+
response = self.provider.chat(messages, system=SECURITY_ANALYST_PROMPT, max_tokens=4096)
|
|
37
|
+
return {"url": url, "analysis": response, "raw": response}
|
|
38
|
+
|
|
39
|
+
def analyze_code(self, code: str, filepath: str = "") -> dict:
|
|
40
|
+
"""Analyze source code for vulnerabilities"""
|
|
41
|
+
prompt = f"""Analyze this source code for security vulnerabilities:
|
|
42
|
+
|
|
43
|
+
File: {filepath}
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
{code[:8000]}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Find: SQL injection, XSS, SSRF, command injection, path traversal, auth bypass,
|
|
50
|
+
deserialization, hardcoded secrets, unsafe eval, etc.
|
|
51
|
+
|
|
52
|
+
For each finding, specify the exact line and how to exploit it."""
|
|
53
|
+
|
|
54
|
+
messages = [{"role": "user", "content": prompt}]
|
|
55
|
+
response = self.provider.chat(messages, system=SECURITY_ANALYST_PROMPT, max_tokens=4096)
|
|
56
|
+
return {"file": filepath, "analysis": response}
|
|
57
|
+
|
|
58
|
+
def generate_report(self, findings: list, target: str) -> str:
|
|
59
|
+
"""Generate a comprehensive security report"""
|
|
60
|
+
findings_text = "\n\n---\n\n".join([
|
|
61
|
+
f"## Finding {i+1}\n{f.get('analysis', f.get('raw',''))}"
|
|
62
|
+
for i, f in enumerate(findings)
|
|
63
|
+
])
|
|
64
|
+
|
|
65
|
+
prompt = f"""Generate a PROFESSIONAL penetration test report for {target}.
|
|
66
|
+
|
|
67
|
+
Findings:
|
|
68
|
+
{findings_text[:6000]}
|
|
69
|
+
|
|
70
|
+
Create a structured report with:
|
|
71
|
+
1. Executive Summary
|
|
72
|
+
2. Methodology
|
|
73
|
+
3. Findings (detailed per vulnerability)
|
|
74
|
+
4. Risk Matrix
|
|
75
|
+
5. Recommendations
|
|
76
|
+
6. Conclusion
|
|
77
|
+
|
|
78
|
+
Format in Markdown. Be professional and precise."""
|
|
79
|
+
|
|
80
|
+
messages = [{"role": "user", "content": prompt}]
|
|
81
|
+
return self.provider.chat(messages, system="You are a senior security consultant writing a pentest report.", max_tokens=8192)
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"""API Security Agent — GraphQL, REST, OpenAPI detection 📡"""
|
|
2
|
+
from briar.agents.analyzer import SecurityAnalyzer
|
|
3
|
+
from briar.core.http import HTTPClient
|
|
4
|
+
|
|
5
|
+
class APIAgent:
|
|
6
|
+
"""Detects API endpoints and tests for common misconfigurations"""
|
|
7
|
+
|
|
8
|
+
API_PATHS = [
|
|
9
|
+
("/graphql", "GraphQL endpoint"),
|
|
10
|
+
("/graphiql", "GraphQL IDE"),
|
|
11
|
+
("/api", "REST API"),
|
|
12
|
+
("/api/v1", "REST API v1"),
|
|
13
|
+
("/api/v2", "REST API v2"),
|
|
14
|
+
("/swagger.json", "Swagger/OpenAPI spec"),
|
|
15
|
+
("/openapi.json", "OpenAPI 3.0 spec"),
|
|
16
|
+
("/api-docs", "API docs"),
|
|
17
|
+
("/docs", "API docs"),
|
|
18
|
+
("/.well-known/openid-configuration", "OIDC config"),
|
|
19
|
+
("/wp-json/", "WordPress REST API"),
|
|
20
|
+
("/v1/", "API v1 prefix"),
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
GRAPHQL_INTROSPECTION = {
|
|
24
|
+
"query": "{ __schema { types { name fields { name } } } }"
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
def __init__(self, provider="ollama"):
|
|
28
|
+
self.analyzer = SecurityAnalyzer(provider)
|
|
29
|
+
self.http = HTTPClient(timeout=10)
|
|
30
|
+
self.name = "API"
|
|
31
|
+
|
|
32
|
+
def scan(self, url: str, **kwargs) -> dict:
|
|
33
|
+
"""Detect API endpoints and test security"""
|
|
34
|
+
findings = []
|
|
35
|
+
discovered = []
|
|
36
|
+
|
|
37
|
+
# Check common API paths
|
|
38
|
+
for path, desc in self.API_PATHS:
|
|
39
|
+
try:
|
|
40
|
+
full_url = url.rstrip("/") + path
|
|
41
|
+
resp = self.http.get(full_url)
|
|
42
|
+
if resp.status_code in [200, 301, 302, 401, 403]:
|
|
43
|
+
discovered.append({"path": path, "desc": desc, "status": resp.status_code, "length": len(resp.text)})
|
|
44
|
+
|
|
45
|
+
# GraphQL introspection test
|
|
46
|
+
if "graphql" in path.lower() and resp.status_code == 200:
|
|
47
|
+
try:
|
|
48
|
+
intro_resp = self.http.post(full_url, json=self.GRAPHQL_INTROSPECTION)
|
|
49
|
+
if "__schema" in intro_resp.text or "types" in intro_resp.text:
|
|
50
|
+
findings.append({
|
|
51
|
+
"type": "GraphQL Introspection Enabled",
|
|
52
|
+
"severity": "Medium",
|
|
53
|
+
"endpoint": full_url,
|
|
54
|
+
"detail": "Schema fully exposed via introspection query",
|
|
55
|
+
})
|
|
56
|
+
except:
|
|
57
|
+
pass
|
|
58
|
+
|
|
59
|
+
# Rate limiting check
|
|
60
|
+
if "api" in path.lower() and resp.status_code == 200:
|
|
61
|
+
for _ in range(5):
|
|
62
|
+
try:
|
|
63
|
+
r = self.http.get(full_url)
|
|
64
|
+
if r.status_code == 429:
|
|
65
|
+
findings.append({
|
|
66
|
+
"type": "Rate Limiting Active",
|
|
67
|
+
"severity": "Info",
|
|
68
|
+
"endpoint": full_url,
|
|
69
|
+
})
|
|
70
|
+
break
|
|
71
|
+
except:
|
|
72
|
+
pass
|
|
73
|
+
|
|
74
|
+
except:
|
|
75
|
+
pass
|
|
76
|
+
|
|
77
|
+
analysis = f"API scan complete for {url}\n\n"
|
|
78
|
+
analysis += f"Endpoints discovered: {len(discovered)}\n\n"
|
|
79
|
+
for d in discovered:
|
|
80
|
+
analysis += f"- `{d['path']}` — {d['desc']} (HTTP {d['status']})\n"
|
|
81
|
+
|
|
82
|
+
if findings:
|
|
83
|
+
analysis += f"\n**{len(findings)} API security issues found:**\n\n"
|
|
84
|
+
for f in findings:
|
|
85
|
+
analysis += f"- **{f['type']}**: {f.get('endpoint','?')} — {f.get('detail','')}\n"
|
|
86
|
+
analysis += "\n---\n\nLLM analysis of real API findings:\n"
|
|
87
|
+
|
|
88
|
+
result = self.analyzer.analyze_endpoint(url, "GET", analysis)
|
|
89
|
+
result["real_findings"] = findings
|
|
90
|
+
result["discovered_endpoints"] = [d["path"] for d in discovered]
|
|
91
|
+
result["agent"] = self.name
|
|
92
|
+
result["type"] = "API Security"
|
|
93
|
+
result["severity"] = "Medium" if findings else "Info"
|
|
94
|
+
return result
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
"""Authentication Attack Agent — JWT, brute force, token analysis 🔐"""
|
|
2
|
+
import re
|
|
3
|
+
from briar.agents.analyzer import SecurityAnalyzer
|
|
4
|
+
from briar.core.http import HTTPClient
|
|
5
|
+
|
|
6
|
+
class AuthAgent:
|
|
7
|
+
"""Discovers authentication vulnerabilities"""
|
|
8
|
+
|
|
9
|
+
WEAK_CREDS = [
|
|
10
|
+
("admin", "admin"), ("admin", "password"), ("admin", "123456"),
|
|
11
|
+
("test", "test"), ("guest", "guest"), ("user", "user"),
|
|
12
|
+
("root", "root"), ("admin", ""), ("administrator", "administrator"),
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
def __init__(self, provider="ollama"):
|
|
16
|
+
self.analyzer = SecurityAnalyzer(provider)
|
|
17
|
+
self.http = HTTPClient(timeout=10)
|
|
18
|
+
self.name = "Authentication"
|
|
19
|
+
|
|
20
|
+
def _detect_login_form(self, html: str) -> list:
|
|
21
|
+
"""Find login forms by looking for password inputs"""
|
|
22
|
+
login_forms = []
|
|
23
|
+
forms = self.http.extract_forms(html)
|
|
24
|
+
for form in forms:
|
|
25
|
+
if any("pass" in i.lower() for i in form["inputs"]):
|
|
26
|
+
login_forms.append(form)
|
|
27
|
+
return login_forms
|
|
28
|
+
|
|
29
|
+
def _test_jwt(self, jwt_str: str) -> list:
|
|
30
|
+
"""Test JWT for common vulnerabilities"""
|
|
31
|
+
import base64, json
|
|
32
|
+
findings = []
|
|
33
|
+
try:
|
|
34
|
+
parts = jwt_str.split(".")
|
|
35
|
+
if len(parts) != 3:
|
|
36
|
+
return findings
|
|
37
|
+
|
|
38
|
+
# Decode without verification
|
|
39
|
+
for i, part in enumerate(parts[:2]):
|
|
40
|
+
# Add padding
|
|
41
|
+
padded = part + "=" * (4 - len(part) % 4)
|
|
42
|
+
try:
|
|
43
|
+
decoded = base64.urlsafe_b64decode(padded)
|
|
44
|
+
findings.append({
|
|
45
|
+
"type": "JWT decoded without verification",
|
|
46
|
+
"severity": "Low",
|
|
47
|
+
"part": "header" if i == 0 else "payload",
|
|
48
|
+
"content": decoded.decode("utf-8", errors="replace")[:200],
|
|
49
|
+
})
|
|
50
|
+
except:
|
|
51
|
+
pass
|
|
52
|
+
|
|
53
|
+
# Check alg:none
|
|
54
|
+
header = parts[0]
|
|
55
|
+
padded = header + "=" * (4 - len(header) % 4)
|
|
56
|
+
decoded_header = base64.urlsafe_b64decode(padded).decode("utf-8", errors="replace")
|
|
57
|
+
if '"none"' in decoded_header.lower() or '"None"' in decoded_header:
|
|
58
|
+
findings.append({
|
|
59
|
+
"type": "JWT alg:none accepted",
|
|
60
|
+
"severity": "Critical",
|
|
61
|
+
"detail": "Algorithm allows 'none' — signature bypass possible",
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
except:
|
|
65
|
+
pass
|
|
66
|
+
return findings
|
|
67
|
+
|
|
68
|
+
def scan(self, url: str, auth_type: str = "unknown", **kwargs) -> dict:
|
|
69
|
+
"""Scan for authentication vulnerabilities"""
|
|
70
|
+
findings = []
|
|
71
|
+
|
|
72
|
+
try:
|
|
73
|
+
resp = self.http.get(url)
|
|
74
|
+
html = resp.text
|
|
75
|
+
|
|
76
|
+
# Check for JWT in cookies/headers
|
|
77
|
+
jwt_pattern = r'[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+'
|
|
78
|
+
for header_val in resp.headers.values():
|
|
79
|
+
for match in re.finditer(jwt_pattern, header_val):
|
|
80
|
+
jwt_findings = self._test_jwt(match.group(0))
|
|
81
|
+
findings.extend(jwt_findings)
|
|
82
|
+
for match in re.finditer(jwt_pattern, resp.text[:2000]):
|
|
83
|
+
jwt_findings = self._test_jwt(match.group(0))
|
|
84
|
+
findings.extend(jwt_findings)
|
|
85
|
+
|
|
86
|
+
# Find login forms and test weak creds
|
|
87
|
+
login_forms = self._detect_login_form(html)
|
|
88
|
+
for form in login_forms:
|
|
89
|
+
form_url = form["action"] or url
|
|
90
|
+
for username, password in self.WEAK_CREDS[:5]:
|
|
91
|
+
try:
|
|
92
|
+
data = {}
|
|
93
|
+
for inp in form["inputs"]:
|
|
94
|
+
if "user" in inp.lower() or "email" in inp.lower() or "login" in inp.lower():
|
|
95
|
+
data[inp] = username
|
|
96
|
+
elif "pass" in inp.lower():
|
|
97
|
+
data[inp] = password
|
|
98
|
+
else:
|
|
99
|
+
data[inp] = username
|
|
100
|
+
|
|
101
|
+
login_resp = self.http.post(form_url, data=data, allow_redirects=False)
|
|
102
|
+
if login_resp.status_code in [302, 200]:
|
|
103
|
+
# Check if login succeeded (no error message, redirect to dashboard)
|
|
104
|
+
text_lower = login_resp.text.lower()
|
|
105
|
+
if not any(e in text_lower for e in ["invalid", "incorrect", "wrong", "error", "failed"]):
|
|
106
|
+
findings.append({
|
|
107
|
+
"type": "Weak credentials",
|
|
108
|
+
"severity": "Critical",
|
|
109
|
+
"endpoint": form_url,
|
|
110
|
+
"credentials": f"{username}:{password}",
|
|
111
|
+
"response_status": login_resp.status_code,
|
|
112
|
+
})
|
|
113
|
+
break
|
|
114
|
+
except:
|
|
115
|
+
pass
|
|
116
|
+
|
|
117
|
+
if findings:
|
|
118
|
+
break # Found vuln, stop brute force
|
|
119
|
+
|
|
120
|
+
if not login_forms:
|
|
121
|
+
findings.append({"type": "No login form found", "severity": "Info"})
|
|
122
|
+
|
|
123
|
+
except Exception as e:
|
|
124
|
+
findings.append({"type": "Auth scan error", "error": str(e)})
|
|
125
|
+
|
|
126
|
+
analysis = f"Authentication scan complete for {url}\n\n"
|
|
127
|
+
if findings:
|
|
128
|
+
analysis += f"**{len(findings)} authentication issues found:**\n\n"
|
|
129
|
+
for f in findings:
|
|
130
|
+
if "credential" in str(f.get("type", "")).lower():
|
|
131
|
+
analysis += f"- **Weak credentials**: `{f.get('credentials','?')}` → {f.get('endpoint','?')}\n"
|
|
132
|
+
elif "jwt" in str(f.get("type", "")).lower():
|
|
133
|
+
analysis += f"- **{f['type']}**: {f.get('detail', f.get('content',''))}\n"
|
|
134
|
+
analysis += "\n---\n\nLLM analysis of auth findings:\n"
|
|
135
|
+
|
|
136
|
+
result = self.analyzer.analyze_endpoint(url, "GET/POST", analysis)
|
|
137
|
+
result["real_findings"] = findings
|
|
138
|
+
result["agent"] = self.name
|
|
139
|
+
result["type"] = "Authentication"
|
|
140
|
+
result["severity"] = "Critical" if any(f["severity"] == "Critical" for f in findings) else ("High" if findings else "Info")
|
|
141
|
+
return result
|