Régulièrement on m’évoque que les bases NOSQL ne peuvent souffrir d’injection SQL. Sur le principe je dis oui, pas d’injection SQL dans les bases NOSQL, mais des injection NOSQL oui J.
Pour cela il convient de rappeler ce qu’est
- une injection
- une base NOSQL
et ensuite on pourra aborder le sujet de comment les empêcher.
Qu-est-ce qu’une injection ?
L’injection fait partie des failles les plus courante et les plus critiques. Elle est en pole position dans le Top10 OWASP.
Une injection c’est l’envoi de données malveillantes (via une entête, un champ de formulaire, …) à un interpréteur qui realise alors un comportement non attendu qui peut se finir par la prise de contrôle du serveur SQL dans le cas d’une injection SQL. Il existe des tonnes d’injections (commandes, XPath, XML, SQL, LDAP, Hibernate, …) car tout interpréteur est vulnérable…
Soit un morceau de code moisi de ce style :
Exemple (en Java adapté de CWE-89):
String username = req.getParameter (“username”); String itemName = req.getParameter (“item”); conn = pool.getConnection( ); String query = "select * from items where owner='" + userName +"' and itemname='" + itemName + "'"; stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(query); …..
Exemple (en C#) (CWE-89) :
string userName = ctx.getAuthenticatedUserName(); string query = "SELECT * FROM items WHERE owner = '" + userName + "' AND itemname = '" + ItemName.Text + "'"; sda = new SqlDataAdapter(query, conn); DataTable dt = new DataTable(); sda.Fill(dt); ...
Alors nous voyons que si dans la variable userName on retrouve un truc du genre : test’ OR ‘1’=’1’ -- on se trouve a avoir une requête SQL moisie qui sera :
SELECT * FROM items where owner =’test’ OR ‘1’=’1’
ou encore au final
SELECT * FROM items
Et donc au final on rapatriera tous les éléments….
La seule solution pour empêcher les injections consiste à valider l’ensemble des données que l’on s’apprête à manipuler avec l’interpréteur.
Il existe une « verrue » supplémentaire dans le cas de SQL supporté par la majorité des frameworks . Personnellement je trouve cela un peu trop « simple » et ne permettant pas de bien faire entrer le principe de la validation de données, donc j’appelle cela une verrue.
Cette « verrue » consiste en l’utilisation des requêtes paramétrées (ou requete préparées). Cela a pour effet lorsque cette « verrue » est bien utilisée de neutraliser l’injection.
Le code moisi précédent s’écrit donc alors :
Exemple en Java
//
// On va pas disgresser ici sur la validation des données , IL FAUT LA FAIRE QUAND MEME !!!! => Principe Numéro 1
//
String userName = req.getParameter (“username”);
String itemName = req.getParameter (“item”);
if (! maMethodeDeValidation (userName, “\\w”))
{
……
// Exception et stop de la fonction métier
……
}
else if (!maMethodeDeValidation (itemName, “\\w”))
{
……
// Exception et stop de la fonction métier
……
}
else
{
conn = pool.getConnection( );
String query = "select * from items where owner= ? AND itemName = ?”;
PreparedStatement stmt = conn. prepareStatement
(query);
stmt.setString (userName, 1);
stmt.setString (itemName, 2);
ResultSet rs = stmt.executeQuery(sql);
...
Exemple (en C#)
...
string userName = ctx.getAuthenticatedUserName();
try {
//
//pas joli mais faudra enrober
//
SqlConnection connexion = new SQLConnection (connectString)
String req = “SELECT * FROM items WHERE owner = @userName AND itemName=@item’’
SqlCommand sqlCmd = new SqlCommand (req, connexion);
sqlCmd.Parameters.Add (new SqlParameter (“@userName”,userName));
sqlCmd.Parameters.Add (new SqlParameter (“@itemName”,item));
sqlCmd.Connection.Open();
SqlDataReader ret = sqlCmd.ExecuteReader();
…..
et dans ce cas, toute tentative d’envoi de la chaine “ test’ OR ‘1’=’1’ -- “ génèrera une exception.
Qu’est-ce qu’une base NOSQL ?
Ce type de bases de données est très à la mode pour la gestion des sites nécessitant de la performance (entre autre) et a été adopté par quelques uns des plus gros sites de la planète (Amazon, google, Facebook, twitter, …)
NOSQL est un concept ou il existe malgré tout un interpréteur. La grosse différence entre une base NOSQL et une base SQL, est que dans les bases NOSQL le stockage n’est plus effectué comme dans les bases relationnelles avec un modèle bien défini, mais sous la forme de tableaux associatifs (type clef/valeurs) ou orienté colonne (le nombre de colonnes peut varier) ou orienté document (les données sont stockées sous la forme de documents XML, JSON, …) ou encore orienté graphe (basé sur la théorie des graphes).
On va retrouver les bases suivantes :
Au final on va donc se retrouver avec un stockage de données sous la forme choisie par la base (exemple en JSON/XML/….) avec en amont un moteur permettant de transformer ce que l’on lui envoie. Ce qui veut dire que l’on dispose alors d’un interpréteur ou tout autre élément permettant d’effectuer des requêtes…
Il est donc possible d’avoir des injections NOSQL. Il existe un peu de littérature sur ce sujet (surtout orienté PHP….)
Donc il est nécessaire de mettre en place une bonne validation pour les combattre. (Suite a l’épisode 2)
Aucun commentaire:
Enregistrer un commentaire