add check wxmsg
This commit is contained in:
1
src/modules/html/index.ts
Normal file
1
src/modules/html/index.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export * from './robot.ts';
|
||||||
15
src/modules/html/robot.ts
Normal file
15
src/modules/html/robot.ts
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
export const robotsTxt = `User-agent: *
|
||||||
|
Disallow: /admin/
|
||||||
|
Disallow: /config/
|
||||||
|
Disallow: /settings/
|
||||||
|
Disallow: /private/
|
||||||
|
Disallow: /secret/
|
||||||
|
Disallow: /.git/
|
||||||
|
Disallow: /.env
|
||||||
|
Disallow: /backup/
|
||||||
|
Disallow: /backups/
|
||||||
|
Disallow: /logs/
|
||||||
|
Disallow: /log/
|
||||||
|
Disallow: /tmp/
|
||||||
|
Disallow: /plus/
|
||||||
|
`;
|
||||||
44
src/modules/off/ban.ts
Normal file
44
src/modules/off/ban.ts
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
// 常备黑的 http://web/ban/
|
||||||
|
// 禁止使用这些用户名注册
|
||||||
|
// 容易被黑客扫描, 也容易被滥用
|
||||||
|
//
|
||||||
|
export const bannedUserNames = [
|
||||||
|
"admin", // 常见管理员名
|
||||||
|
"user", // 常见用户名
|
||||||
|
"guest", // 常见访客名
|
||||||
|
"core", // 常见系统名
|
||||||
|
"config", // 配置相关
|
||||||
|
"system", // 系统相关
|
||||||
|
"setting", // 设置相关
|
||||||
|
"storage", // 存储相关
|
||||||
|
"logs", // 日志相关
|
||||||
|
"log", // 日志相关
|
||||||
|
"backup", // 备份相关
|
||||||
|
"backups", // 备份相关
|
||||||
|
"tmp", // 临时相关
|
||||||
|
]
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查用户名是否在禁止列表中
|
||||||
|
* @param username
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export const userIsBanned = (username: string): boolean => {
|
||||||
|
if (username.startsWith('.')) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (username.endsWith('.')) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return bannedUserNames.includes(username.toLowerCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
export const appIsBanned = (appname: string): boolean => {
|
||||||
|
if (appname.startsWith('.')) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (appname.endsWith('.')) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
3
src/modules/off/index.ts
Normal file
3
src/modules/off/index.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
export * from './off-link.ts'
|
||||||
|
|
||||||
|
export * from './ban.ts'
|
||||||
330
src/modules/off/off-link.ts
Normal file
330
src/modules/off/off-link.ts
Normal file
@@ -0,0 +1,330 @@
|
|||||||
|
/**
|
||||||
|
* 黑客敏感文件爬取清单(TS 配置版)
|
||||||
|
*
|
||||||
|
* 黑客在渗透测试或自动化扫描中,会优先爬取以下敏感文件和目录,
|
||||||
|
* 以获取系统配置、凭证、密钥、数据库连接、源码泄露等高价值信息。
|
||||||
|
* 本列表按类别组织,便于安全审计、WAF规则、防御系统匹配。
|
||||||
|
*
|
||||||
|
* 注意:实际攻击中,黑客常使用工具如 dirsearch、gobuster、nuclei、Burp Suite 等进行批量扫描。
|
||||||
|
*/
|
||||||
|
|
||||||
|
// ========================
|
||||||
|
// 🌐 环境变量配置文件(最常见目标)
|
||||||
|
// ========================
|
||||||
|
// 黑客优先扫描 .env 文件,因其中常包含数据库密码、API密钥、JWT密钥、云服务凭证等
|
||||||
|
const envFiles = [
|
||||||
|
".env",
|
||||||
|
".env.local",
|
||||||
|
".env.development",
|
||||||
|
".env.production",
|
||||||
|
".env.example",
|
||||||
|
".env.dist",
|
||||||
|
".env.sample",
|
||||||
|
".env.backup",
|
||||||
|
".env.bak",
|
||||||
|
".env.old",
|
||||||
|
".env.txt"
|
||||||
|
];
|
||||||
|
|
||||||
|
// ========================
|
||||||
|
// ⚙️ 应用配置文件(框架/语言相关)
|
||||||
|
// ========================
|
||||||
|
// 不同语言/框架的配置文件,常暴露数据库连接、密钥、调试开关
|
||||||
|
const configFiles = [
|
||||||
|
// Node.js / JavaScript
|
||||||
|
"config.js",
|
||||||
|
"config.json",
|
||||||
|
"config.ts",
|
||||||
|
"config.yaml",
|
||||||
|
"config.yml",
|
||||||
|
"settings.js",
|
||||||
|
"settings.json",
|
||||||
|
"appsettings.json",
|
||||||
|
"server.js",
|
||||||
|
"server.ts",
|
||||||
|
|
||||||
|
// PHP
|
||||||
|
"config.php",
|
||||||
|
"wp-config.php", // WordPress 核心配置,含数据库凭证
|
||||||
|
"database.php",
|
||||||
|
"settings.php",
|
||||||
|
"app.php",
|
||||||
|
"bootstrap.php",
|
||||||
|
"config.ini",
|
||||||
|
|
||||||
|
// Python
|
||||||
|
"settings.py",
|
||||||
|
"config.py",
|
||||||
|
"local_settings.py",
|
||||||
|
"secrets.py",
|
||||||
|
"django_settings.py",
|
||||||
|
"flask_config.py",
|
||||||
|
|
||||||
|
// Java / Spring
|
||||||
|
"application.properties",
|
||||||
|
"application.yml",
|
||||||
|
"application-dev.properties",
|
||||||
|
"application-prod.properties",
|
||||||
|
|
||||||
|
// .NET
|
||||||
|
"appsettings.json",
|
||||||
|
"web.config",
|
||||||
|
"app.config",
|
||||||
|
|
||||||
|
// Go
|
||||||
|
"config.yaml",
|
||||||
|
"config.json",
|
||||||
|
"config.toml",
|
||||||
|
|
||||||
|
// Node
|
||||||
|
".npmrc",
|
||||||
|
".yarnrc",
|
||||||
|
".yarnrc.yml"
|
||||||
|
];
|
||||||
|
|
||||||
|
// ========================
|
||||||
|
// 🐳 容器与部署配置
|
||||||
|
// ========================
|
||||||
|
// Dockerfile、docker-compose 等文件可能暴露端口、挂载路径、密钥注入方式
|
||||||
|
const dockerFiles = [
|
||||||
|
"Dockerfile",
|
||||||
|
"Dockerfile.prod",
|
||||||
|
"Dockerfile.dev",
|
||||||
|
"docker-compose.yml",
|
||||||
|
"docker-compose.yaml",
|
||||||
|
"docker-compose.prod.yml",
|
||||||
|
"docker-compose.dev.yml",
|
||||||
|
"docker-compose.override.yml",
|
||||||
|
".dockerignore"
|
||||||
|
];
|
||||||
|
|
||||||
|
// ========================
|
||||||
|
// 💾 备份与临时文件(高危!常被忽略)
|
||||||
|
// ========================
|
||||||
|
// 黑客专门扫描备份文件,因开发者常忘记删除,其中包含原始敏感数据
|
||||||
|
const backupFiles = [
|
||||||
|
// 通用备份
|
||||||
|
"*.bak",
|
||||||
|
"*.backup",
|
||||||
|
"*.old",
|
||||||
|
"*.tmp",
|
||||||
|
"*.swp",
|
||||||
|
"*.swo",
|
||||||
|
"~",
|
||||||
|
|
||||||
|
// 具体文件类型备份
|
||||||
|
".env.bak",
|
||||||
|
".env.backup",
|
||||||
|
".env.old",
|
||||||
|
"config.php.bak",
|
||||||
|
"wp-config.php.bak",
|
||||||
|
"database.sql",
|
||||||
|
"database.sql.bak",
|
||||||
|
"database.dump",
|
||||||
|
"db.sql",
|
||||||
|
"db_backup.sql",
|
||||||
|
"backup.zip",
|
||||||
|
"backup.tar.gz",
|
||||||
|
"backup.tar",
|
||||||
|
"backup.rar"
|
||||||
|
];
|
||||||
|
|
||||||
|
// ========================
|
||||||
|
// 🛠️ 管理面板与控制台文件(视具体项目而定)
|
||||||
|
// ========================
|
||||||
|
// 某些项目可能包含自定义管理面板,黑客会尝试爬取这些路径
|
||||||
|
const adminFiles = [
|
||||||
|
"admin/",
|
||||||
|
"administrator/",
|
||||||
|
"admin.php",
|
||||||
|
"admin.html",
|
||||||
|
"controlpanel/",
|
||||||
|
"cpanel/",
|
||||||
|
"manage/",
|
||||||
|
"dashboard/",
|
||||||
|
"console/"
|
||||||
|
]
|
||||||
|
// ========================
|
||||||
|
// 📜 日志文件(泄露调试信息、路径、错误堆栈)
|
||||||
|
// ========================
|
||||||
|
// 日志文件常包含敏感错误信息、堆栈追踪、数据库查询、用户输入等
|
||||||
|
const logFiles = [
|
||||||
|
"logs/",
|
||||||
|
"log/",
|
||||||
|
"storage/logs/",
|
||||||
|
"app/logs/",
|
||||||
|
"var/log/",
|
||||||
|
"logs/error.log",
|
||||||
|
"logs/access.log",
|
||||||
|
"logs/debug.log",
|
||||||
|
"logs/app.log",
|
||||||
|
"runtime/logs/*.log",
|
||||||
|
"nginx/error.log",
|
||||||
|
"nginx/access.log",
|
||||||
|
"apache/error.log",
|
||||||
|
"apache/access.log",
|
||||||
|
"php_error.log",
|
||||||
|
"debug.log",
|
||||||
|
"system.log"
|
||||||
|
];
|
||||||
|
|
||||||
|
// ========================
|
||||||
|
// 🌐 WordPress 特有敏感文件
|
||||||
|
// ========================
|
||||||
|
// WordPress 是最常被攻击的 CMS,黑客会扫描其专属配置与插件
|
||||||
|
const wordpressFiles = [
|
||||||
|
"wp-config.php",
|
||||||
|
"wp-admin/",
|
||||||
|
"wp-login.php",
|
||||||
|
"wp-content/uploads/",
|
||||||
|
"wp-content/plugins/",
|
||||||
|
"wp-content/themes/",
|
||||||
|
"readme.html",
|
||||||
|
"license.txt",
|
||||||
|
"xmlrpc.php",
|
||||||
|
"wp-includes/",
|
||||||
|
"wp-json/wp/v2/users" // API 接口,可枚举用户
|
||||||
|
];
|
||||||
|
|
||||||
|
// ========================
|
||||||
|
// 🔐 密钥与凭证文件(最高优先级)
|
||||||
|
// ========================
|
||||||
|
// 包含私钥、公钥、令牌、证书等,泄露即等于系统沦陷
|
||||||
|
const secretFiles = [
|
||||||
|
"id_rsa",
|
||||||
|
"id_rsa.pub",
|
||||||
|
"authorized_keys",
|
||||||
|
"known_hosts",
|
||||||
|
"ssh_config",
|
||||||
|
"config",
|
||||||
|
"credentials",
|
||||||
|
"secrets.json",
|
||||||
|
"secrets.yaml",
|
||||||
|
"secrets.yml",
|
||||||
|
"key.pem",
|
||||||
|
"cert.pem",
|
||||||
|
"certificate.crt",
|
||||||
|
"private.key",
|
||||||
|
"public.key",
|
||||||
|
"token",
|
||||||
|
"access_token",
|
||||||
|
"refresh_token",
|
||||||
|
"oauth_token",
|
||||||
|
"jwt.key",
|
||||||
|
"jwt.secret",
|
||||||
|
"api_key",
|
||||||
|
"apikey",
|
||||||
|
"API_KEY",
|
||||||
|
"SECRET_KEY",
|
||||||
|
"ACCESS_KEY",
|
||||||
|
"SECRET",
|
||||||
|
"AWS_ACCESS_KEY_ID",
|
||||||
|
"AWS_SECRET_ACCESS_KEY",
|
||||||
|
"GOOGLE_API_KEY",
|
||||||
|
"TWILIO_ACCOUNT_SID",
|
||||||
|
"TWILIO_AUTH_TOKEN",
|
||||||
|
"STRIPE_SECRET_KEY",
|
||||||
|
"SENDGRID_API_KEY",
|
||||||
|
"DATABASE_URL",
|
||||||
|
"MONGODB_URI",
|
||||||
|
"REDIS_URL"
|
||||||
|
];
|
||||||
|
|
||||||
|
// ========================
|
||||||
|
// 🧩 .git 仓库泄露(致命!可还原完整源码)
|
||||||
|
// ========================
|
||||||
|
// 黑客利用 .git 目录泄露,通过 git-dumper、GitTools 等工具还原整个项目源码
|
||||||
|
const gitFiles = [
|
||||||
|
".git/",
|
||||||
|
".git/config",
|
||||||
|
".git/HEAD",
|
||||||
|
".git/index",
|
||||||
|
".git/objects/",
|
||||||
|
".git/refs/",
|
||||||
|
".git/refs/heads/",
|
||||||
|
".git/refs/remotes/",
|
||||||
|
".git/FETCH_HEAD",
|
||||||
|
".git/COMMIT_EDITMSG",
|
||||||
|
".git/logs/HEAD",
|
||||||
|
".gitignore", // 虽非敏感,但可辅助判断项目结构
|
||||||
|
".gitattributes"
|
||||||
|
];
|
||||||
|
|
||||||
|
// ========================
|
||||||
|
// 🧱 通用敏感文件(跨平台高危)
|
||||||
|
// ========================
|
||||||
|
// 常见于各类项目中,黑客通用扫描项
|
||||||
|
const commonSensitiveFiles = [
|
||||||
|
"README.md",
|
||||||
|
"LICENSE",
|
||||||
|
"package.json",
|
||||||
|
"package-lock.json",
|
||||||
|
"yarn.lock",
|
||||||
|
"composer.json",
|
||||||
|
"composer.lock",
|
||||||
|
"requirements.txt",
|
||||||
|
"Pipfile",
|
||||||
|
"Pipfile.lock",
|
||||||
|
"Gemfile",
|
||||||
|
"Gemfile.lock",
|
||||||
|
"manifest.json",
|
||||||
|
"robots.txt", // 可能暴露隐藏路径
|
||||||
|
"sitemap.xml",
|
||||||
|
"crossdomain.xml",
|
||||||
|
"client-secrets.json", // Google OAuth
|
||||||
|
"firebase.json",
|
||||||
|
"netlify.toml",
|
||||||
|
"vercel.json",
|
||||||
|
|
||||||
|
// 邮件配置文件
|
||||||
|
"mailsettings.json",
|
||||||
|
"smtp.config",
|
||||||
|
"email.config",
|
||||||
|
"brevo",
|
||||||
|
];
|
||||||
|
|
||||||
|
// ========================
|
||||||
|
// 🚨 汇总:所有敏感文件路径(供安全系统统一调用)
|
||||||
|
// ========================
|
||||||
|
// 将所有类别合并为一个全量列表,便于 WAF、IDS、扫描器使用
|
||||||
|
export const ALL_SENSITIVE_FILES = [
|
||||||
|
...envFiles,
|
||||||
|
...configFiles,
|
||||||
|
...dockerFiles,
|
||||||
|
...backupFiles,
|
||||||
|
...adminFiles,
|
||||||
|
...logFiles,
|
||||||
|
...wordpressFiles,
|
||||||
|
...secretFiles,
|
||||||
|
...gitFiles,
|
||||||
|
...commonSensitiveFiles
|
||||||
|
];
|
||||||
|
|
||||||
|
// ========================
|
||||||
|
// 📌 使用建议
|
||||||
|
// ========================
|
||||||
|
// 1. 在 Nginx/Apache 中禁止访问上述文件/目录
|
||||||
|
// 2. 在 CI/CD 中禁止提交 .env、*.bak、.git 等文件
|
||||||
|
// 3. 使用 .gitignore 正确排除敏感文件
|
||||||
|
// 4. 使用安全扫描工具(如 Trivy、Semgrep、Snyk)定期检测
|
||||||
|
// 5. 生产环境禁止暴露 .env、wp-config.php、.git 等文件
|
||||||
|
//
|
||||||
|
// ✅ 安全实践:所有敏感文件应存储在服务器外部,通过环境变量注入
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 快速查看是否被攻击者爬取了敏感文件
|
||||||
|
* @param filePath
|
||||||
|
*/
|
||||||
|
export const hasBadUser = (filePath: string): boolean => {
|
||||||
|
return ALL_SENSITIVE_FILES.some(sensitivePath => {
|
||||||
|
// 精确匹配或通配符匹配
|
||||||
|
if (sensitivePath.includes('*')) {
|
||||||
|
// 转换通配符为正则表达式
|
||||||
|
const regexStr = sensitivePath.replace(/\./g, '\\.').replace(/\*/g, '.*');
|
||||||
|
const regex = new RegExp(`^${regexStr}$`);
|
||||||
|
return regex.test(filePath);
|
||||||
|
} else {
|
||||||
|
return filePath === sensitivePath;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -128,6 +128,7 @@ export class UserApp {
|
|||||||
const fetchRes = await fetchDomain(domain).catch((err) => {
|
const fetchRes = await fetchDomain(domain).catch((err) => {
|
||||||
return {
|
return {
|
||||||
code: 500,
|
code: 500,
|
||||||
|
data: null,
|
||||||
message: err,
|
message: err,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -177,6 +177,7 @@ const simpleAppsPrefixs = [
|
|||||||
"/api/s1/",
|
"/api/s1/",
|
||||||
"/api/container/",
|
"/api/container/",
|
||||||
"/api/resource/",
|
"/api/resource/",
|
||||||
|
"/api/wxmsg"
|
||||||
];
|
];
|
||||||
|
|
||||||
export const handleRequest = async (req: http.IncomingMessage, res: http.ServerResponse) => {
|
export const handleRequest = async (req: http.IncomingMessage, res: http.ServerResponse) => {
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ import { getLoginUser } from '../modules/auth.ts';
|
|||||||
import { rediretHome } from '../modules/user-app/index.ts';
|
import { rediretHome } from '../modules/user-app/index.ts';
|
||||||
import { logger } from '../modules/logger.ts';
|
import { logger } from '../modules/logger.ts';
|
||||||
import { UserV1Proxy } from '../modules/ws-proxy/proxy.ts';
|
import { UserV1Proxy } from '../modules/ws-proxy/proxy.ts';
|
||||||
|
import { hasBadUser, userIsBanned, appIsBanned } from '@/modules/off/index.ts';
|
||||||
|
import { robotsTxt } from '@/modules/html/index.ts';
|
||||||
const domain = config?.proxy?.domain;
|
const domain = config?.proxy?.domain;
|
||||||
const allowedOrigins = config?.proxy?.allowedOrigin || [];
|
const allowedOrigins = config?.proxy?.allowedOrigin || [];
|
||||||
|
|
||||||
@@ -22,14 +24,6 @@ const notAuthPathList = [
|
|||||||
user: 'root',
|
user: 'root',
|
||||||
paths: ['center'],
|
paths: ['center'],
|
||||||
},
|
},
|
||||||
{
|
|
||||||
user: 'admin',
|
|
||||||
paths: ['center'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
user: 'user',
|
|
||||||
paths: ['login'],
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
user: 'public',
|
user: 'public',
|
||||||
paths: ['center'],
|
paths: ['center'],
|
||||||
@@ -53,6 +47,12 @@ const checkNotAuthPath = (user, app) => {
|
|||||||
});
|
});
|
||||||
return notAuthPath;
|
return notAuthPath;
|
||||||
};
|
};
|
||||||
|
const forBadUser = (req: http.IncomingMessage, res: http.ServerResponse) => {
|
||||||
|
// TODO: 记录日志,封禁IP等操作
|
||||||
|
const dns = getDNS(req);
|
||||||
|
logger.warn(`Bad user access from IP: ${dns.ip}, Host: ${dns.hostName}, URL: ${req.url}`);
|
||||||
|
// 这里可以添加更多的处理逻辑,比如封禁IP等
|
||||||
|
}
|
||||||
export const handleRequest = async (req: http.IncomingMessage, res: http.ServerResponse) => {
|
export const handleRequest = async (req: http.IncomingMessage, res: http.ServerResponse) => {
|
||||||
const querySearch = new URL(req.url, `http://${req.headers.host}`).searchParams;
|
const querySearch = new URL(req.url, `http://${req.headers.host}`).searchParams;
|
||||||
const password = querySearch.get('p');
|
const password = querySearch.get('p');
|
||||||
@@ -153,6 +153,7 @@ export const handleRequest = async (req: http.IncomingMessage, res: http.ServerR
|
|||||||
console.error('Invalid domain: ', req.url, dns.hostName);
|
console.error('Invalid domain: ', req.url, dns.hostName);
|
||||||
res.writeHead(404, { 'Content-Type': 'text/plain' });
|
res.writeHead(404, { 'Content-Type': 'text/plain' });
|
||||||
res.end('Invalid domain\n');
|
res.end('Invalid domain\n');
|
||||||
|
forBadUser(req, res);
|
||||||
return res.end();
|
return res.end();
|
||||||
}
|
}
|
||||||
// 验证域名
|
// 验证域名
|
||||||
@@ -198,9 +199,18 @@ export const handleRequest = async (req: http.IncomingMessage, res: http.ServerR
|
|||||||
// 原始url地址
|
// 原始url地址
|
||||||
const urls = url.split('/');
|
const urls = url.split('/');
|
||||||
if (urls.length < 3) {
|
if (urls.length < 3) {
|
||||||
console.log('urls errpr', urls);
|
const [_, _user] = urls;
|
||||||
|
if (_user === 'robots.txt') {
|
||||||
|
res.writeHead(200, { 'Content-Type': 'text/plain' });
|
||||||
|
res.end(robotsTxt);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log('urls error', urls, 'originUrl:', url);
|
||||||
res.writeHead(404, { 'Content-Type': 'text/html' });
|
res.writeHead(404, { 'Content-Type': 'text/html' });
|
||||||
res.write('Invalid Proxy URL\n');
|
res.write('Invalid Proxy URL\n');
|
||||||
|
if (hasBadUser(_user)) {
|
||||||
|
forBadUser(req, res);
|
||||||
|
}
|
||||||
return res.end();
|
return res.end();
|
||||||
}
|
}
|
||||||
const [_, _user, _app] = urls;
|
const [_, _user, _app] = urls;
|
||||||
@@ -244,6 +254,10 @@ export const handleRequest = async (req: http.IncomingMessage, res: http.ServerR
|
|||||||
const userApp = new UserApp({ user, app });
|
const userApp = new UserApp({ user, app });
|
||||||
let isExist = await userApp.getExist();
|
let isExist = await userApp.getExist();
|
||||||
logger.debug('userApp', userApp, isExist);
|
logger.debug('userApp', userApp, isExist);
|
||||||
|
if (userIsBanned(user) || appIsBanned(app)) {
|
||||||
|
forBadUser(req, res);
|
||||||
|
return createErrorPage();
|
||||||
|
}
|
||||||
if (!isExist) {
|
if (!isExist) {
|
||||||
try {
|
try {
|
||||||
const { code, loading, message } = await userApp.setCacheData();
|
const { code, loading, message } = await userApp.setCacheData();
|
||||||
|
|||||||
Reference in New Issue
Block a user