Files

68 lines
3.4 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 写库前的校验与规范化(零依赖)。
*
* 从 core.js 抽出来的模块:这些函数决定"什么值允许进库",
* 是安全边界所在(路径穿越、非法枚举),值得单独一处、单独读、单独测。
*/
import { resolve, sep } from 'node:path'
export const WEBSHELL_TYPES = ['behinder', 'godzilla', 'antSword', 'antsword', 'custom']
export const WEBSHELL_STATUSES = ['online', 'offline', 'dead', 'unknown']
/**
* 规范化马类型:大小写不敏感、允许中文别名(冰蝎/哥斯拉/蚁剑)。
* 认不出就抛错而不是静默存原文 —— 面板的"用户连不上"红标、会话页的连接口令复制
* 都按这个字段判断,存进去一个拼错的值不会报错,只会让这两处判定静默失效。
* @param value - 原始值(可为空)。
* @returns 规范化后的值或 null(空值合法 = 未声明)。
*/
export function normalizeShellType(value) {
const raw = value === undefined || value === null ? '' : String(value).trim()
if (raw === '') return null
const lower = raw.toLowerCase()
if (/behinder|冰蝎/.test(lower)) return 'behinder'
if (/godzilla|哥斯拉/.test(lower)) return 'godzilla'
if (/antsword|蚁剑/.test(lower)) return 'antSword'
if (lower === 'custom' || lower === 'custom-shell' || /自定义|自研/.test(raw)) return 'custom'
throw new Error("webshell shell_type 非法:" + JSON.stringify(value)
+ '。交付要求是**冰蝎马(behinder)/ 哥斯拉马(godzilla)**(用户要能自己连上);'
+ '其它类型请填 custom(只作临时中转,面板会标"用户连不上")。')
}
/** 规范化马状态(界面按 online/offline/unknown 三态显示)。 */
export function normalizeShellStatus(value) {
const raw = String(value === undefined || value === null ? '' : value).trim().toLowerCase()
const aliases = { up: 'online', alive: 'online', down: 'offline', failed: 'offline', removed: 'dead' }
const normalized = aliases[raw] || raw
if (normalized === '') return 'online'
if (!WEBSHELL_STATUSES.includes(normalized)) {
throw new Error("webshell status 非法:" + JSON.stringify(value) + "。合法值只有 " + WEBSHELL_STATUSES.join(" / ") + "。")
}
return normalized
}
/**
* 路径必须在允许的根目录内(防目录穿越)。
*
* 为什么需要:`readAttackFile` / `pocGet` 读的是**数据库里的 path 列**,
* 而那个列是智能体自己经 `addAttackFile` / `savePoc` 写进去的 —— 也就是不可信输入。
* 一旦填成 `/etc/passwd` 或 `~/.ssh/id_rsa`,面板点一下就把文件读到浏览器里了。
* `deletePoc` 早有 startsWith 防护,读路径与写路径却漏了,这里补成一处共用实现。
* @param target - 待校验的路径。
* @param allowedRoots - 允许的根目录(数组)。
* @returns 规范化后的绝对路径。
* @throws 越界时抛错(调用方按"查不到"处理,不要静默返回内容)。
*/
export function assertPathWithin(target, allowedRoots) {
const abs = resolve(String(target || ""))
const roots = (allowedRoots || []).filter((r) => typeof r === "string" && r !== "").map((r) => resolve(r))
const okFlag = roots.some((root) => abs === root || abs.startsWith(root + sep))
if (!okFlag) {
throw new Error("path outside allowed roots: " + abs
+ "(允许的根:" + roots.join(", ") + ")。这条记录的文件路径不在本靶标目录内,已拒绝读取。")
}
return abs
}