Les mesures de sécurité sont inévitables lors du développement d'applications Web. Parmi eux, "l'injection SQL" est connue comme une menace grave pour les bases de données.
Dans cet article, expliquerons de manière facile à comprendre comment fonctionne l'injection SQL et montrerons comment les attaques sont réellement réalisées. De plus, une implémentation sûre à l'aide de Spring Boot et Mybatis, avec du code! Il s'agit d'une lecture incontournable pour les développeurs Web, des débutants aux joueurs intermédiaires.
Qu'est-ce que l'injection SQL? Découvrez les dangers des attaques à travers des vidéos!
L'injection SQL est une attaque qui utilise des vulnérabilités dans une application pour lancer des opérations frauduleuses sur une base de données.
Même si vous le trouvez "ça a l'air un peu difficile ...", vous pourrez avoir une idée approximative du type d'attaque en regardant la courte vidéo ci-dessous!
📺 Regardez la démo sur YouTube : vous pouvez le regarder à partir de ce lien
La vidéo explique comment l'injection SQL fonctionne avec des exemples simples.
Jetez un coup d'œil et passez à la section suivante pour en savoir plus!
Qu'est-ce que l'injection SQL?
une technique d'attaque dans laquelle un attaquant injecte du code SQL malveillant lorsqu'une application interagit avec une base de données ce qui fait effectuer un attaquant d'effectuer des opérations illicites.
- Acquisition non autorisée de données : les informations utilisateur et les données sensibles peuvent être divulguées.
- Contournant l'authentification : un attaquant peut être en mesure de se connecter sans autorisation.
- Tamponnage et suppression des données : la base de données est manipulée et la fiabilité est compromise.
Comment fonctionne l'injection SQL dans des exemples concrètes
La fonction de connexion explique comment elle fonctionne. Par exemple, pour les paramètres suivants, SQL est converti comme ceci:
- Nom d'utilisateur:
admin
- Mot de passe:
mot de passe
Sélectionnez Count (*)> 0 dans les utilisateurs où username = 'admin' et mot de passe = 'mot de passe';
C'est un comportement normal, mais ce qui se passe si un attaquant saisit quelque chose comme ceci:
- Nom d'utilisateur:
'ou' 1 '=' 1 '-
- Mot de passe:
toute valeur
Cela peut être réécrit comme suit:
Sélectionnez Count (*)> 0 dans les utilisateurs où username = '' ou '1' = '1' - et mot de passe = 'toute valeur';
Résultat : - et mot de passe = «Toute valeur»
est commenté par -
Ou '1' = '1
est toujours vrai, donc tous les utilisateurs sont considérés comme des connexions authentifiées et non autorisées sont possibles.
Comment gérer l'injection SQL
L'injection SQL est une menace grave pour la sécurité des applications. Cependant, la prise de mesures appropriées peut atténuer efficacement ce risque.
Cette fois, nous expliquerons comment prendre des mesures en utilisant Spring Boot et Mybatis Apprenez à créer des applications sécurisées en tirant parti de ces outils.
1. Utilisez une requête paramétrée avec des espaces réservés
Résumé : liez en toute sécurité les paramètres à l'aide des espaces réservés (# {}) plutôt que d'intégrer l'entrée utilisateur directement dans les instructions SQL.
Raison : les espaces réservés échappent automatiquement aux valeurs d'entrée et empêchent l'injection SQL.
Vous trouverez ci-dessous les codes qui utilisent des espaces réservés et des codes qui ne sont pas utilisés.
Les différences sont les pièces "'$ {nom d'utilisateur}' → # {nom d'utilisateur} '" et "' $ {mot de passe} '→ # {mot de passe}'".
Dans le cas de MyBatis, vous pouvez lier en toute sécurité les paramètres en le définissant sur
# {}
Si vous souhaitez utiliser des paramètres tels quels dans SQL, assurez-vous d'utiliser # {}
Vulnérable
@Select ("SELECT COUNT (*)> 0 From Users Where Username = '$ {username}' et mot de passe = '$ {mot de passe}'") booléen vulnerableAuthenticate (@param ("" username ") String username, @param (" mot de passe ") String Motways);
sécurité
@Select ("SELECT COUNT (*)> 0 From Users Where username = # {username} et mot de passe = # {mot de passe}") Boolean SecureAuthentiCate (@param ("username") String Name, @param ("mot de passe") Mot de passe de chaîne);
2. Vérification et désinfection des entrées utilisateur
Résumé : restreint les types et les formats que les utilisateurs peuvent entrer, empêchant l'entrée illégale.
Raison : la suppression des chaînes dangereuses et des mots clés SQL peut réduire considérablement le taux de réussite de votre attaque.
restreindre le type de caractère et le format d'un paramètre, ou supprimer ou échapper aux caractères spécifiques (par exemple '
, -
,; etc.
) pour éviter l'injection de SQL.
if (! username.matches ("^ [a-za-z0-9] + $")) {lancez new illégalargumentException ("entrée invalide"); }
Fondamentalement, il est préférable de considérer "1. Utilisez une requête paramétrée avec des espaces réservées", mais si elle est impossible, cette solution peut réduire considérablement le taux de réussite de l'attaque.
3. Évitez de construire des requêtes dynamiques
Résumé : utilise des requêtes paramétrées plutôt que de générer dynamiquement des instructions SQL avec des opérations de chaîne.
Raison : la construction de SQL avec des manipulations de cordes rend l'injection SQL plus probable.
Ceci est un peu différent des contre-mesures, mais je pense qu'il est préférable de comprendre
que l'utilisation de la manipulation de chaîne (+ opérateurs ou String.format) lors de l'assemblage de SQL dynamique entraînera un risque d'injection de SQL.
MyBatis est conçu par défaut pour éviter d'utiliser les opérations de chaîne pour construire directement les requêtes, ce n'est donc pas un problème, mais soyez prudent si vous utilisez des opérations de chaîne lorsque vous assemblez Dynamic SQL.
Dans les cas précédents, j'ai vu des sources qui construisent une instruction WHERE en utilisant la manipulation de la chaîne et la définissent avec $ {}.
Dans ce cas, bien sûr, la possibilité d'injection SQL augmente.
Public String buildWheReClause (Nom d'utilisateur de chaîne, chaîne Email) {String whiteClause = "Where 1 = 1"; if (username! = null) {whereclause + = "et username = '" + username + "'"; } if (email! = null) {whereclause + = "et e-mail = '" + email + "'"; } return whereClause; } @Select ("SELECT * FROM Users $ {whereclause}")<User> FINDUSERS (@param ("whereclause") String whereclause);
Dans le cas de Mybatis,<if> Vous pouvez générer des requêtes dynamiques en utilisant cette option, alors assurez-vous de l'utiliser.
<select id="findUsers" resultType="User">Sélectionnez * chez les utilisateurs où 1 = 1<if test="username != null"> Et nom d'utilisateur = # {nom d'utilisateur}</if><if test="email != null"> Et email = # {email}</if></select>
4. Autre
Il existe plusieurs autres façons de réduire l'injection de SQL, mais il est important de comprendre qu'il n'est pas parfait et n'est qu'une atténuation.
- Définir les autorisations de base de données minimales
- Utilisation des procédures stockées
- Déploiement du pare-feu d'application Web (WAF)
- etc.
Exemple d'implémentation à l'aide de Spring Boot + Mybatis
Comme mentionné sur YouTube, nous avons inclus un exemple d'implémentation qui vous permet de démontrer réellement l'injection SQL.
L'ensemble du code source est publié sur GitHub, alors veuillez le vérifier si vous en avez besoin.
💾 Référentiel GitHub : vérifiez le code source de ce lien
Contrôleur
package com.youtube.security.app.security_demo.Controller; import com.youtube.security.app.security_demo.repository.sqlinjectionmapper; import org.springframework.web.bind.annotation.postmapping; import org.springframework.web.bind.annotation.requestParam; import org.springframework.web.bind.annotation.restController; / ** * Ce contrôleur montre comment les vulnérabilités d'injection SQL se produisent et fournit une implémentation sécurisée en utilisant * MyBatis. * * L'injection SQL est un type d'attaque qui rend * des instructions SQL arbitraires possibles sur une base de données en injectant le code SQL malveillant dans une requête. * * Exemple d'implémentation sûre: * - Utilisez une requête paramétrée avec les espaces réservés * -> empêche l'injection SQL en utilisant des espaces réservés (# {}) au lieu d'incorporer la saisie de l'utilisateur directement dans la requête. * - Vérifiez et désinfectez les entrées de l'utilisateur * -> Augmenter la sécurité en limitant le type de caractère que l'utilisateur peut entrer, et en supprimant et en échappant aux caractères et symboles dangereux. * - Évitez la génération de SQL dynamique avec les opérations de chaîne * -> en utilisant les opérations de chaîne (+ opérateurs et String.format) lors de l'assemblage de SQL dynamique augmente le risque d'injection SQL. * -> Il est important d'assembler les requêtes de manière sûre, et non de les générer dynamiquement avec des manipulations de chaînes. * -> MyBatis est conçu par défaut pour éviter la façon de construire des requêtes directement à l'aide de la manipulation de la chaîne. * * * Cette classe ne doit être utilisée qu'à des fins éducatives. * / @RestController Classe publique SQLinjectionController {private final sqlinjectionmapper sqlinjectionmapper; public sqlinjectionController (sqlinjectionmapper sqlinjectionmapper) {this.sqlinjectionmapper = sqlinjectionmapper; } / ** * Exemple d'une requête vulnérable utilisant MyBatis. * * @param nom d'utilisateur username * @param mot de passe mot de passe * @return Result de connexion (succès ou échec) * / @postmapping ("/ login / vulnérable") public String vulnerableLogin (@RequestParam String username, @requestParam String Passway sqlinjectionmapper.vulnerableAuthenticate (nom d'utilisateur, mot de passe); Retour isAuthenticated? "Success Login (Implémentation vulnérable)": "Échec de la connexion (implémentation vulnérable)"; } / ** * Exécutez des requêtes paramétrées à l'aide de MyBatis. * * @param nom d'utilisateur nom d'utilisateur * @param mot de passe mot de passe * @return Résultat de connexion (succès ou échec) * / @PostMapping ("/ Login / Secure") Public String SecureLogin (@RequestParam String Username, @requestParam Mot de passe) {// Appelez MyBatis Secure Query Boolean Isauthenticated = SQLinIectMapper.SecureAralicate (Usauthenticated); Retour isAuthenticated? "Connexion réussie (implémentation sécurisée)": "Échec de la connexion (Implémentation sécurisée)"; }}
Tabac
package com.youtube.security.app.security_demo.Repository; import org.apache.ibatis.annotations.mapper; import org.apache.ibatis.annotations.param; import org.apache.ibatis.annotations.Select; @Mapper interface publique SQLinjectionMapper {/ ** * Méthode qui exécute des requêtes SQL vulnérables. * @param nom d'utilisateur * @param mot de passe mot de passe * @return true si l'authentification est réussie, false si l'échec * / @Select ("SELECT COUNT (*)> 0 chez les utilisateurs où username = '$ {username}' et mot de passe = '$ {mot de passe}'") Boolean VulnerableAuthentate (@param ("username") String username, @param ("" "); / ** * Méthode d'exécution d'une requête SQL sécurisée. * @param username username * @param mot de passe mot de passe * @return true si l'authentification est réussie, false si l'échec * / @Select ("SELECT COUNT (*)> 0 chez les utilisateurs où username = # {username} et mot de passe = # {mot de passe}") Boolean SecureAuthenticiate (@param ("username") string nom de filet, @param ("mot de passe"); }
Pratique de l'injection SQL
Nous avons des outils pour vous aider à pratiquer l'injection SQL.
Il est disponible sur GitHub, alors veuillez en utiliser. (Même si vous ne l'utilisez pas, vous pouvez simplement envoyer la même demande et il n'y a pas de problème.)
💾 Référentiel GitHub : vérifiez le code source de ce lien
La vidéo YouTube suivante montre une attaque d'injection SQL. Ce contenu vous permet de vivre des exemples spécifiques d'attaques en personne, alors jetez un œil.
📺 Regardez la démo sur YouTube : vous pouvez le regarder à partir de ce lien
La vidéo montre comment les attaques d'injection SQL exploitent les vulnérabilités d'application. C'est une simple démonstration, mais cela devrait vous aider à comprendre le contour de l'attaque.