muaddib-scanner 2.10.21 → 2.10.23
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 +11 -11
- package/bin/muaddib.js +365 -39
- package/package.json +1 -1
- package/scripts/benchmark.js +326 -0
- package/src/index.js +34 -3
- package/src/ioc/scraper.js +4 -141
- package/src/ioc/updater.js +26 -7
- package/src/response/playbooks.js +112 -0
- package/src/rules/index.js +324 -1
- package/src/scanner/ast-detectors.js +744 -12
- package/src/scanner/ast.js +62 -1
- package/src/scanner/package.js +70 -0
- package/src/scanner/shell.js +5 -5
- package/src/scoring.js +76 -6
- package/src/shared/constants.js +5 -5
- package/src/utils.js +8 -0
|
@@ -698,6 +698,118 @@ const PLAYBOOKS = {
|
|
|
698
698
|
'dans ~/.config/sysmon/ et exfiltre vers checkmarx.zone. ' +
|
|
699
699
|
'Verifier: find $(python -c "import site; print(site.getsitepackages()[0])") -name "*.pth" -exec cat {} \\; ' +
|
|
700
700
|
'Supprimer tout fichier .pth non standard. Rotation des credentials.',
|
|
701
|
+
|
|
702
|
+
// Audit v3 Bypass Playbooks (AST-062 to AST-069)
|
|
703
|
+
reflect_apply_require:
|
|
704
|
+
'CRITIQUE: Reflect.apply(require, null, [module]) detecte — contournement de require() via Reflect API. ' +
|
|
705
|
+
'Aucun package legitime ne charge des modules via Reflect.apply. ' +
|
|
706
|
+
'Supprimer le package. Auditer les modules charges dynamiquement.',
|
|
707
|
+
|
|
708
|
+
finalization_registry_exec:
|
|
709
|
+
'CRITIQUE: FinalizationRegistry avec callback dangereux (child_process/exec/spawn). ' +
|
|
710
|
+
'Le callback s\'execute apres le garbage collection, hors du flux synchrone — evasion sandbox. ' +
|
|
711
|
+
'Aucun usage legitime ne combine FinalizationRegistry avec des appels systeme. Supprimer le package.',
|
|
712
|
+
|
|
713
|
+
function_prototype_constructor:
|
|
714
|
+
'CRITIQUE: Acces au constructeur Function via chaine de prototypes — (function(){}).constructor(code) ' +
|
|
715
|
+
'ou [].constructor.constructor(code). Equivalent a eval() mais invisible aux detections statiques de eval/Function. ' +
|
|
716
|
+
'Supprimer le package. Aucun usage legitime.',
|
|
717
|
+
|
|
718
|
+
prototype_pollution:
|
|
719
|
+
'HAUTE: Pollution de prototype detectee (__proto__, __defineGetter__, __defineSetter__). ' +
|
|
720
|
+
'Peut detourner les proprietes heritees de tous les objets du runtime. ' +
|
|
721
|
+
'Verifier si le code modifie Object.prototype ou des prototypes de classes natives. ' +
|
|
722
|
+
'Si combine avec du code d\'execution dynamique, traiter comme CRITIQUE.',
|
|
723
|
+
|
|
724
|
+
module_wrap_override:
|
|
725
|
+
'CRITIQUE: Module.wrap remplace — la fonction wrapper du module loader est detournee. ' +
|
|
726
|
+
'Tout module charge apres cette modification execute du code injecte. ' +
|
|
727
|
+
'Aucun package legitime ne remplace Module.wrap. Supprimer immediatement.',
|
|
728
|
+
|
|
729
|
+
symbol_property_hiding:
|
|
730
|
+
'HAUTE: Module dangereux cache derriere une propriete Symbol. ' +
|
|
731
|
+
'Invisible a Object.keys(), JSON.stringify() et for...in. Technique anti-forensics. ' +
|
|
732
|
+
'Auditer toutes les proprietes Symbol du module. Supprimer si combine avec child_process/fs.',
|
|
733
|
+
|
|
734
|
+
with_body_dangerous:
|
|
735
|
+
'HAUTE: with() statement avec require/exec/spawn dans le body. ' +
|
|
736
|
+
'Le with() rend les identifiants ambigus, empechant l\'analyse statique. ' +
|
|
737
|
+
'Aucun code moderne legitime n\'utilise with(). Supprimer le package.',
|
|
738
|
+
|
|
739
|
+
require_process_mainmodule:
|
|
740
|
+
'CRITIQUE: require("process").mainModule.require() detecte — contournement de la detection ' +
|
|
741
|
+
'process.mainModule.require() via require("process") au lieu de l\'objet global. ' +
|
|
742
|
+
'Aucun package legitime n\'utilise ce pattern. Supprimer immediatement.',
|
|
743
|
+
|
|
744
|
+
// Blue Team v8 — New playbook entries
|
|
745
|
+
shared_memory_ipc:
|
|
746
|
+
'SharedArrayBuffer + Worker Thread detectes. Canal IPC memoire partagee qui contourne la surveillance. ' +
|
|
747
|
+
'Verifier si les workers manipulent des donnees sensibles. Isoler si combine avec eval/exec.',
|
|
748
|
+
|
|
749
|
+
websocket_c2:
|
|
750
|
+
'HAUTE: Connexion WebSocket vers domaine suspect ou avec execution dynamique. Canal C2 persistant bidirectionnel. ' +
|
|
751
|
+
'Analyser l\'URL de connexion. Bloquer les connexions WebSocket sortantes. Verifier les messages echanges.',
|
|
752
|
+
|
|
753
|
+
udp_exfiltration:
|
|
754
|
+
'HAUTE: Socket UDP (dgram) avec envoi de donnees. Exfiltration contournant les firewalls HTTP. ' +
|
|
755
|
+
'Verifier les destinations IP. Bloquer le trafic UDP sortant non-DNS. Auditer les donnees envoyees.',
|
|
756
|
+
|
|
757
|
+
native_addon_install:
|
|
758
|
+
'HAUTE: binding.gyp avec script lifecycle non-standard. Code natif compile a l\'installation. ' +
|
|
759
|
+
'Verifier le contenu de binding.gyp et les sources C/C++. Installer avec --ignore-scripts si suspect.',
|
|
760
|
+
|
|
761
|
+
string_mutation_obfuscation:
|
|
762
|
+
'HAUTE: Chaine de .replace() reconstruisant des noms d\'API dangereuses (leet-speak). ' +
|
|
763
|
+
'Technique d\'evasion par substitution de caracteres. Decoder la chaine finale. Supprimer si malveillant.',
|
|
764
|
+
|
|
765
|
+
crontab_systemd_write:
|
|
766
|
+
'CRITIQUE: Ecriture dans les fichiers cron/crontab. Persistence via tache planifiee. ' +
|
|
767
|
+
'Verifier /etc/cron*, /var/spool/cron. Supprimer les entrees ajoutees. Auditer crontab -l.',
|
|
768
|
+
|
|
769
|
+
isolated_suspicious_file:
|
|
770
|
+
'Un seul fichier suspect parmi de nombreux fichiers propres. Pattern de dissimulation typique ' +
|
|
771
|
+
'ou le code malveillant est cache dans un package apparemment legitime. Examiner le fichier suspect en detail.',
|
|
772
|
+
|
|
773
|
+
deep_suspicious_file:
|
|
774
|
+
'Pattern suspect dans un fichier profondement imbrique. Technique pour echapper aux analyses superficielles. ' +
|
|
775
|
+
'Verifier le contenu du fichier et son role dans l\'arborescence du package.',
|
|
776
|
+
|
|
777
|
+
// Blue Team v8b playbooks
|
|
778
|
+
module_internals_hijack:
|
|
779
|
+
'CRITIQUE: Assignation a Module._resolveFilename/_compile/_extensions. Detournement du systeme de modules Node.js. ' +
|
|
780
|
+
'Tous les require() sont interceptes. Supprimer le package immediatement. Auditer tous les modules charges apres installation.',
|
|
781
|
+
|
|
782
|
+
json_reviver_pollution:
|
|
783
|
+
'HAUTE: JSON.parse avec reviver accedant a __proto__/prototype. Pollution de prototype via JSON. ' +
|
|
784
|
+
'Ne jamais passer de JSON non fiable avec un reviver manipulant __proto__. Verifier les sources de donnees JSON.',
|
|
785
|
+
|
|
786
|
+
vm_dynamic_code:
|
|
787
|
+
'CRITIQUE: vm.runInContext/compileFunction avec code construit dynamiquement. Evasion de sandbox. ' +
|
|
788
|
+
'Verifier d\'ou provient le code execute. Bloquer l\'acces au module vm. Supprimer si non justifie.',
|
|
789
|
+
|
|
790
|
+
callback_exec_rce:
|
|
791
|
+
'CRITIQUE: exec/spawn dans callback .on(\'message\'|\'data\'). Execution de commandes depuis flux reseau. ' +
|
|
792
|
+
'Pattern C2: commandes recues par WebSocket/TCP executees via child_process. Supprimer immediatement.',
|
|
793
|
+
|
|
794
|
+
stego_binary_exec:
|
|
795
|
+
'CRITIQUE: Lecture de fichier image/binaire + eval/Function. Payload steganographique. ' +
|
|
796
|
+
'Verifier le contenu du fichier image. Scanner avec des outils stego. Supprimer le fichier et le code d\'extraction.',
|
|
797
|
+
|
|
798
|
+
asynclocal_context_exec:
|
|
799
|
+
'HAUTE: AsyncLocalStorage + execution dynamique. Code malveillant cache dans un contexte async. ' +
|
|
800
|
+
'Examiner les callbacks AsyncLocalStorage. Verifier ce qui est stocke et execute dans le store.',
|
|
801
|
+
|
|
802
|
+
prototype_chain_constructor:
|
|
803
|
+
'CRITIQUE: Object.getPrototypeOf(var).constructor stocke dans une variable. Traversee de prototype pour Function. ' +
|
|
804
|
+
'Technique d\'evasion avancee. Supprimer le code. Verifier si le constructeur est appele avec du code dynamique.',
|
|
805
|
+
|
|
806
|
+
ci_environment_probe:
|
|
807
|
+
'HAUTE: Detection de 3+ fournisseurs CI (GitHub Actions, GitLab CI, etc.) dans le meme fichier. ' +
|
|
808
|
+
'Sondage d\'environnement CI pour activation conditionnelle. Verifier la logique conditionnelle associee.',
|
|
809
|
+
|
|
810
|
+
lifecycle_missing_script:
|
|
811
|
+
'CRITIQUE: Script lifecycle reference un fichier inexistant dans le package. Script fantome. ' +
|
|
812
|
+
'Le payload peut etre injecte dynamiquement ou lors d\'une mise a jour. Installer avec --ignore-scripts. Supprimer le package.',
|
|
701
813
|
};
|
|
702
814
|
|
|
703
815
|
function getPlaybook(threatType) {
|
package/src/rules/index.js
CHANGED
|
@@ -1523,7 +1523,7 @@ const RULES = {
|
|
|
1523
1523
|
id: 'MUADDIB-SHELL-019',
|
|
1524
1524
|
name: 'Python Time Delay Execution',
|
|
1525
1525
|
severity: 'HIGH',
|
|
1526
|
-
confidence:
|
|
1526
|
+
confidence: 'medium',
|
|
1527
1527
|
description: 'Execution Python avec delai time.sleep() >= 100s via child process. Technique d\'evasion sandbox (T1497.003) : le malware attend que la sandbox expire avant d\'executer le payload.',
|
|
1528
1528
|
references: ['https://attack.mitre.org/techniques/T1497/003/'],
|
|
1529
1529
|
mitre: 'T1497.003'
|
|
@@ -1850,6 +1850,310 @@ const RULES = {
|
|
|
1850
1850
|
],
|
|
1851
1851
|
mitre: 'T1071'
|
|
1852
1852
|
},
|
|
1853
|
+
|
|
1854
|
+
// Audit v3 Bypass Detections (AST-062 to AST-069)
|
|
1855
|
+
reflect_apply_require: {
|
|
1856
|
+
id: 'MUADDIB-AST-062',
|
|
1857
|
+
name: 'Reflect.apply(require) Bypass',
|
|
1858
|
+
severity: 'CRITICAL',
|
|
1859
|
+
confidence: 'high',
|
|
1860
|
+
description: 'Reflect.apply(require, null, [module]) detecte — contourne la detection statique de require() en passant par l\'API Reflect. Permet de charger child_process/fs/net sans appel require() direct.',
|
|
1861
|
+
references: [
|
|
1862
|
+
'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/apply',
|
|
1863
|
+
'https://attack.mitre.org/techniques/T1059/'
|
|
1864
|
+
],
|
|
1865
|
+
mitre: 'T1059'
|
|
1866
|
+
},
|
|
1867
|
+
finalization_registry_exec: {
|
|
1868
|
+
id: 'MUADDIB-AST-063',
|
|
1869
|
+
name: 'FinalizationRegistry Deferred Execution',
|
|
1870
|
+
severity: 'CRITICAL',
|
|
1871
|
+
confidence: 'high',
|
|
1872
|
+
description: 'new FinalizationRegistry() avec callback contenant child_process/exec/spawn. Le callback s\'execute apres le garbage collection, hors du flux d\'execution normal — technique d\'evasion sandbox qui differe l\'execution malveillante.',
|
|
1873
|
+
references: [
|
|
1874
|
+
'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/FinalizationRegistry',
|
|
1875
|
+
'https://attack.mitre.org/techniques/T1497/003/'
|
|
1876
|
+
],
|
|
1877
|
+
mitre: 'T1497.003'
|
|
1878
|
+
},
|
|
1879
|
+
function_prototype_constructor: {
|
|
1880
|
+
id: 'MUADDIB-AST-064',
|
|
1881
|
+
name: 'Function via Prototype Chain',
|
|
1882
|
+
severity: 'CRITICAL',
|
|
1883
|
+
confidence: 'high',
|
|
1884
|
+
description: '(function(){}).constructor(code) ou [].constructor.constructor(code) detecte — acces au constructeur Function via la chaine de prototypes, contourne les detections de new Function() et eval().',
|
|
1885
|
+
references: [
|
|
1886
|
+
'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function',
|
|
1887
|
+
'https://attack.mitre.org/techniques/T1059/'
|
|
1888
|
+
],
|
|
1889
|
+
mitre: 'T1059'
|
|
1890
|
+
},
|
|
1891
|
+
prototype_pollution: {
|
|
1892
|
+
id: 'MUADDIB-AST-065',
|
|
1893
|
+
name: 'Prototype Pollution',
|
|
1894
|
+
severity: 'HIGH',
|
|
1895
|
+
confidence: 'high',
|
|
1896
|
+
description: '__defineGetter__, __defineSetter__ ou assignation __proto__ detectee — pollution de prototype permettant de detourner les proprietes heritees de tous les objets. Vecteur d\'escalade pour injecter du code dans des chemins d\'execution inattendus.',
|
|
1897
|
+
references: [
|
|
1898
|
+
'https://portswigger.net/web-security/prototype-pollution',
|
|
1899
|
+
'https://attack.mitre.org/techniques/T1574/'
|
|
1900
|
+
],
|
|
1901
|
+
mitre: 'T1574'
|
|
1902
|
+
},
|
|
1903
|
+
module_wrap_override: {
|
|
1904
|
+
id: 'MUADDIB-AST-066',
|
|
1905
|
+
name: 'Module.wrap Override',
|
|
1906
|
+
severity: 'CRITICAL',
|
|
1907
|
+
confidence: 'high',
|
|
1908
|
+
description: 'Module.wrap = ... detecte — remplacement de la fonction wrapper du module loader Node.js. Permet d\'injecter du code dans CHAQUE module charge apres le remplacement, technique de persistence systemique.',
|
|
1909
|
+
references: [
|
|
1910
|
+
'https://nodejs.org/api/modules.html',
|
|
1911
|
+
'https://attack.mitre.org/techniques/T1574/006/'
|
|
1912
|
+
],
|
|
1913
|
+
mitre: 'T1574.006'
|
|
1914
|
+
},
|
|
1915
|
+
symbol_property_hiding: {
|
|
1916
|
+
id: 'MUADDIB-AST-067',
|
|
1917
|
+
name: 'Symbol Property Hiding',
|
|
1918
|
+
severity: 'HIGH',
|
|
1919
|
+
confidence: 'high',
|
|
1920
|
+
description: 'obj[Symbol(...)] = require(module_dangereux) detecte — dissimulation de modules dangereux derriere des proprietes Symbol, invisibles a Object.keys() et JSON.stringify(). Technique anti-forensics.',
|
|
1921
|
+
references: [
|
|
1922
|
+
'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol',
|
|
1923
|
+
'https://attack.mitre.org/techniques/T1564/'
|
|
1924
|
+
],
|
|
1925
|
+
mitre: 'T1564'
|
|
1926
|
+
},
|
|
1927
|
+
with_body_dangerous: {
|
|
1928
|
+
id: 'MUADDIB-AST-068',
|
|
1929
|
+
name: 'WithStatement Dangerous Body',
|
|
1930
|
+
severity: 'HIGH',
|
|
1931
|
+
confidence: 'high',
|
|
1932
|
+
description: 'with() statement dont le body contient require/exec/spawn/child_process — injection de scope pour obscurcir les appels dangereux. Le with() rend tous les identifiants ambigus, empechant l\'analyse statique de tracer les appels.',
|
|
1933
|
+
references: [
|
|
1934
|
+
'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/with',
|
|
1935
|
+
'https://attack.mitre.org/techniques/T1027/'
|
|
1936
|
+
],
|
|
1937
|
+
mitre: 'T1027'
|
|
1938
|
+
},
|
|
1939
|
+
require_process_mainmodule: {
|
|
1940
|
+
id: 'MUADDIB-AST-069',
|
|
1941
|
+
name: 'require("process").mainModule Bypass',
|
|
1942
|
+
severity: 'CRITICAL',
|
|
1943
|
+
confidence: 'high',
|
|
1944
|
+
description: 'require("process").mainModule.require() detecte — acces indirect au mainModule via require("process") au lieu de l\'objet global process. Contourne la detection de process.mainModule.require() qui ne surveille que l\'identifiant "process".',
|
|
1945
|
+
references: [
|
|
1946
|
+
'https://nodejs.org/api/process.html',
|
|
1947
|
+
'https://attack.mitre.org/techniques/T1059/'
|
|
1948
|
+
],
|
|
1949
|
+
mitre: 'T1059'
|
|
1950
|
+
},
|
|
1951
|
+
|
|
1952
|
+
// Blue Team v8 — New detections (AST-070 to AST-077, SHELL-023, SCORE-001/002)
|
|
1953
|
+
shared_memory_ipc: {
|
|
1954
|
+
id: 'MUADDIB-AST-070',
|
|
1955
|
+
name: 'Shared Memory IPC',
|
|
1956
|
+
severity: 'MEDIUM',
|
|
1957
|
+
confidence: 'medium',
|
|
1958
|
+
description: 'SharedArrayBuffer + Worker Thread detectes — canal IPC memoire partagee qui contourne la surveillance des messages inter-threads.',
|
|
1959
|
+
references: [
|
|
1960
|
+
'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer',
|
|
1961
|
+
'https://attack.mitre.org/techniques/T1559/'
|
|
1962
|
+
],
|
|
1963
|
+
mitre: 'T1559'
|
|
1964
|
+
},
|
|
1965
|
+
websocket_c2: {
|
|
1966
|
+
id: 'MUADDIB-AST-071',
|
|
1967
|
+
name: 'WebSocket C2 Channel',
|
|
1968
|
+
severity: 'HIGH',
|
|
1969
|
+
confidence: 'high',
|
|
1970
|
+
description: 'Connexion WebSocket vers un domaine suspect ou avec execution dynamique — canal C2 bidirectionnel persistant.',
|
|
1971
|
+
references: [
|
|
1972
|
+
'https://attack.mitre.org/techniques/T1071.001/',
|
|
1973
|
+
'https://owasp.org/www-community/attacks/WebSocket_Hijacking'
|
|
1974
|
+
],
|
|
1975
|
+
mitre: 'T1071.001'
|
|
1976
|
+
},
|
|
1977
|
+
udp_exfiltration: {
|
|
1978
|
+
id: 'MUADDIB-AST-072',
|
|
1979
|
+
name: 'UDP Data Exfiltration',
|
|
1980
|
+
severity: 'HIGH',
|
|
1981
|
+
confidence: 'high',
|
|
1982
|
+
description: 'Module dgram (UDP) avec envoi de donnees — exfiltration via protocole UDP qui contourne les firewalls HTTP.',
|
|
1983
|
+
references: [
|
|
1984
|
+
'https://nodejs.org/api/dgram.html',
|
|
1985
|
+
'https://attack.mitre.org/techniques/T1048.003/'
|
|
1986
|
+
],
|
|
1987
|
+
mitre: 'T1048.003'
|
|
1988
|
+
},
|
|
1989
|
+
native_addon_install: {
|
|
1990
|
+
id: 'MUADDIB-AST-073',
|
|
1991
|
+
name: 'Native Addon Installation',
|
|
1992
|
+
severity: 'HIGH',
|
|
1993
|
+
confidence: 'medium',
|
|
1994
|
+
description: 'binding.gyp present avec script lifecycle non-standard — compilation native potentiellement malveillante a l\'installation.',
|
|
1995
|
+
references: [
|
|
1996
|
+
'https://nodejs.org/api/addons.html',
|
|
1997
|
+
'https://attack.mitre.org/techniques/T1195.002/'
|
|
1998
|
+
],
|
|
1999
|
+
mitre: 'T1195.002'
|
|
2000
|
+
},
|
|
2001
|
+
string_mutation_obfuscation: {
|
|
2002
|
+
id: 'MUADDIB-AST-074',
|
|
2003
|
+
name: 'String Mutation Obfuscation',
|
|
2004
|
+
severity: 'HIGH',
|
|
2005
|
+
confidence: 'high',
|
|
2006
|
+
description: 'Chaine de 3+ appels .replace() pour reconstruire des noms d\'API dangereuses — technique leet-speak/substitution pour contourner la detection statique.',
|
|
2007
|
+
references: [
|
|
2008
|
+
'https://attack.mitre.org/techniques/T1027/',
|
|
2009
|
+
'https://attack.mitre.org/techniques/T1140/'
|
|
2010
|
+
],
|
|
2011
|
+
mitre: 'T1027'
|
|
2012
|
+
},
|
|
2013
|
+
crontab_systemd_write: {
|
|
2014
|
+
id: 'MUADDIB-SHELL-023',
|
|
2015
|
+
name: 'Crontab/Cron Write',
|
|
2016
|
+
severity: 'CRITICAL',
|
|
2017
|
+
confidence: 'high',
|
|
2018
|
+
description: 'Ecriture dans les fichiers cron (/etc/cron*, crontab, /var/spool/cron) — persistence via tache planifiee.',
|
|
2019
|
+
references: [
|
|
2020
|
+
'https://attack.mitre.org/techniques/T1053.003/',
|
|
2021
|
+
'https://attack.mitre.org/techniques/T1543/'
|
|
2022
|
+
],
|
|
2023
|
+
mitre: 'T1053.003'
|
|
2024
|
+
},
|
|
2025
|
+
isolated_suspicious_file: {
|
|
2026
|
+
id: 'MUADDIB-SCORE-001',
|
|
2027
|
+
name: 'Isolated Suspicious File',
|
|
2028
|
+
severity: 'MEDIUM',
|
|
2029
|
+
confidence: 'medium',
|
|
2030
|
+
description: 'Un seul fichier suspect parmi 10+ fichiers propres — pattern de dissimulation ou le code malveillant est cache dans un package legitime.',
|
|
2031
|
+
references: [
|
|
2032
|
+
'https://attack.mitre.org/techniques/T1036/'
|
|
2033
|
+
],
|
|
2034
|
+
mitre: 'T1036'
|
|
2035
|
+
},
|
|
2036
|
+
deep_suspicious_file: {
|
|
2037
|
+
id: 'MUADDIB-SCORE-002',
|
|
2038
|
+
name: 'Deeply Nested Suspicious File',
|
|
2039
|
+
severity: 'LOW',
|
|
2040
|
+
confidence: 'low',
|
|
2041
|
+
description: 'Pattern suspect detecte dans un fichier profondement imbrique (profondeur > 3) — technique de dissimulation dans l\'arborescence du package.',
|
|
2042
|
+
references: [
|
|
2043
|
+
'https://attack.mitre.org/techniques/T1036.005/'
|
|
2044
|
+
],
|
|
2045
|
+
mitre: 'T1036.005'
|
|
2046
|
+
},
|
|
2047
|
+
|
|
2048
|
+
// Blue Team v8b — New detections (AST-075 to AST-082, PKG-017)
|
|
2049
|
+
module_internals_hijack: {
|
|
2050
|
+
id: 'MUADDIB-AST-075',
|
|
2051
|
+
name: 'Module Internals Hijack',
|
|
2052
|
+
severity: 'CRITICAL',
|
|
2053
|
+
confidence: 'high',
|
|
2054
|
+
description: 'Assignation a Module._resolveFilename, _compile ou _extensions — detournement des mecanismes internes du systeme de modules Node.js. Tous les require() subsequents peuvent etre interceptes.',
|
|
2055
|
+
references: [
|
|
2056
|
+
'https://nodejs.org/api/modules.html',
|
|
2057
|
+
'https://attack.mitre.org/techniques/T1574.006/'
|
|
2058
|
+
],
|
|
2059
|
+
mitre: 'T1574.006'
|
|
2060
|
+
},
|
|
2061
|
+
json_reviver_pollution: {
|
|
2062
|
+
id: 'MUADDIB-AST-076',
|
|
2063
|
+
name: 'JSON Reviver Prototype Pollution',
|
|
2064
|
+
severity: 'HIGH',
|
|
2065
|
+
confidence: 'high',
|
|
2066
|
+
description: 'JSON.parse avec fonction reviver accedant a __proto__ ou prototype — pollution de prototype via donnees JSON non fiables.',
|
|
2067
|
+
references: [
|
|
2068
|
+
'https://portswigger.net/web-security/prototype-pollution',
|
|
2069
|
+
'https://attack.mitre.org/techniques/T1059.007/'
|
|
2070
|
+
],
|
|
2071
|
+
mitre: 'T1059.007'
|
|
2072
|
+
},
|
|
2073
|
+
vm_dynamic_code: {
|
|
2074
|
+
id: 'MUADDIB-AST-077',
|
|
2075
|
+
name: 'VM Dynamic Code Execution',
|
|
2076
|
+
severity: 'CRITICAL',
|
|
2077
|
+
confidence: 'high',
|
|
2078
|
+
description: 'vm.runInContext/runInNewContext/compileFunction avec code construit dynamiquement — evasion du sandbox via code genere au runtime.',
|
|
2079
|
+
references: [
|
|
2080
|
+
'https://nodejs.org/api/vm.html',
|
|
2081
|
+
'https://attack.mitre.org/techniques/T1059.007/'
|
|
2082
|
+
],
|
|
2083
|
+
mitre: 'T1059.007'
|
|
2084
|
+
},
|
|
2085
|
+
callback_exec_rce: {
|
|
2086
|
+
id: 'MUADDIB-AST-078',
|
|
2087
|
+
name: 'Callback Remote Code Execution',
|
|
2088
|
+
severity: 'CRITICAL',
|
|
2089
|
+
confidence: 'high',
|
|
2090
|
+
description: 'exec/spawn dans un callback .on(\'message\') ou .on(\'data\') avec child_process — execution de commandes a distance depuis un flux reseau.',
|
|
2091
|
+
references: [
|
|
2092
|
+
'https://attack.mitre.org/techniques/T1059/',
|
|
2093
|
+
'https://attack.mitre.org/techniques/T1071/'
|
|
2094
|
+
],
|
|
2095
|
+
mitre: 'T1059'
|
|
2096
|
+
},
|
|
2097
|
+
stego_binary_exec: {
|
|
2098
|
+
id: 'MUADDIB-AST-079',
|
|
2099
|
+
name: 'Steganographic Binary Execution',
|
|
2100
|
+
severity: 'CRITICAL',
|
|
2101
|
+
confidence: 'high',
|
|
2102
|
+
description: 'Lecture de fichier binaire/image (PNG, JPG) + execution dynamique (eval/Function) — extraction et execution de payload steganographique.',
|
|
2103
|
+
references: [
|
|
2104
|
+
'https://attack.mitre.org/techniques/T1027.003/',
|
|
2105
|
+
'https://attack.mitre.org/techniques/T1140/'
|
|
2106
|
+
],
|
|
2107
|
+
mitre: 'T1027.003'
|
|
2108
|
+
},
|
|
2109
|
+
asynclocal_context_exec: {
|
|
2110
|
+
id: 'MUADDIB-AST-080',
|
|
2111
|
+
name: 'AsyncLocalStorage Context Execution',
|
|
2112
|
+
severity: 'HIGH',
|
|
2113
|
+
confidence: 'medium',
|
|
2114
|
+
description: 'AsyncLocalStorage + execution dynamique — code malveillant cache dans un contexte asynchrone, echappe a l\'analyse de pile d\'appels synchrone.',
|
|
2115
|
+
references: [
|
|
2116
|
+
'https://nodejs.org/api/async_context.html',
|
|
2117
|
+
'https://attack.mitre.org/techniques/T1059.007/'
|
|
2118
|
+
],
|
|
2119
|
+
mitre: 'T1059.007'
|
|
2120
|
+
},
|
|
2121
|
+
prototype_chain_constructor: {
|
|
2122
|
+
id: 'MUADDIB-AST-081',
|
|
2123
|
+
name: 'Prototype Chain Constructor Access',
|
|
2124
|
+
severity: 'CRITICAL',
|
|
2125
|
+
confidence: 'high',
|
|
2126
|
+
description: 'Object.getPrototypeOf(variable).constructor extrait dans une variable — traversee de la chaine de prototypes pour atteindre le constructeur Function et executer du code arbitraire.',
|
|
2127
|
+
references: [
|
|
2128
|
+
'https://attack.mitre.org/techniques/T1059.007/',
|
|
2129
|
+
'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getPrototypeOf'
|
|
2130
|
+
],
|
|
2131
|
+
mitre: 'T1059.007'
|
|
2132
|
+
},
|
|
2133
|
+
ci_environment_probe: {
|
|
2134
|
+
id: 'MUADDIB-AST-082',
|
|
2135
|
+
name: 'CI Environment Fingerprinting',
|
|
2136
|
+
severity: 'HIGH',
|
|
2137
|
+
confidence: 'medium',
|
|
2138
|
+
description: 'References a 3+ variables d\'environnement de fournisseurs CI (GITHUB_ACTIONS, GITLAB_CI, etc.) — sondage d\'environnement CI pour activation conditionnelle de payload.',
|
|
2139
|
+
references: [
|
|
2140
|
+
'https://attack.mitre.org/techniques/T1082/',
|
|
2141
|
+
'https://attack.mitre.org/techniques/T1497/'
|
|
2142
|
+
],
|
|
2143
|
+
mitre: 'T1082'
|
|
2144
|
+
},
|
|
2145
|
+
lifecycle_missing_script: {
|
|
2146
|
+
id: 'MUADDIB-PKG-017',
|
|
2147
|
+
name: 'Phantom Lifecycle Script',
|
|
2148
|
+
severity: 'CRITICAL',
|
|
2149
|
+
confidence: 'high',
|
|
2150
|
+
description: 'Script lifecycle (preinstall/install) reference un fichier qui n\'existe pas dans le package — script fantome, le payload peut etre injecte au moment de la publication.',
|
|
2151
|
+
references: [
|
|
2152
|
+
'https://attack.mitre.org/techniques/T1195.002/',
|
|
2153
|
+
'https://blog.npmjs.org/post/166316363605/the-lifecycle-script-vulnerability'
|
|
2154
|
+
],
|
|
2155
|
+
mitre: 'T1195.002'
|
|
2156
|
+
},
|
|
1853
2157
|
};
|
|
1854
2158
|
|
|
1855
2159
|
function getRule(type) {
|
|
@@ -1912,4 +2216,23 @@ for (const [, rule] of Object.entries(PARANOID_RULES)) {
|
|
|
1912
2216
|
PARANOID_RULES_BY_ID[rule.id] = rule;
|
|
1913
2217
|
}
|
|
1914
2218
|
|
|
2219
|
+
// Validate all rules at load time
|
|
2220
|
+
const VALID_SEVERITIES = new Set(['CRITICAL', 'HIGH', 'MEDIUM', 'LOW']);
|
|
2221
|
+
const VALID_CONFIDENCES = new Set(['high', 'medium', 'low']);
|
|
2222
|
+
|
|
2223
|
+
for (const [key, rule] of Object.entries(RULES)) {
|
|
2224
|
+
if (!VALID_SEVERITIES.has(rule.severity)) {
|
|
2225
|
+
throw new Error(`Rule "${key}" has invalid severity: ${JSON.stringify(rule.severity)} (expected CRITICAL|HIGH|MEDIUM|LOW)`);
|
|
2226
|
+
}
|
|
2227
|
+
if (!VALID_CONFIDENCES.has(rule.confidence)) {
|
|
2228
|
+
throw new Error(`Rule "${key}" has invalid confidence: ${JSON.stringify(rule.confidence)} (expected high|medium|low)`);
|
|
2229
|
+
}
|
|
2230
|
+
}
|
|
2231
|
+
// PARANOID_RULES use a different schema (patterns/message, no confidence field)
|
|
2232
|
+
for (const [key, rule] of Object.entries(PARANOID_RULES)) {
|
|
2233
|
+
if (!VALID_SEVERITIES.has(rule.severity)) {
|
|
2234
|
+
throw new Error(`Paranoid rule "${key}" has invalid severity: ${JSON.stringify(rule.severity)} (expected CRITICAL|HIGH|MEDIUM|LOW)`);
|
|
2235
|
+
}
|
|
2236
|
+
}
|
|
2237
|
+
|
|
1915
2238
|
module.exports = { RULES, getRule, PARANOID_RULES };
|