muaddib-scanner 2.2.26 → 2.2.27
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/package.json +1 -1
- package/src/monitor.js +81 -18
- package/src/response/playbooks.js +362 -346
- package/src/rules/index.js +1076 -1038
- package/src/scanner/ast-detectors.js +67 -0
- package/src/scanner/ast.js +10 -1
|
@@ -565,6 +565,7 @@ function handleCallExpression(node, ctx) {
|
|
|
565
565
|
|
|
566
566
|
if (callName === 'eval') {
|
|
567
567
|
ctx.hasEvalInFile = true;
|
|
568
|
+
ctx.hasDynamicExec = true;
|
|
568
569
|
// Detect staged eval decode
|
|
569
570
|
if (node.arguments.length === 1 && hasDecodeArg(node.arguments[0])) {
|
|
570
571
|
ctx.threats.push({
|
|
@@ -585,6 +586,7 @@ function handleCallExpression(node, ctx) {
|
|
|
585
586
|
});
|
|
586
587
|
}
|
|
587
588
|
} else if (callName === 'Function') {
|
|
589
|
+
ctx.hasDynamicExec = true;
|
|
588
590
|
// Detect staged Function decode
|
|
589
591
|
if (node.arguments.length >= 1 && hasDecodeArg(node.arguments[node.arguments.length - 1])) {
|
|
590
592
|
ctx.threats.push({
|
|
@@ -679,12 +681,57 @@ function handleCallExpression(node, ctx) {
|
|
|
679
681
|
});
|
|
680
682
|
}
|
|
681
683
|
if (propName === '_compile') {
|
|
684
|
+
ctx.hasDynamicExec = true;
|
|
682
685
|
ctx.threats.push({
|
|
683
686
|
type: 'module_compile',
|
|
684
687
|
severity: 'CRITICAL',
|
|
685
688
|
message: 'module._compile() detected — executes arbitrary code from string in module context (flatmap-stream pattern).',
|
|
686
689
|
file: ctx.relFile
|
|
687
690
|
});
|
|
691
|
+
// SANDWORM_MODE: Module._compile with non-literal argument = dynamic code execution
|
|
692
|
+
if (node.arguments.length >= 1 && !hasOnlyStringLiteralArgs(node)) {
|
|
693
|
+
ctx.threats.push({
|
|
694
|
+
type: 'module_compile_dynamic',
|
|
695
|
+
severity: 'CRITICAL',
|
|
696
|
+
message: 'In-memory code execution via Module._compile(). Common malware evasion technique.',
|
|
697
|
+
file: ctx.relFile
|
|
698
|
+
});
|
|
699
|
+
}
|
|
700
|
+
// Module._compile counts as temp file exec for write-execute-delete pattern
|
|
701
|
+
ctx.hasTempFileExec = ctx.hasTempFileExec || ctx.hasTmpdirInContent;
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
// SANDWORM_MODE: Track writeFileSync/writeFile to temp paths
|
|
705
|
+
if (propName === 'writeFileSync' || propName === 'writeFile') {
|
|
706
|
+
const arg = node.arguments && node.arguments[0];
|
|
707
|
+
if (arg) {
|
|
708
|
+
const strVal = extractStringValue(arg);
|
|
709
|
+
if (strVal && (/\/dev\/shm\b/.test(strVal) || /\btmp\b/i.test(strVal) || /\btemp\b/i.test(strVal))) {
|
|
710
|
+
ctx.hasTempFileWrite = true;
|
|
711
|
+
}
|
|
712
|
+
// Variable reference to tmpdir/temp path
|
|
713
|
+
if (!strVal && (arg.type === 'Identifier' || arg.type === 'CallExpression' || arg.type === 'MemberExpression')) {
|
|
714
|
+
// Dynamic path — check if file content involves tmpdir patterns
|
|
715
|
+
ctx.hasTempFileWrite = ctx.hasTempFileWrite || ctx.hasTmpdirInContent;
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
// SANDWORM_MODE: Track unlinkSync/rmSync (file deletion)
|
|
721
|
+
if (propName === 'unlinkSync' || propName === 'unlink' || propName === 'rmSync') {
|
|
722
|
+
ctx.hasFileDelete = true;
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
// SANDWORM_MODE: Track require() of temp path (execution of temp file)
|
|
727
|
+
if (callName === 'require' && node.arguments.length > 0) {
|
|
728
|
+
const arg = node.arguments[0];
|
|
729
|
+
const strVal = extractStringValue(arg);
|
|
730
|
+
if (strVal && (/\/dev\/shm\b/.test(strVal) || /\btmp\b/i.test(strVal) || /\btemp\b/i.test(strVal))) {
|
|
731
|
+
ctx.hasTempFileExec = true;
|
|
732
|
+
} else if (!strVal && ctx.hasTmpdirInContent) {
|
|
733
|
+
// Variable argument in a file that references tmpdir paths
|
|
734
|
+
ctx.hasTempFileExec = true;
|
|
688
735
|
}
|
|
689
736
|
}
|
|
690
737
|
}
|
|
@@ -897,6 +944,26 @@ function handleMemberExpression(node, ctx) {
|
|
|
897
944
|
}
|
|
898
945
|
|
|
899
946
|
function handlePostWalk(ctx) {
|
|
947
|
+
// SANDWORM_MODE: zlib inflate + base64 decode + eval/Function/Module._compile = obfuscated payload
|
|
948
|
+
if (ctx.hasZlibInflate && ctx.hasBase64Decode && ctx.hasDynamicExec) {
|
|
949
|
+
ctx.threats.push({
|
|
950
|
+
type: 'zlib_inflate_eval',
|
|
951
|
+
severity: 'CRITICAL',
|
|
952
|
+
message: 'Obfuscated payload: zlib inflate + base64 decode + dynamic execution. No legitimate package uses this pattern.',
|
|
953
|
+
file: ctx.relFile
|
|
954
|
+
});
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
// SANDWORM_MODE: write + execute + delete = anti-forensics staging
|
|
958
|
+
if (ctx.hasTempFileWrite && ctx.hasTempFileExec && ctx.hasFileDelete) {
|
|
959
|
+
ctx.threats.push({
|
|
960
|
+
type: 'write_execute_delete',
|
|
961
|
+
severity: 'HIGH',
|
|
962
|
+
message: 'Anti-forensics: write, execute, then delete. Typical malware staging pattern.',
|
|
963
|
+
file: ctx.relFile
|
|
964
|
+
});
|
|
965
|
+
}
|
|
966
|
+
|
|
900
967
|
// JS reverse shell pattern
|
|
901
968
|
if (ctx.hasJsReverseShell) {
|
|
902
969
|
ctx.threats.push({
|
package/src/scanner/ast.js
CHANGED
|
@@ -75,7 +75,16 @@ function analyzeFile(content, filePath, basePath) {
|
|
|
75
75
|
/\.pipe\b/.test(content) &&
|
|
76
76
|
(/\bspawn\b/.test(content) || /\bstdin\b/.test(content) || /\bstdout\b/.test(content)),
|
|
77
77
|
hasBinaryFileLiteral: /\.(png|jpg|jpeg|gif|bmp|ico|wasm)\b/i.test(content),
|
|
78
|
-
hasEvalInFile: false
|
|
78
|
+
hasEvalInFile: false,
|
|
79
|
+
// SANDWORM_MODE: zlib inflate + base64 + eval co-occurrence
|
|
80
|
+
hasZlibInflate: /\brequire\s*\(\s*['"]zlib['"]\s*\)/.test(content) || /\bzlib\s*\.\s*inflate/.test(content),
|
|
81
|
+
hasBase64Decode: /Buffer\.from\s*\([^)]*,\s*['"]base64['"]/.test(content),
|
|
82
|
+
hasDynamicExec: false, // set in handleCallExpression for eval/Function/Module._compile
|
|
83
|
+
// SANDWORM_MODE: write + execute + delete anti-forensics
|
|
84
|
+
hasTempFileWrite: false,
|
|
85
|
+
hasTempFileExec: false,
|
|
86
|
+
hasFileDelete: false,
|
|
87
|
+
hasTmpdirInContent: /\btmpdir\b|\/dev\/shm\b|\/tmp\b/i.test(content)
|
|
79
88
|
};
|
|
80
89
|
|
|
81
90
|
walk.simple(ast, {
|