Intégrer la CTI à QRadar #3 – Python et QRadar
Nous voici dans le troisième épisode de cette série d’articles axée sur la CTI intégrée à QRadar. Nous avons vu précédemment comment interagir avec OpenCTI et comment récupérer les informations présentes sur la plateforme.
Dans la suite de cet article vous allez voir le côté technique de la deuxième partie du script présenté en introduction de cette série d’articles, à savoir comment interagir avec QRadar. Vous allez apprendre non seulement à récupérer des informations présentes sur votre instance QRadar mais également comment modifier des informations. Nous verrons quelques bases ainsi que quelques exemples mais les principes généraux qui vont être expliqués sont utilisables et modifiables selon vos souhaits.
2. Découverte de l’API QRadar
Tout d’abord nous allons voir où nous pouvons échanger avec l’API de QRadar. Nous avions vu dans l’épisode précédent que pour OpenCTI, un "playground" était mis à disposition, permettant à chacun de pouvoir s’entraîner / peaufiner ses requêtes avant d’implémenter le tout dans un code.
IBM offre la même option avec la page d’API que vous retrouverez en allant sur l’URL suivante : "https://<QRADAR_FQDN>/api_doc" en étant connecté avec un compte ayant les droits suffisants bien évidemment. Une fois arrivé sur la page on constate qu’il existe un grand nombre d’endpoints API disponibles, pour chacun il est possible de faire des tests comme ci-dessous.
Comme vous pouvez le voir dans l’exemple ci-dessus, chaque endpoint est également accessible via une unique URL. Dans le panel de droite, plusieurs sections s’offrent à vous :
- "Description" : correspond à ce que fait cet endpoint API
- "Response Description" : explique la réponse renvoyée par l’API QRadar, avec notamment les différentes clés/valeurs
- "Success & Error Responses" : liste les différents codes de réponse de l’API et une brève explication pour chacun
- "Response Type" : montre le formatage de la réponse de l’API
- "Parameters" : liste les paramètres qu’il est possible de configurer pour cet endpoint, pour chacun il y a plusieurs sections qui permettent de mieux comprendre ce qui est attendu
- "cURL" : affiche la requête cURL correspondante à vos choix
Je vais mettre dans la section Bibliographie plusieurs ressources qui m’ont aidé dans la compréhension de l’API.
a. Bases des requêtes
Maintenant que nous maîtrisons un peu plus l’API de QRadar et son fonctionnement, nous allons voir comment intégrer le tout dans un script. Il existe plusieurs méthodes et nous verrons ici l’utilisation du module "requests" en langage "Python", n’hésitez pas à commenter avec d’autres solutions possibles.
Voici ci-dessous la structure d’une requête de base que nous allons expliquer :
>>> import requests
>>> QRadar_URL = """https://<QRADAR_FQDN>/api/system/about"""
>>> QRadar_request_headers = {
'SEC':'<QRADAR_TOKEN>',
'Content-Type':'application/json',
'accept':'application/json'
}
>>> QRadar_request = requests.get(QRadar_request_URL, headers=QRadar_request_headers, verify=False)
>>> QRadar_request.text
'{"release_name":"7.3.3","build_version":"2019.14.0.20191031163225","external_version":"7.3.3"}'
Si on reprend les actions une par une :
- importation du module
- on enregistre l’endpoint API dans une variable
- on enregistre le header de la requête dans une variable
- on exécute la requête
- on affiche le résultat
Pour que le tout fonctionne de votre côté il faut bien penser à modifier les paramètres suivants :
- <QRADAR_FQDN> qui correspond à l’IP, ou le FQDN de votre instance QRadar.
- <QRADAR_TOKEN> qui correspond au token au format UUID. Pour créer votre token, il faut aller sur l’URL "https://<QRADAR_FQDN>/console/do/qradar/authorizedService?dispatch=authorizedServiceList" puis créer un token avec un "User Role" et un "Security Profile" valant "Admin".
Et voilà, notre première requête basique fonctionne et nous pouvons, dans ce cas précis, intégrer dans un script la récupération des informations systèmes de notre instance QRadar.
b. Interaction avec les référentiels QRadar
Pour correspondre à nos besoins, il nous faut pouvoir récupérer et interagir avec les informations des référentiels dans QRadar. En cherchant un peu dans la documentation on trouve l’endpoint API suivant : "reference_data/maps". De manière plus globale toute la section "reference_data" de l’API est très intéressante en ce qui concerne la récupération d’informations, je vous invite à vous y perdre pour voir tout ce qu’il est possible de faire.
i. Récupération d’éléments dans un référentiel
Dans un premier temps nous allons voir comment récupérer les informations d’un référentiel lambda pour lequel nous avons seulement le nom.
- On choisit l’endpoint "/reference_data/maps/{name}"
- On spécifie que l’on souhaite faire une requête GET
- On entre le nom de notre référentiel (qu’il faut créer au préalable dans la GUI QRadar)
- On modifie le nombre d’éléments que l’on souhaite avoir en retour, ici je ne souhaite que 2 éléments comme j’effectue des tests
- On lance la requête
Et avant de passer à la suite, on note sur le côté l’URL du "cURL" :
https://<QRADAR_FQDN>/api/reference_data/maps/TEST_IP
Une fois la requête exécutée et si votre référentiel existe vous obtiendrez un résultat similaire à ce dernier :
Avec :
- En valeur de la clé "data", tous les éléments de votre référentiel, je l’ai encadré ici et noté ①.
- Dans les valeurs de la clé "data", vous retrouverez autant de clés que vous avez d’éléments dans votre liste (contre exemple ici car j’ai demandé à n’afficher que 2 éléments pour que cela soit plus lisible). Donc on voit bien les clés que sont les 2 IPs que j’ai encadrées et obfusquées avec comme valeur une liste de clés/valeurs qui sont encadrée et notée ② et ③.
- On note également, en surligné au début de la réponse, la valeur "37888", qui est le nombre d’éléments dans le référentiel. Cela pourra nous servir dans le script par exemple.
- On note enfin, en surligné et à la fin de la réponse, la valeur "TEST_IP", qui est tout simplement le nom de notre référentiel.
ii. Ajout d’éléments dans un référentiel
Maintenant que nous savons comment récupérer les informations d’un référentiel, voyons comment en ajouter ou en supprimer. S’il l’on remonte un peu dans l’arborescence de l’API on trouve l’endpoint suivant :
- On choisit le endpoint "/reference_data/maps/bulk_load/{name}"
- On spécifie que l’on souhaite faire une requête POST
- On entre le nom de notre référentiel (qu’il faut créer au préalable dans la GUI QRadar)
- On entre le JSON des données que l’on souhaite ajouter à notre référentiel (il faut bien respecter le format qui est expliqué dans la colonne "Sample")
- On lance la requête
Et avant de passer à la suite, on note sur le côté l’URL du "cURL" :
https://<QRADAR_FQDN>/api/reference_data/maps/bulk_load/TEST_IP
avec les données suivantes :
{"127.0.0.1":"60","127.0.0.2":"61"}
Une fois la requête exécutée, nous avons un code 200 si l’ajout s’est bien déroulé avec un résumé du référentiel. Comme vous pouvez le voir j’ai une IP en plus (37889).
iii. Suppression d’éléments dans un référentiel
Enfin, nous avons besoin de pouvoir supprimer des éléments, pour cela nous allons utiliser un autre endpoint décrit ci-dessous :
- On choisit l’endpoint "/reference_data/maps/{name}/{key}"
- On spécifie que l’on souhaite faire une requête DELETE
- On entre le nom de notre référentiel (qu’il faut créer au préalable dans la GUI QRadar)
- On entre la clé que l’on souhaite supprimer, ici l’IP que l’on souhaite enlever de notre référentiel
- On entre la valeur de la clé que l’on souhaite supprimer, ici le score de l’IP en question
- On lance la requête
Et avant de passer à la suite, on note sur le côté l’URL du "cURL" :
https://<QRADAR_FQDN>/api/reference_data/maps/TEST_IP/127.0.0.1?value=50
Une fois la requête exécutée, nous avons un code 200 si la suppression s’est bien déroulée avec un résumé du référentiel. Ainsi nous retournons au nombre d’éléments initial du référentiel, à savoir 37888.
3. Requêtes Python
Nous voici dans la dernière partie de cet article, nous allons voir comment scripter tout ce que nous avons vu dans la partie précédente afin de pouvoir l’utiliser industriellement.
a. Récupération et suppression des données
Premièrement, pour la récupération des données, nous avons vu que c’est une requête GET, utilisant l’URL suivant :
https://<QRADAR_FQDN>/api/reference_data/maps/TEST_IP
Ainsi, nous n’avons qu’à appliquer les bases de la requête que nous avons vue en début d’article tout en changeant l’URL à atteindre par le script pour obtenir la base suivante :
>>> QRadar_FQDN = "<QRADAR_FQDN>"
>>> QRadar_Ref_Name = "TEST_IP"
>>> QRadar_request_headers = {
'SEC':'<QRADAR_TOKEN>',
'Content-Type':'application/json',
'accept':'application/json'
}
>>> QRadar_URL = """https://{0}/api/reference_data/maps/{1}""".format(QRadar_FQDN, QRadar_Ref_Name)
>>> QRadar_request = requests.get(QRadar_URL, headers=QRadar_request_headers, verify=False)
>>> QRadar_request.status_code
200
Si vous avez comme moi un code 200, c’est que tout s’est bien passé, sinon je vous invite à reprendre la documentation de l’API ainsi que le message retourné par l’API (récupérable dans la variable "QRadar_request.text") pour comprendre l’erreur. N’hésitez pas à poser des questions ou exposer vos problèmes en commentaires si vous en rencontrez.
En ce qui concerne la suppression, c’est le même principe, il suffit d’utiliser la méthode "delete()" à la place de la méthode "get()" et utiliser l’endpoint vu dans la précédente partie.
b. Téléversement des données
Deuxièmement, pour l’envoi des données dans un référentiel donné, nous avons constaté que la requête était un POST utilisant le format d’URL suivant :
https://192.168.1.174/api/reference_data/maps/bulk_load/TEST_IP
avec un champ de datas structuré comme ceci :
{"key1":"Data1",
"key2":"Data2",
"key3":"Data3",
"key4":"Data4",
"key5":"Data5",
"key6":"Data6"}
Nous ne pouvons donc pas appliquer la même méthode que précédemment mais utiliser la méthode adéquate que vous retrouverez ci-dessous :
>>> QRadar_FQDN = "<QRADAR_FQDN>"
>>> QRadar_Ref_Name = "TEST_IP"
>>> QRadar_request_headers = {
'SEC':'<QRADAR_TOKEN>',
'Content-Type':'application/json',
'accept':'application/json'
}
>>> Datas_to_upload = str({"127.0.0.2":"60","127.0.0.3":"61"})
>>> QRadar_URL = """https://{0}/api/reference_data/maps/bulk_load/{1}""".format(QRadar_FQDN, QRadar_Ref_Name)
>>> QRadar_request = requests.post(QRadar_URL, data=Datas_to_upload, headers=QRadar_request_headers, verify=False)
>>> QRadar_request.status_code
200
>>> QRadar_request.text
'{"timeout_type":"FIRST_SEEN","number_of_elements":37891,"creation_time":1674335219527,"name":"TEST_IP","element_type":"NUM"}'
Si vous avez comme moi un code 200, c’est que tout s’est bien passé, sinon je vous invite à reprendre la documentation de l’API ainsi que le message retourné par l’API (récupérable dans la variable "QRadar_request.text") pour comprendre l’erreur. N’hésitez pas à poser des questions ou exposer vos problèmes en commentaires si vous en rencontrez.
c. Formatage des données
Nous avons vu comment effectuer les différentes actions de façon automatisée dans un script, avant de passer à la conclusion, nous allons voir comment formater les données pour pouvoir les utiliser facilement.
Comme dans le précédent article, nous allons utiliser la librairie "json" de Python qui va faire le travail pour nous.
Dans l’exemple ci-dessous, nous allons afficher chaque IP avec son score pour chaque entrée dans un référentiel QRadar. On suppose que la requête a été faite avec succès.
QRadar_request_json = json.loads(QRadar_request.text)
for IP in QRadar_request_json["data"].keys():
print("""Le score de l'IP "{0}" est {1}/100 """.format(IP, QRadar_request_json["data"][IP]["value"]))
Ensuite, libre à vous de récupérer les informations comme vous le souhaitez. En effet, les objets JSON sont très facilement manipulables et compréhensibles.
4. Conclusion
Nous sommes déjà à la conclusion de cet article qui vous explique comment utiliser l’API QRadar et l’associer avec des scripts en Python.
N’hésitez pas également à partager vos idées à ce sujet pour que nous puissions tous en profiter.
5. Bibliographie
- Documentation IBM sur l’API : http://ftpmirror.your.org/pub/misc/ftp.software.ibm.com/software/security/products/qradar/documents/7.3.0/en/b_qradar_api.pdf
- Explication du fonctionnement de l’API : Creating reference data collections with the APIs