CYPR
针对 URL 和文件的确定性启发式威胁检测。
## 目录
- [项目状态](#project-status)
- [概述](#overview)
- [为什么选择 CYPR](#why-cypr)
- [问题陈述](#problem-statement)
- [解决方案](#solution)
- [核心功能](#key-features)
- [架构概述](#architecture-overview)
- [威胁分析 Pipeline](#threat-analysis-pipeline)
- [VAJRA 引擎](#vajra-engine)
- [技术栈](#technology-stack)
- [截图](#screenshots)
- [目录结构](#folder-structure)
- [REST API 概述](#rest-api-overview)
- [安装说明](#installation)
- [配置](#configuration)
- [本地运行](#running-locally)
- [Docker](#docker)
- [部署](#deployment)
- [安全](#security)
- [性能](#performance)
- [路线图](#roadmap)
- [文档](#documentation)
- [贡献](#contributing)
- [许可协议](#license)
- [作者](#author)
- [致谢](#acknowledgements)
## 项目状态
CYPR 正在积极开发中。身份验证、扫描和仪表盘功能已实现并可用。[路线图](#roadmap)中的项目仅为计划——它们被记录下来是为了保持透明,并不属于当前构建版本的一部分。
| | |
|---|---|
| 阶段 | 1.0 之前的版本,积极开发中 |
| API 稳定性 | v1.0 之前可能会发生变化 |
| 维护 | 积极维护中 |
## 概述
CYPR 通过专有的启发式引擎 VAJRA 检测钓鱼 URL 和恶意文件,并结合 VirusTotal 进行可选的验证。后端是一个 Spring Boot 应用程序,负责处理身份验证、扫描和持久化;前端是一个纯 HTML/CSS/JavaScript 仪表盘,用于提交扫描并查看结果。
VAJRA 不使用机器学习或任何形式的统计训练。每个信号都是一个固定的、手写的规则。给定相同的输入,VAJRA 总是返回相同的分数,并且该分数中的每一个点都可以追溯到生成它的具体规则。
## 为什么选择 CYPR
大多数钓鱼检测工具属于以下两类之一:
- **基于分类器的工具**通常很准确,但无法解释其判定结果——没有明确的规则可循,这使得它们难以审计。
- **基于黑名单的工具**完全可以解释,但只能捕获已经被报告的 URL,这对于用于短期活动的域名来说是个问题。
CYPR 采用第三种方法:一组固定的、独立的启发式规则。每个规则都有文档记录且可单独检查,无需 URL 已经存在于威胁情报源中即可对其进行评分。
## 问题陈述
钓鱼基础设施都是一次性的。攻击者注册一个域名,运行几个小时或几天的活动,然后在它出现在大多数黑名单或威胁情报源之前就将其废弃。完全依赖先前报告的检测将永远滞后于这个周期。
## 解决方案
CYPR 在请求时根据 16 个独立的启发式信号对每个提交的 URL 进行评分,因此判定结果并不依赖于该域名以前是否被见过。VirusTotal 集成可作为辅助检查手段,在需要二次确认时,将 URL 或文件与 70 多个第三方扫描引擎进行交叉比对。
## 核心功能
| 功能 | 描述 |
|---|---|
| URL 扫描器 | 通过 VAJRA 引擎进行实时 URL 风险评分 |
| 文件恶意软件扫描器 | 通过 VirusTotal API 进行文件上传扫描 |
| VAJRA 检测引擎 | 16 信号确定性启发式评分引擎 |
| 密码强度分析器 | 客户端密码强度评分 |
| 身份验证 | 基于 JWT 的会话,支持 Google OAuth 和 GitHub OAuth |
| 威胁历史记录 | 每个用户过去的扫描和判定结果记录 |
| 仪表盘 | 扫描活动和账户状态的集中查看界面 |
| 分析 | 随时间变化的汇总扫描趋势 |
| 安全新闻 | 来自 CISA、NIST、KrebsOnSecurity、BleepingComputer 和 The Hacker News 的聚合信息流 |
| 通知 | 针对扫描结果和账户事件的应用内提醒 |
| Bot 防护 | 在面向公众的表单上使用 Cloudflare Turnstile |
## 架构概述
系统分为三层:
- **前端** —— 一个静态的纯 JS 仪表盘,直接调用后端 REST API。没有服务端渲染,也没有前端框架。
- **后端** —— 一个 Spring Boot 应用程序,提供用于身份验证、扫描、历史记录和仪表盘数据的 REST endpoint。VAJRA 作为请求生命周期的一部分在进程内运行,而不是作为一个单独的服务。
- **数据和外部服务** —— 使用 PostgreSQL 进行持久化,VirusTotal 用于可选的二次验证,Brevo 用于事务性邮件,OAuth 提供商(Google、GitHub)用于第三方登录。
```
Client (vanilla JS) ─▶ Spring Boot REST API ─▶ Auth Interceptor
─▶ VAJRA Engine (in-process)
─▶ PostgreSQL
─▶ VirusTotal API (optional)
─▶ Brevo Email API
```
## 威胁分析 Pipeline
1. 客户端通过扫描 endpoint 提交 URL 或文件。
2. 认证拦截器验证 JWT,并拒绝未经认证或格式错误的请求。
3. 对输入进行标准化处理(URL 解析、协议处理、编码检查)。
4. VAJRA 根据其 16 个信号对输入进行评估,并生成加权风险评分。
5. 如果分数处于不确定的范围内,则可选择将输入与 VirusTotal 进行交叉核对。
6. 结果——包括分数、判定结果和每个信号的细分——将被持久化保存到威胁历史记录中。
7. 将完整的细分结果返回给客户端,而不仅仅是一个通过/失败的标签。
## VAJRA 引擎
VAJRA 是一个确定性的、多层次的启发式引擎。它不使用机器学习,不会从过去的扫描中“学习”,也不做任何预测性声明——每个信号都是一个具有明确文档说明的条件和权重的固定规则。
全部 16 个信号
| # | 信号 | 检查内容 |
|---|---|---|
| 1 | 香农熵分析 | 域名/子域名字符串中的随机性,常见于算法生成的域名 |
| 2 | N-gram 频率建模 | 字符序列模式,与典型的合法域名结构进行对比 |
| 3 | Levenshtein 距离 | 与已知品牌名称的编辑距离相似度(域名抢注/拼写错误) |
| 4 | 同形字检测 | 与 ASCII 字母在视觉上相似的 Unicode 字符(例如西里尔字母“а”与拉丁字母“a”) |
| 5 | 混合抢注检测 | 品牌名称与不相关词汇的组合(例如 `paypal-secure-login.com`) |
| 6 | 端口异常检测 | URL 中对于所声明服务不正常的非标准端口 |
| 7 | URL 长度启发式 | 异常长的 URL,通常用于掩盖真实目的地 |
| 8 | 子域名深度分析 | 过度的子域名嵌套,用于伪装实际的根域名 |
| 9 | 可疑 TLD 检测 | 与滥用行为密切相关且不成比例的顶级域名 |
| 10 | 基于 IP 的 URL 检测 | 使用原始 IP 地址代替域名 |
| 11 | URL 短链接检测 | 已知的会掩盖最终目的地的短链接服务 |
| 12 | 特殊字符比例 | 域名中连字符、数字或符号的异常密度 |
| 13 | 品牌关键词冒充 | 出现在其合法域名之外的知名品牌词汇 |
| 14 | SSL/TLS 证书检查 | 检查证书的存在性、有效性以及颁发者 |
| 15 | 域名年龄启发式 | 基于 WHOIS 查询的域名注册时间 |
| 16 | 重定向链分析 | 到达最终页面之前的重定向次数和目的地 |
每个信号都会贡献一个独立的加权分数。最终结果包含总分以及显示哪些信号被触发及其原因的详细说明。
## 技术栈
| 层级 | 技术 |
|---|---|
| 后端 | Java 17, Spring Boot 3.3, Maven, Spring Security, Hibernate |
| 数据库 | PostgreSQL |
| 前端 | HTML5, CSS3, JavaScript (无框架) |
| 身份验证 | JWT, Google OAuth, GitHub OAuth |
| 安全 | Cloudflare Turnstile, BCrypt, 自定义认证拦截器, IDOR/BOLA 防护 |
| 基础设施 | Docker, AWS EC2, AWS RDS, GitHub Actions, Vercel |
| 外部服务 | VirusTotal, Brevo Email API, OpenPhish, phishing.army |
| 威胁情报源 | CISA, NIST, KrebsOnSecurity, BleepingComputer, The Hacker News |
## 截图
## 目录结构
```
cypr/
├── backend/
│ ├── src/
│ │ ├── main/
│ │ │ ├── java/com/cypr/
│ │ │ │ ├── config/
│ │ │ │ ├── controller/
│ │ │ │ ├── service/
│ │ │ │ ├── engine/
│ │ │ │ ├── repository/
│ │ │ │ ├── entity/
│ │ │ │ └── model/
│ │ │ └── resources/
│ │ │ ├── application.properties
│ │ └── test/
│ ├── pom.xml
│ └── Dockerfile
├── frontend/
│ ├── assets/
│ ├── notifications.js
│ └── index.html
├── docker-compose.yml
├── .env.example
└── README.md
```
## REST API 概述
核心 endpoint
| 方法 | Endpoint | 描述 | 认证 |
|---|---|---|---|
| POST | `/api/user/register` | 创建新账户 | 否 |
| POST | `/api/user/login` | 认证并接收 JWT | 否 |
| GET | `/api/oauth/google/authorize` | 启动 Google OAuth 流程 | 否 |
| GET | `/api/oauth/github/authorize` | 启动 GitHub OAuth 流程 | 否 |
| POST | `/api/phish-check` | 提交 URL 以进行 VAJRA 分析 | 是 |
| POST | `/api/malware/scan` | 提交文件以进行恶意软件分析 | 是 |
| GET | `/api/malware/history/{userId}` | 获取已认证用户的扫描历史记录 | 是 |
| GET | `/api/stats/global-stats` | 获取汇总的仪表盘数据 | 是 |
完整的 endpoint 参考(包括请求/响应 schema)维护在 [`docs/api.md`](docs/api.md) 中。
## 安装说明
**前置条件**
- Java 17
- Maven 3.9+
- PostgreSQL 15+
- Docker(可选,用于容器化设置)
```
git clone https://github.com/iamvineetupadhyay/CYPR-Tech.git
cd CYPR-Tech
cp .env.example .env
# 在下方 Configuration 中描述的值内填入
```
## 配置
所有配置均通过环境变量提供,在本地开发中通过 `.env` 加载。
环境变量
| 变量 | 必需 | 描述 |
|---|---|---|
| `DB_URL` | 是 | PostgreSQL JDBC 连接字符串 |
| `DB_USERNAME` | 是 | 数据库用户名 |
| `DB_PASSWORD` | 是 | 数据库密码 |
| `JWT_SECRET` | 是 | JWT 的签名密钥 |
| `JWT_EXPIRATION` | 否 | token 生命周期(以秒为单位,默认:3600) |
| `GOOGLE_CLIENT_ID` | 是 | Google OAuth 客户端 ID |
| `GOOGLE_CLIENT_SECRET` | 是 | Google OAuth 客户端密钥 |
| `GITHUB_CLIENT_ID` | 是 | GitHub OAuth 客户端 ID |
| `GITHUB_CLIENT_SECRET` | 是 | GitHub OAuth 客户端密钥 |
| `VIRUSTOTAL_API_KEY` | 是 | 用于 VirusTotal 集成的 API 密钥 |
| `BREVO_API_KEY` | 是 | 用于事务性邮件的 API 密钥 |
| `CLOUDFLARE_TURNSTILE_SITE_KEY` | 是 | Turnstile 站点密钥 |
| `CLOUDFLARE_TURNSTILE_SECRET_KEY` | 是 | Turnstile 密钥 |
| `APP_BASE_URL` | 是 | 用于 OAuth 重定向和电子邮件链接的公共基础 URL |
切勿将 `.env` 提交到版本控制系统中。`.env.example` 文档记录了所需的键,但不包含真实值。
## 本地运行
```
cd backend
mvn clean install
mvn spring-boot:run
```
API 可通过 `http://localhost:8080` 访问。使用任何静态文件服务器或通过后端的静态资源处理器提供 `frontend/index.html` 服务,并将其指向 API 的基础 URL。
## Docker
```
docker build -t cypr-backend .
docker run -p 8080:8080 cypr-backend
```
这将启动 Spring Boot 后端服务。配置将从环境变量中读取。
## 部署
参考部署方案是在 AWS EC2 上运行后端,并使用 AWS RDS 作为 PostgreSQL 数据库,在推送到主分支时通过 GitHub Actions 工作流进行配置和部署。静态前端可以独立部署到 Vercel 或任何静态主机上,并指向已部署的 API 的基础 URL。
## 安全
- 密码使用 BCrypt 进行哈希处理;绝不存储或记录明文密码。
- 会话是无状态的,由签名的 JWT 提供支持。
- 自定义认证拦截器在每个受保护的路由上执行授权。
- 应用对象级访问检查以防止 IDOR/BOLA——用户只能访问他们拥有的资源。
- 在面向公众的表单上应用 Cloudflare Turnstile,以减少自动化滥用。
- 密钥仅从环境变量中读取;没有任何硬编码或被提交的密钥。
## 性能
| 指标 | 数值 | 备注 |
||---|---|
| 平均 VAJRA 扫描时间 | < 100ms | 本地测量,仅限 VAJRA,不包括 VirusTotal 的往返时间 |
| VirusTotal 交叉检查 | 70+ 引擎 | 延迟取决于 VirusTotal API 的响应时间 |
| 部署 | 支持 Docker、支持 AWS | 通过 `docker build` 实现单命令本地启动 |
这些数据反映了在单实例设置上的本地测量结果。它们并非正式压力测试的结果,不应被视为生产流量下的保证。
## 路线图
以下功能已在计划中,但在当前代码库中**尚未实现**:
| 功能 | 状态 |
|---|---|
| 浏览器扩展 | 已计划 |
| Android 应用 | 已计划 |
| 管理员门户 | 已计划 |
| 暗网检查器 | 已计划 |
| 二维码扫描器 | 已计划 |
| 邮件扫描器 | 已计划 |
| 报告导出 | 已计划 |
## 文档
- [API 参考](docs/api.md)
- [架构深度剖析](docs/architecture.md)
- [VAJRA 引擎内部原理](docs/vajra-engine.md)
- [部署指南](docs/deployment.md)
- [贡献指南](CONTRIBUTING.md)
## 许可协议
基于 [MIT 许可协议](LICENSE) 发布。
## 作者
**Vineet**
计算机科学与工程 工程学士
GitHub: [github.com/iamvineetupadhyay](https://github.com/iamvineetupadhyay)
LinkedIn: [linkedin.com/in/iamvineetupadhyay](https://linkedin.com/in/iamvineetupadhyay)
## 致谢
- [VirusTotal](https://www.virustotal.com/) —— 第三方扫描验证
- [OpenPhish](https://openphish.com/) 和 [phishing.army](https://phishing.army/) —— 参考威胁数据
- CISA, NIST, KrebsOnSecurity, BleepingComputer, The Hacker News —— 安全新闻来源
- [Cloudflare Turnstile](https://www.cloudflare.com/products/turnstile/) —— Bot 防护
- Spring Boot 和开源社区
如果您觉得 CYPR 有用,请考虑为该仓库加星。