@surfinguard/core-engine 0.1.0
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/README.md +65 -0
- package/dist/analyzers/base.d.ts +38 -0
- package/dist/analyzers/base.d.ts.map +1 -0
- package/dist/analyzers/base.js +2 -0
- package/dist/analyzers/base.js.map +1 -0
- package/dist/analyzers/command.d.ts +44 -0
- package/dist/analyzers/command.d.ts.map +1 -0
- package/dist/analyzers/command.js +544 -0
- package/dist/analyzers/command.js.map +1 -0
- package/dist/analyzers/file-read.d.ts +31 -0
- package/dist/analyzers/file-read.d.ts.map +1 -0
- package/dist/analyzers/file-read.js +159 -0
- package/dist/analyzers/file-read.js.map +1 -0
- package/dist/analyzers/file-write.d.ts +32 -0
- package/dist/analyzers/file-write.d.ts.map +1 -0
- package/dist/analyzers/file-write.js +177 -0
- package/dist/analyzers/file-write.js.map +1 -0
- package/dist/analyzers/index.d.ts +7 -0
- package/dist/analyzers/index.d.ts.map +1 -0
- package/dist/analyzers/index.js +6 -0
- package/dist/analyzers/index.js.map +1 -0
- package/dist/analyzers/text.d.ts +30 -0
- package/dist/analyzers/text.d.ts.map +1 -0
- package/dist/analyzers/text.js +139 -0
- package/dist/analyzers/text.js.map +1 -0
- package/dist/analyzers/url.d.ts +33 -0
- package/dist/analyzers/url.d.ts.map +1 -0
- package/dist/analyzers/url.js +325 -0
- package/dist/analyzers/url.js.map +1 -0
- package/dist/classifier.d.ts +7 -0
- package/dist/classifier.d.ts.map +1 -0
- package/dist/classifier.js +12 -0
- package/dist/classifier.js.map +1 -0
- package/dist/context.d.ts +10 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +9 -0
- package/dist/context.js.map +1 -0
- package/dist/engine.d.ts +49 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +122 -0
- package/dist/engine.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/patterns.d.ts +8 -0
- package/dist/patterns.d.ts.map +1 -0
- package/dist/patterns.js +66 -0
- package/dist/patterns.js.map +1 -0
- package/dist/scorer.d.ts +23 -0
- package/dist/scorer.d.ts.map +1 -0
- package/dist/scorer.js +52 -0
- package/dist/scorer.js.map +1 -0
- package/dist/verdict.d.ts +7 -0
- package/dist/verdict.d.ts.map +1 -0
- package/dist/verdict.js +41 -0
- package/dist/verdict.js.map +1 -0
- package/package.json +44 -0
- package/patterns/brands.json +205 -0
- package/patterns/commands.json +44 -0
- package/patterns/file-read.json +85 -0
- package/patterns/file-write.json +100 -0
- package/patterns/text.json +190 -0
- package/patterns/urls.json +412 -0
|
@@ -0,0 +1,544 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Command Analyzer — heuristic shell command threat detection.
|
|
3
|
+
*
|
|
4
|
+
* Analyzes shell commands against 20 threat patterns (C01-C20)
|
|
5
|
+
* mapped to 5 risk primitives.
|
|
6
|
+
*/
|
|
7
|
+
export class CommandAnalyzer {
|
|
8
|
+
actionType = 'command';
|
|
9
|
+
db;
|
|
10
|
+
safeCommandsSet;
|
|
11
|
+
destructiveCommandsSet;
|
|
12
|
+
exfiltrationCommandsSet;
|
|
13
|
+
networkCommandsSet;
|
|
14
|
+
packageManagersSet;
|
|
15
|
+
encodingCommandsSet;
|
|
16
|
+
constructor(patterns) {
|
|
17
|
+
this.db = patterns;
|
|
18
|
+
this.safeCommandsSet = new Set(patterns.safeCommands);
|
|
19
|
+
this.destructiveCommandsSet = new Set(patterns.destructiveCommands);
|
|
20
|
+
this.exfiltrationCommandsSet = new Set(patterns.exfiltrationCommands);
|
|
21
|
+
this.networkCommandsSet = new Set(patterns.networkCommands);
|
|
22
|
+
this.packageManagersSet = new Set(patterns.packageManagers);
|
|
23
|
+
this.encodingCommandsSet = new Set(patterns.encodingCommands);
|
|
24
|
+
}
|
|
25
|
+
analyze(value) {
|
|
26
|
+
const trimmed = value.trim();
|
|
27
|
+
if (!trimmed) {
|
|
28
|
+
return { actionType: 'command', findings: [], shortCircuit: { safe: true, reason: 'Empty command' } };
|
|
29
|
+
}
|
|
30
|
+
const findings = [];
|
|
31
|
+
const add = (primitive, score, reason, threatId) => {
|
|
32
|
+
findings.push({ primitive, score, reason, threatId });
|
|
33
|
+
};
|
|
34
|
+
const lower = trimmed.toLowerCase();
|
|
35
|
+
const segments = this.tokenize(trimmed);
|
|
36
|
+
const hasPipe = trimmed.includes('|');
|
|
37
|
+
const hasRedirect = /[^|&]>[^&]|>>|<[^<]|2>/.test(trimmed);
|
|
38
|
+
const hasSubshell = trimmed.includes('$(') || trimmed.includes('`');
|
|
39
|
+
// ── Short-circuit for known-safe commands ─────────────────────────
|
|
40
|
+
if (segments.length === 1 && !hasPipe && !hasRedirect && !hasSubshell) {
|
|
41
|
+
const cmd = segments[0].command.toLowerCase();
|
|
42
|
+
if (this.safeCommandsSet.has(cmd) && !this.hasRiskyArgs(segments[0])) {
|
|
43
|
+
return { actionType: 'command', findings: [], shortCircuit: { safe: true, reason: 'Known safe command' } };
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
// ── 1. Pipe-to-shell (C04) ────────────────────────────────────────
|
|
47
|
+
for (const pattern of this.db.pipeToShell) {
|
|
48
|
+
if (lower.includes(pattern.toLowerCase())) {
|
|
49
|
+
add('DESTRUCTION', 9, `Piping output to shell interpreter (${pattern.trim()})`, 'C04');
|
|
50
|
+
break;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
// ── 2. Reverse shell patterns (C03) ───────────────────────────────
|
|
54
|
+
for (const pattern of this.db.reverseShellPatterns) {
|
|
55
|
+
if (lower.includes(pattern.toLowerCase())) {
|
|
56
|
+
add('EXFILTRATION', 9, `Reverse shell pattern detected (${pattern})`, 'C03');
|
|
57
|
+
break;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// ── 3. Fork bomb (C09) ────────────────────────────────────────────
|
|
61
|
+
if (this.isForkBomb(trimmed)) {
|
|
62
|
+
add('DESTRUCTION', 9, 'Fork bomb detected — will exhaust system resources', 'C09');
|
|
63
|
+
}
|
|
64
|
+
// ── 4. Encoded/obfuscated (C13) ───────────────────────────────────
|
|
65
|
+
if (this.isEncodedCommand(lower)) {
|
|
66
|
+
add('MANIPULATION', 8, 'Encoded or obfuscated command hides true intent', 'C13');
|
|
67
|
+
}
|
|
68
|
+
// ── 5. Variable expansion risk (C14) ──────────────────────────────
|
|
69
|
+
if (this.hasVariableExpansionRisk(trimmed)) {
|
|
70
|
+
add('DESTRUCTION', 7, 'Variable expansion in destructive command — empty variable could target root', 'C14');
|
|
71
|
+
}
|
|
72
|
+
// ── 6. Destructive operations (C01) ───────────────────────────────
|
|
73
|
+
for (const seg of segments) {
|
|
74
|
+
const cmd = seg.command.toLowerCase();
|
|
75
|
+
const rawLower = seg.raw.toLowerCase();
|
|
76
|
+
// Match exact command or dotted prefix (e.g., mkfs.ext4 matches mkfs)
|
|
77
|
+
const cmdBase = cmd.split('.')[0];
|
|
78
|
+
if (this.destructiveCommandsSet.has(cmd) || this.destructiveCommandsSet.has(cmdBase)) {
|
|
79
|
+
// Check for ad-hoc adjustments first
|
|
80
|
+
if (cmd === 'rm') {
|
|
81
|
+
const hasRecursive = seg.args.some(a => ['-r', '-rf', '-fr', '--recursive', '-Rf', '-fR'].includes(a));
|
|
82
|
+
const targetsCritical = this.targetsCriticalPath(seg.args);
|
|
83
|
+
if (hasRecursive && targetsCritical) {
|
|
84
|
+
add('DESTRUCTION', 9, `Recursive delete targeting critical path`, 'C01');
|
|
85
|
+
}
|
|
86
|
+
else if (hasRecursive) {
|
|
87
|
+
add('DESTRUCTION', 7, 'Recursive file deletion', 'C01');
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
// rm without -r on a specific file — reduced risk
|
|
91
|
+
add('DESTRUCTION', 3, 'File deletion command', 'C01');
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
else if (cmd === 'dd') {
|
|
95
|
+
if (rawLower.includes('of=/dev/')) {
|
|
96
|
+
add('DESTRUCTION', 9, `dd writing to device — will destroy data`, 'C01');
|
|
97
|
+
}
|
|
98
|
+
// dd to non-device is handled by disk-filling check below
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
add('DESTRUCTION', 9, `Destructive command: ${cmd}`, 'C01');
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
// Dangerous flags on non-destructive commands
|
|
105
|
+
if (this.db.destructiveFlags[cmd]) {
|
|
106
|
+
for (const flag of this.db.destructiveFlags[cmd]) {
|
|
107
|
+
if (seg.args.some(a => a.includes(flag))) {
|
|
108
|
+
// Skip if already detected above
|
|
109
|
+
if (cmd !== 'rm' && cmd !== 'dd') {
|
|
110
|
+
add('DESTRUCTION', 7, `Dangerous flag ${flag} used with ${cmd}`, 'C01');
|
|
111
|
+
}
|
|
112
|
+
break;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
// ── 7. Data exfiltration (C02) ────────────────────────────────────
|
|
118
|
+
for (const pattern of this.db.exfiltrationPatterns) {
|
|
119
|
+
if (lower.includes(pattern.toLowerCase())) {
|
|
120
|
+
add('EXFILTRATION', 8, `Data exfiltration pattern detected (${pattern.trim()})`, 'C02');
|
|
121
|
+
break;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
// Also check for exfiltration commands sending data
|
|
125
|
+
for (const seg of segments) {
|
|
126
|
+
const cmd = seg.command.toLowerCase();
|
|
127
|
+
if (cmd === 'scp' || cmd === 'rsync') {
|
|
128
|
+
// scp/rsync with a remote target
|
|
129
|
+
if (seg.args.some(a => a.includes('@') || a.includes(':'))) {
|
|
130
|
+
if (!findings.some(f => f.threatId === 'C02')) {
|
|
131
|
+
add('EXFILTRATION', 8, `${cmd} transferring data to remote host`, 'C02');
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
// ── 8. Credential harvesting (C18) ────────────────────────────────
|
|
137
|
+
const credentialPatterns = [
|
|
138
|
+
'/etc/shadow', '/etc/passwd', '.ssh/id_rsa', '.ssh/id_ed25519',
|
|
139
|
+
'.ssh/id_dsa', '.ssh/id_ecdsa', '.ssh/authorized_keys',
|
|
140
|
+
'.env', '.pem', '.key', '.p12', '.pfx',
|
|
141
|
+
'credentials', '.aws/credentials', '.docker/config.json',
|
|
142
|
+
'.kube/config', '.gnupg/', '.netrc',
|
|
143
|
+
];
|
|
144
|
+
for (const cred of credentialPatterns) {
|
|
145
|
+
if (lower.includes(cred)) {
|
|
146
|
+
// Only flag if reading, not just referencing in a safe context
|
|
147
|
+
const isReading = segments.some(s => {
|
|
148
|
+
const cmd = s.command.toLowerCase();
|
|
149
|
+
return ['cat', 'less', 'more', 'head', 'tail', 'cp', 'scp', 'rsync', 'curl', 'wget', 'base64'].includes(cmd);
|
|
150
|
+
});
|
|
151
|
+
// Also flag file redirection of sensitive files
|
|
152
|
+
const hasOutputRedirect = hasRedirect && lower.includes(cred);
|
|
153
|
+
if (isReading || hasOutputRedirect || lower.includes(`-d @`) || lower.includes('--upload-file')) {
|
|
154
|
+
add('EXFILTRATION', 8, `Accessing sensitive credential file (${cred})`, 'C18');
|
|
155
|
+
break;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
// ── 9. Privilege escalation (C05) ─────────────────────────────────
|
|
160
|
+
for (const seg of segments) {
|
|
161
|
+
const cmd = seg.command.toLowerCase();
|
|
162
|
+
const rawLower = seg.raw.toLowerCase();
|
|
163
|
+
if (cmd === 'sudo') {
|
|
164
|
+
// sudo apt install / sudo brew install — common, reduced
|
|
165
|
+
const subCmd = seg.args[0]?.toLowerCase();
|
|
166
|
+
if (subCmd === 'apt' || subCmd === 'apt-get' || subCmd === 'brew' || subCmd === 'yum' || subCmd === 'dnf' || subCmd === 'pacman') {
|
|
167
|
+
if (seg.args.some(a => a.toLowerCase() === 'install')) {
|
|
168
|
+
add('ESCALATION', 2, `sudo ${subCmd} install — common system administration`, 'C05');
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
add('ESCALATION', 4, `sudo ${subCmd} — elevated package management`, 'C05');
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
else if (subCmd === 'chmod' || subCmd === 'chown') {
|
|
175
|
+
add('ESCALATION', 8, `sudo ${subCmd} — elevated permission change`, 'C05');
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
add('ESCALATION', 6, `sudo — elevated privileges`, 'C05');
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
else if (cmd === 'doas' || cmd === 'pkexec') {
|
|
182
|
+
add('ESCALATION', 8, `Privilege escalation via ${cmd}`, 'C05');
|
|
183
|
+
}
|
|
184
|
+
else if (rawLower.includes('chmod u+s') || rawLower.includes('setuid')) {
|
|
185
|
+
add('ESCALATION', 8, 'Setting SUID bit — privilege escalation', 'C05');
|
|
186
|
+
}
|
|
187
|
+
// chmod with dangerous values on critical paths
|
|
188
|
+
if (cmd === 'chmod') {
|
|
189
|
+
const hasRiskyPerm = seg.args.some(a => ['777', '000', 'a+rwx'].includes(a));
|
|
190
|
+
const targetsCritical = this.targetsCriticalPath(seg.args);
|
|
191
|
+
if (hasRiskyPerm && targetsCritical) {
|
|
192
|
+
if (!findings.some(f => f.threatId === 'C05' && f.score >= 8)) {
|
|
193
|
+
add('ESCALATION', 8, `chmod with dangerous permissions on critical path`, 'C05');
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
else if (hasRiskyPerm) {
|
|
197
|
+
if (!findings.some(f => f.threatId === 'C05' && f.score >= 6)) {
|
|
198
|
+
add('ESCALATION', 4, `chmod with broad permissions`, 'C05');
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
// chmod on user-owned paths without recursive — low risk
|
|
203
|
+
// Don't add anything for normal chmod usage
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
// ── 10. Container escape (C19) ────────────────────────────────────
|
|
208
|
+
for (const pattern of this.db.containerEscapePatterns) {
|
|
209
|
+
if (lower.includes(pattern.toLowerCase())) {
|
|
210
|
+
add('ESCALATION', 9, `Container escape pattern detected (${pattern})`, 'C19');
|
|
211
|
+
break;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
// ── 11. Process injection (C15) ───────────────────────────────────
|
|
215
|
+
for (const seg of segments) {
|
|
216
|
+
const cmd = seg.command.toLowerCase();
|
|
217
|
+
if (cmd === 'gdb' && seg.args.some(a => a === '-p' || a === '--pid')) {
|
|
218
|
+
add('ESCALATION', 8, 'Process injection via gdb attach', 'C15');
|
|
219
|
+
}
|
|
220
|
+
if (cmd === 'strace' && seg.args.some(a => a === '-p')) {
|
|
221
|
+
add('ESCALATION', 8, 'Process tracing via strace', 'C15');
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
// LD_PRELOAD as inline env var (not export)
|
|
225
|
+
if (/\bLD_PRELOAD=\S+\s+\S/.test(trimmed) && !findings.some(f => f.threatId === 'C15')) {
|
|
226
|
+
add('ESCALATION', 8, 'Process injection via LD_PRELOAD', 'C15');
|
|
227
|
+
}
|
|
228
|
+
// ── 12. Persistence — cron (C06) ──────────────────────────────────
|
|
229
|
+
for (const seg of segments) {
|
|
230
|
+
const cmd = seg.command.toLowerCase();
|
|
231
|
+
if (cmd === 'crontab') {
|
|
232
|
+
add('PERSISTENCE', 7, 'Crontab modification — may install persistent task', 'C06');
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
if (lower.includes('/etc/cron') || lower.includes('/var/spool/cron')) {
|
|
236
|
+
if (!findings.some(f => f.threatId === 'C06')) {
|
|
237
|
+
add('PERSISTENCE', 7, 'Writing to cron directory — persistent execution', 'C06');
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
// ── 13. Persistence — shell config (C07) ──────────────────────────
|
|
241
|
+
const shellConfigs = ['.bashrc', '.zshrc', '.profile', '.bash_profile', '.bash_login'];
|
|
242
|
+
for (const config of shellConfigs) {
|
|
243
|
+
if (lower.includes(config) && (hasRedirect || lower.includes('echo') || lower.includes('tee'))) {
|
|
244
|
+
add('PERSISTENCE', 6, `Modifying shell config file (${config}) — persistence`, 'C07');
|
|
245
|
+
break;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
// ── 14. Git hook injection (C11) ──────────────────────────────────
|
|
249
|
+
if (lower.includes('.git/hooks/') && (hasRedirect || lower.includes('echo') || lower.includes('tee') || lower.includes('cp') || lower.includes('chmod'))) {
|
|
250
|
+
add('PERSISTENCE', 6, 'Git hook modification — code runs on git operations', 'C11');
|
|
251
|
+
}
|
|
252
|
+
// ── 15. Environment poisoning (C10) ───────────────────────────────
|
|
253
|
+
if (/\bexport\s+PATH=/.test(trimmed)) {
|
|
254
|
+
add('PERSISTENCE', 6, 'PATH environment variable modification', 'C10');
|
|
255
|
+
}
|
|
256
|
+
if (/\bexport\s+LD_PRELOAD=/.test(trimmed)) {
|
|
257
|
+
if (!findings.some(f => f.threatId === 'C15')) {
|
|
258
|
+
add('PERSISTENCE', 6, 'LD_PRELOAD environment variable set', 'C10');
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
// ── 16. Lateral movement (C08) ────────────────────────────────────
|
|
262
|
+
for (const seg of segments) {
|
|
263
|
+
const cmd = seg.command.toLowerCase();
|
|
264
|
+
if (this.networkCommandsSet.has(cmd)) {
|
|
265
|
+
if (cmd === 'ssh') {
|
|
266
|
+
add('ESCALATION', 6, 'SSH connection — potential lateral movement', 'C08');
|
|
267
|
+
}
|
|
268
|
+
else if (cmd === 'nmap') {
|
|
269
|
+
add('ESCALATION', 6, 'Network scanning detected', 'C08');
|
|
270
|
+
}
|
|
271
|
+
else if (cmd === 'ping' || cmd === 'traceroute') {
|
|
272
|
+
// ping/traceroute are generally safe — no finding
|
|
273
|
+
}
|
|
274
|
+
else {
|
|
275
|
+
add('ESCALATION', 5, `Network tool: ${cmd}`, 'C08');
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
// ── 17. Network listeners (C17) ───────────────────────────────────
|
|
280
|
+
for (const seg of segments) {
|
|
281
|
+
const cmd = seg.command.toLowerCase();
|
|
282
|
+
if (cmd === 'nc' || cmd === 'ncat' || cmd === 'netcat') {
|
|
283
|
+
if (seg.args.some(a => a === '-l' || a === '-lp' || a.startsWith('-l'))) {
|
|
284
|
+
add('ESCALATION', 5, 'Network listener opened', 'C17');
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
if (cmd === 'socat') {
|
|
288
|
+
add('ESCALATION', 5, 'socat — potential network relay', 'C17');
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
// python/python3 -m http.server
|
|
292
|
+
if (lower.includes('http.server') || lower.includes('simplehttpserver')) {
|
|
293
|
+
if (!findings.some(f => f.threatId === 'C17')) {
|
|
294
|
+
add('ESCALATION', 5, 'HTTP server started — exposes files on network', 'C17');
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
// ── 18. History tampering (C12) ───────────────────────────────────
|
|
298
|
+
if (lower.includes('history -c') || lower.includes('rm ~/.bash_history') ||
|
|
299
|
+
lower.includes('rm -f ~/.bash_history') || lower.includes('unset histfile') ||
|
|
300
|
+
lower.includes('export histfile=/dev/null') || lower.includes('set +o history')) {
|
|
301
|
+
add('MANIPULATION', 4, 'Command history tampering detected', 'C12');
|
|
302
|
+
}
|
|
303
|
+
// ── 19. Disk filling (C16) ────────────────────────────────────────
|
|
304
|
+
for (const seg of segments) {
|
|
305
|
+
const cmd = seg.command.toLowerCase();
|
|
306
|
+
if (cmd === 'dd') {
|
|
307
|
+
// dd writing to a file (not device) — disk filling
|
|
308
|
+
const hasDev = seg.raw.toLowerCase().includes('of=/dev/');
|
|
309
|
+
const hasOf = seg.raw.toLowerCase().includes('of=');
|
|
310
|
+
if (hasOf && !hasDev && !findings.some(f => f.threatId === 'C01' && f.score >= 9)) {
|
|
311
|
+
add('DESTRUCTION', 5, 'dd writing to file — potential disk filling', 'C16');
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
// ── 20. Package manager abuse (C20) ───────────────────────────────
|
|
316
|
+
for (const seg of segments) {
|
|
317
|
+
const cmd = seg.command.toLowerCase();
|
|
318
|
+
// Handle multi-word package managers like "go install"
|
|
319
|
+
const fullCmd = `${cmd} ${seg.args[0] || ''}`.trim().toLowerCase();
|
|
320
|
+
if (this.packageManagersSet.has(cmd) || this.packageManagersSet.has(fullCmd)) {
|
|
321
|
+
const isInstall = seg.args.some(a => ['install', 'add', 'i'].includes(a.toLowerCase()));
|
|
322
|
+
if (isInstall || fullCmd.startsWith('go install')) {
|
|
323
|
+
// Skip if already covered by safe commands (npm test, etc.)
|
|
324
|
+
if (!findings.some(f => f.threatId === 'C20')) {
|
|
325
|
+
add('DESTRUCTION', 3, `Package manager install (${cmd}) — may run arbitrary scripts`, 'C20');
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
return { actionType: 'command', findings };
|
|
331
|
+
}
|
|
332
|
+
// ── Shell Tokenizer ─────────────────────────────────────────────────
|
|
333
|
+
/**
|
|
334
|
+
* Split a command string into pipeline segments.
|
|
335
|
+
* Splits on |, &&, ||, ; respecting quotes.
|
|
336
|
+
*/
|
|
337
|
+
tokenize(input) {
|
|
338
|
+
const segments = [];
|
|
339
|
+
const rawSegments = this.splitPipeline(input);
|
|
340
|
+
for (const raw of rawSegments) {
|
|
341
|
+
const trimmed = raw.trim();
|
|
342
|
+
if (!trimmed)
|
|
343
|
+
continue;
|
|
344
|
+
const tokens = this.tokenizeSegment(trimmed);
|
|
345
|
+
if (tokens.length === 0)
|
|
346
|
+
continue;
|
|
347
|
+
segments.push({
|
|
348
|
+
command: tokens[0],
|
|
349
|
+
args: tokens.slice(1),
|
|
350
|
+
raw: trimmed,
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
return segments;
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* Split on |, &&, ||, ; while respecting quotes and subshells.
|
|
357
|
+
*/
|
|
358
|
+
splitPipeline(input) {
|
|
359
|
+
const segments = [];
|
|
360
|
+
let current = '';
|
|
361
|
+
let inSingle = false;
|
|
362
|
+
let inDouble = false;
|
|
363
|
+
let inBacktick = false;
|
|
364
|
+
let parenDepth = 0;
|
|
365
|
+
for (let i = 0; i < input.length; i++) {
|
|
366
|
+
const ch = input[i];
|
|
367
|
+
const next = input[i + 1];
|
|
368
|
+
// Track quoting
|
|
369
|
+
if (ch === "'" && !inDouble && !inBacktick) {
|
|
370
|
+
inSingle = !inSingle;
|
|
371
|
+
current += ch;
|
|
372
|
+
continue;
|
|
373
|
+
}
|
|
374
|
+
if (ch === '"' && !inSingle && !inBacktick) {
|
|
375
|
+
inDouble = !inDouble;
|
|
376
|
+
current += ch;
|
|
377
|
+
continue;
|
|
378
|
+
}
|
|
379
|
+
if (ch === '`' && !inSingle && !inDouble) {
|
|
380
|
+
inBacktick = !inBacktick;
|
|
381
|
+
current += ch;
|
|
382
|
+
continue;
|
|
383
|
+
}
|
|
384
|
+
// Track subshells
|
|
385
|
+
if (!inSingle && !inDouble && !inBacktick) {
|
|
386
|
+
if (ch === '(' || (ch === '$' && next === '(')) {
|
|
387
|
+
parenDepth++;
|
|
388
|
+
}
|
|
389
|
+
else if (ch === ')' && parenDepth > 0) {
|
|
390
|
+
parenDepth--;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
// Only split when not inside quotes or subshells
|
|
394
|
+
if (!inSingle && !inDouble && !inBacktick && parenDepth === 0) {
|
|
395
|
+
if (ch === '|' && next === '|') {
|
|
396
|
+
segments.push(current);
|
|
397
|
+
current = '';
|
|
398
|
+
i++; // skip second |
|
|
399
|
+
continue;
|
|
400
|
+
}
|
|
401
|
+
if (ch === '&' && next === '&') {
|
|
402
|
+
segments.push(current);
|
|
403
|
+
current = '';
|
|
404
|
+
i++; // skip second &
|
|
405
|
+
continue;
|
|
406
|
+
}
|
|
407
|
+
if (ch === '|') {
|
|
408
|
+
segments.push(current);
|
|
409
|
+
current = '';
|
|
410
|
+
continue;
|
|
411
|
+
}
|
|
412
|
+
if (ch === ';') {
|
|
413
|
+
segments.push(current);
|
|
414
|
+
current = '';
|
|
415
|
+
continue;
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
current += ch;
|
|
419
|
+
}
|
|
420
|
+
if (current.trim()) {
|
|
421
|
+
segments.push(current);
|
|
422
|
+
}
|
|
423
|
+
return segments;
|
|
424
|
+
}
|
|
425
|
+
/**
|
|
426
|
+
* Tokenize a single command segment into command + args.
|
|
427
|
+
* Handles single/double quotes.
|
|
428
|
+
*/
|
|
429
|
+
tokenizeSegment(input) {
|
|
430
|
+
const tokens = [];
|
|
431
|
+
let current = '';
|
|
432
|
+
let inSingle = false;
|
|
433
|
+
let inDouble = false;
|
|
434
|
+
for (let i = 0; i < input.length; i++) {
|
|
435
|
+
const ch = input[i];
|
|
436
|
+
if (ch === "'" && !inDouble) {
|
|
437
|
+
inSingle = !inSingle;
|
|
438
|
+
continue;
|
|
439
|
+
}
|
|
440
|
+
if (ch === '"' && !inSingle) {
|
|
441
|
+
inDouble = !inDouble;
|
|
442
|
+
continue;
|
|
443
|
+
}
|
|
444
|
+
if (ch === '\\' && inDouble && i + 1 < input.length) {
|
|
445
|
+
current += input[++i];
|
|
446
|
+
continue;
|
|
447
|
+
}
|
|
448
|
+
if ((ch === ' ' || ch === '\t') && !inSingle && !inDouble) {
|
|
449
|
+
if (current) {
|
|
450
|
+
tokens.push(current);
|
|
451
|
+
current = '';
|
|
452
|
+
}
|
|
453
|
+
continue;
|
|
454
|
+
}
|
|
455
|
+
current += ch;
|
|
456
|
+
}
|
|
457
|
+
if (current) {
|
|
458
|
+
tokens.push(current);
|
|
459
|
+
}
|
|
460
|
+
return tokens;
|
|
461
|
+
}
|
|
462
|
+
// ── Detection Helpers ───────────────────────────────────────────────
|
|
463
|
+
isForkBomb(cmd) {
|
|
464
|
+
// Classic: :(){ :|:& };:
|
|
465
|
+
if (cmd.includes(':(){ :|:&') || cmd.includes(':(){ :|: &'))
|
|
466
|
+
return true;
|
|
467
|
+
// Variants using function keyword
|
|
468
|
+
if (/\bfork\s*\(\)\s*\{.*fork.*fork/.test(cmd))
|
|
469
|
+
return true;
|
|
470
|
+
// Perl/Python variants
|
|
471
|
+
if (/while\s*\(1\)\s*\{\s*fork/.test(cmd))
|
|
472
|
+
return true;
|
|
473
|
+
return false;
|
|
474
|
+
}
|
|
475
|
+
isEncodedCommand(lower) {
|
|
476
|
+
// base64 -d | bash/sh
|
|
477
|
+
if (/base64\s+(-d|--decode)/.test(lower) && this.db.pipeToShell.some(p => lower.includes(p.toLowerCase()))) {
|
|
478
|
+
return true;
|
|
479
|
+
}
|
|
480
|
+
// eval $(...) with encoding
|
|
481
|
+
if (/eval\s+\$\(/.test(lower) && (lower.includes('base64') || lower.includes('xxd') || lower.includes('echo'))) {
|
|
482
|
+
return true;
|
|
483
|
+
}
|
|
484
|
+
// eval "$(base64 ...)"
|
|
485
|
+
if (/eval\s+/.test(lower) && lower.includes('base64')) {
|
|
486
|
+
return true;
|
|
487
|
+
}
|
|
488
|
+
return false;
|
|
489
|
+
}
|
|
490
|
+
hasVariableExpansionRisk(cmd) {
|
|
491
|
+
// rm -rf $VAR/ or rm -rf ${VAR}/
|
|
492
|
+
if (/rm\s+(-rf|-fr)\s+\$[\w{]/.test(cmd))
|
|
493
|
+
return true;
|
|
494
|
+
if (/rm\s+(-rf|-fr)\s+\$\{[^}]*\}\//.test(cmd))
|
|
495
|
+
return true;
|
|
496
|
+
return false;
|
|
497
|
+
}
|
|
498
|
+
targetsCriticalPath(args) {
|
|
499
|
+
for (const arg of args) {
|
|
500
|
+
if (arg.startsWith('-'))
|
|
501
|
+
continue; // skip flags
|
|
502
|
+
const normalized = arg.replace(/\/+$/, '') || '/'; // trailing slash removal, empty = root
|
|
503
|
+
for (const critical of this.db.criticalPaths) {
|
|
504
|
+
if (normalized === critical || normalized.startsWith(critical + '/')) {
|
|
505
|
+
return true;
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
// Also check for "/" alone
|
|
509
|
+
if (normalized === '/')
|
|
510
|
+
return true;
|
|
511
|
+
}
|
|
512
|
+
return false;
|
|
513
|
+
}
|
|
514
|
+
/**
|
|
515
|
+
* Check if a command segment has arguments that elevate risk
|
|
516
|
+
* beyond what the safe command alone would imply.
|
|
517
|
+
*/
|
|
518
|
+
hasRiskyArgs(seg) {
|
|
519
|
+
const cmd = seg.command.toLowerCase();
|
|
520
|
+
const argsLower = seg.args.map(a => a.toLowerCase());
|
|
521
|
+
// Check if safe command is reading sensitive credentials
|
|
522
|
+
if (['cat', 'less', 'more', 'head', 'tail'].includes(cmd)) {
|
|
523
|
+
const credFiles = ['/etc/shadow', '.ssh/id_rsa', '.ssh/id_ed25519', '.env', '.pem', '.key'];
|
|
524
|
+
if (seg.args.some(a => credFiles.some(c => a.toLowerCase().includes(c)))) {
|
|
525
|
+
return true;
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
// Package managers with install subcommand
|
|
529
|
+
if (this.packageManagersSet.has(cmd)) {
|
|
530
|
+
if (argsLower.some(a => ['install', 'add', 'i'].includes(a))) {
|
|
531
|
+
return true;
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
// Python/python3 running network server
|
|
535
|
+
if (cmd === 'python' || cmd === 'python3') {
|
|
536
|
+
const rawLower = seg.raw.toLowerCase();
|
|
537
|
+
if (rawLower.includes('http.server') || rawLower.includes('simplehttpserver')) {
|
|
538
|
+
return true;
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
return false;
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
//# sourceMappingURL=command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command.js","sourceRoot":"","sources":["../../src/analyzers/command.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { FileReadPatternDatabase } from '@surfinguard/types';
|
|
2
|
+
import type { Analyzer, AnalyzerResult } from './base.js';
|
|
3
|
+
/**
|
|
4
|
+
* File Read Analyzer — sensitive file read detection.
|
|
5
|
+
*
|
|
6
|
+
* Detects 10 threat patterns (FR01-FR10) mapped to the EXFILTRATION primitive.
|
|
7
|
+
*/
|
|
8
|
+
export declare class FileReadAnalyzer implements Analyzer {
|
|
9
|
+
readonly actionType: "file_read";
|
|
10
|
+
private readonly db;
|
|
11
|
+
private readonly safePathPrefixes;
|
|
12
|
+
private readonly safeExtensions;
|
|
13
|
+
constructor(patterns: FileReadPatternDatabase);
|
|
14
|
+
analyze(value: string): AnalyzerResult;
|
|
15
|
+
/**
|
|
16
|
+
* Normalize path: expand ~ to /HOME/, resolve ..
|
|
17
|
+
*/
|
|
18
|
+
private normalizePath;
|
|
19
|
+
/**
|
|
20
|
+
* Check if a path matches a safe path prefix or has a safe extension.
|
|
21
|
+
*/
|
|
22
|
+
private isSafePath;
|
|
23
|
+
/**
|
|
24
|
+
* Match a path against a pattern entry based on matchType.
|
|
25
|
+
*/
|
|
26
|
+
private matchPath;
|
|
27
|
+
private matchExtension;
|
|
28
|
+
private getExtension;
|
|
29
|
+
private getBasename;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=file-read.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-read.d.ts","sourceRoot":"","sources":["../../src/analyzers/file-read.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAA+C,MAAM,oBAAoB,CAAC;AAC/G,OAAO,KAAK,EAAE,QAAQ,EAAmB,cAAc,EAAE,MAAM,WAAW,CAAC;AAE3E;;;;GAIG;AACH,qBAAa,gBAAiB,YAAW,QAAQ;IAC/C,QAAQ,CAAC,UAAU,EAAG,WAAW,CAAU;IAE3C,OAAO,CAAC,QAAQ,CAAC,EAAE,CAA0B;IAC7C,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAW;IAC5C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAc;gBAEjC,QAAQ,EAAE,uBAAuB;IAM7C,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc;IA8DtC;;OAEG;IACH,OAAO,CAAC,aAAa;IAqBrB;;OAEG;IACH,OAAO,CAAC,UAAU;IA8BlB;;OAEG;IACH,OAAO,CAAC,SAAS;IAkBjB,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,WAAW;CAIpB"}
|