
MachForm est un logiciel écrit en PHP, développé par APPNITRO SOFTWARE. Il permet d’héberger et créer sois même des formulaires complexes et gérer les remontées utilisateurs dans son interface d’administration.
Lors d’un test d’intrusion d’application web, Vladimir TOUTAIN a découvert deux vulnérabilités majeures exploitables par un attaquant authentifié sur le backend avec l’accès aux entrées d’au moins un formulaire. Elles permettent d’exécuter des requêtes SQL arbitraires (injections SQL) en base de données afin d’y lire les données de formulaires auxquels l’attaquant n’a pas accès, récupérer les informations de configuration, et peut permettre le vol de compte arbitraire. Les versions de MachForm < v25 sont affectées avec un correctif déployé par l’éditeur en v25.
Détails des vulnérabilités
L’application pentestée en boîte noire était en dernière version de MachForm à date (v24), il n’existait donc pas de CVE exploitables connues sur cette version. L’auditeur s’est donc concentré sur la configuration réalisée par le client : permissions du compte et des formulaires, durcissement sécurité du serveur web, configuration MachForm. Ne trouvant pas de défauts, il a entrepris de chercher de nouvelles vulnérabilités sur la solution MachForm v24 – des vulnérabilités zero-days à exploiter.
Deux injections SQL authentifiées ont été découvertes et sont relatives à la gestion des entrées des formulaires : dans l’export CSV filtré, et dans leur affichage filtré.
1/ SQLi dans l’export filtré des entrées
Le paramètre « entries_id » envoyé au serveur lors d’une requête HTTP GET vers « export_entries.php » (export CSV filtré des entrées d’un formulaire) n’est pas filtré correctement et permet d’extraire les données stockées en base: des commandes SQL sont injectées dans l’entrée utilisateur afin d’affecter l’exécution de commandes SQL prédéfinies.
Cette vulnérabilité peut être exploitée par un attaquant authentifié ayant accès aux entrées d’un formulaire avec un technique basée sur UNION ce qui permet de facilement récupérer les données en base. En revanche, des limitations techniques la rendent difficile à exploiter : le caractère « , » est modifié en « ‘,' » dans la requête finale ce qui empêche de construire librement la charge utile. En outre, la taille des données retournées est limitée ce qui peut nécessiter de construire l’exploit en plusieurs requêtes afin d’extraire de grandes quantités de données. L’exploit varie également en fonction du nombre de champs paramétrés dans le formulaire.
/export_entries.php?type=csv&form_id=XXXXXX&csrf_token=TOKEN&entries_id=186,185185′)+UNION+SELECT+(select+database())’,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′–+UgjQ&incomplete_entries=0&selected_fields=1
La réponse à la requête « select database() » se trouvera dans l’export CSV retourné par le serveur.
Il est alors possible d’extraire des sessions valides d’autres utilisateurs, ou de forcer une réinitialisation de mot de passe puis de voler le reset_hash contenu dans la table ap_users. Notez que même si l’authentification LDAP est activée et que la GUI ne montre pas l’option de réinitialisation de mot de passe, une requête POST vers reset_password.php sera acceptée et le reset_hash pourra être envoyé à reset.php encodé en en base64 dans le paramètre GET « q » :
/reset.php?q=dXNlcl9pZD0xMzM3JnJlc2V0X2hhc2g9MzdjZWU5ZmExYTI2MjZhZWVmYWZkZWFkYmVlZg==
2/ SQLi dans la fonctionnalité de filtre des entrées
Le champ JSON « element_name » de l’objet « filter_prop » envoyé au serveur lors d’une requête HTTP POST vers « save_filter.php » (affichage filtré des entrées d’un formulaire) n’est pas correctement sécurisé et permet d’extraire les données stockées en base: des commandes SQL sont injectées dans l’entrée utilisateur afin d’affecter l’exécution de commandes SQL prédéfinies. Cette injection est dite de second ordre car la requêtes vers save_filter.php permet de sauvegarder le filtre, l’injection est en réalité exécutée lors de l’affichage des entrées du formulaire ainsi attaqué.
Cette vulnérabilité peut être exploitée par un attaquant authentifié ayant accès aux entrées d’un formulaire. Elle est en revanche complexe à exploiter car la taille de l’injection est limitée et il n’y a pas le retour du résultat (BOOLEAN BLIND).
Afin de l’exploiter avec sqlmap il est possible d’utiliser des options avancées :
sqlmap -r actual_sqli –force-ssl –dbms=mysql –level 5 –risk 3 –second-req=second_order_request
Dans cette commande sqlmap nous donnons la requête HTTP vulnérable par le fichier actual_sqli puis la deuxième requête HTTP à effectuer pour récupérer le résultat de l’injection dans le fichier second_order_request.
Contenu de acutal_sqli :
Contenu de second_order_request :
L’exploitation de cette injection SQL est plus complexe et demandera plus de temps puisqu’elle est de type blind.
Communication avec l’éditeur
Le formulaire de contact d’Appnitro Software a été utilisé afin de demander comment les informer de manière sécurisée des vulnérabilités découvertes.
La réponse a été très rapide, tout comme la qualification des vulnérabilités ainsi que leur correction.
18/03/2025 : Formulaire de contact utilisé
18/03/2025 : Retour du fondateur d’Appnitro Software et envoi des détails de la vulnérabilité dans la foulée
20/03/2025 : Retour de Appnitro Software confirmant les vulnérabilités et indiquant leur correction en v25. Accord sur un calendrier de divulgation.
29/03/2025 : MachForm v25 publié https://www.machform.com/blog-machform-25-released/
04/04/2025 : Publication de cet article
🛡️ DSecBypass vous accompagne sur les audits de sécurité de vos applications métier. N’hésitez pas à nous contacter pour des informations complémentaires et/ou un devis personnalisé 📝.