Suis-je en sécurité contre l'injection SQL
-
06-07-2019 - |
Question
Je voudrais savoir si je suis protégé contre l'injection de code SQL lorsque j'utilise un tel système avec PostgresSQL:
CREATE or REPLACE FUNCTION sp_list_name( VARCHAR )
RETURNS SETOF v_player AS '
DECLARE
v_start_name ALIAS FOR $1;
r_player v_player%ROWTYPE;
v_temp VARCHAR;
BEGIN
v_temp := v_start_name || ''%'';
FOR r_player IN
SELECT first_name, last_name FROM v_player WHERE last_name like v_temp
LOOP
RETURN NEXT r_player;
END LOOP;
RETURN;
END;
' LANGUAGE 'plpgsql' VOLATILE;
Je souhaite utiliser cette fonction pour répertorier le nom du joueur commençant par une lettre.
select * from sp_list_name( 'A' );
me donne les joueurs dont le nom de famille commence par A.
J'ai essayé d'injecter SQL avec
select * from sp_list_name( 'A; delete from t_player;--' );
select * from sp_list_name( '''; delete from t_player;--' );
Suis-je en sécurité?
Dans quel cas pourrais-je être injecté?
Cordialement
La solution
En termes de procédure, vous semblez en sécurité, car la variable du SP ne sera pas transformée en code, mais vous pouvez toujours vous exposer si vous n'utilisez pas de requête paramétrée telle que " SELECT * FROM sp_list_name (?);
" dans votre code d'application . Quelque chose comme " SELECT * FROM sp_list_name ('$ start_name");
" peut être subverti par un utilisateur qui passe le nom de début " '); supprime de t_player où last_name NOT IN ('
"). Utilisez donc une requête paramétrée ou un contrôle de validité vos entrées dans votre programme.
NB: Pour les autres, notez qu'une variable d'une procédure stockée ne ne sera pas développée dans le code, même si elle contient un 'ou;, EXECUTE , pour lequel vous utiliseriez des fonctions quote_literal
, et non à la main replace
) en remplaçant ainsi; ou 'est totalement inutile (dans la procédure stockée, l'application qui l'utilise est bien sûr une histoire différente) et vous empêcherait de toujours trouver le " tl; dr
". ou " O'Grady
" équipes.
Leo Moore, Karl et LFSR Consulting : nom_v_temp
dans la procédure stockée sera PAS développé en code dans le SP (non EXECUTE ), la vérification devrait être effectuée dans l'application, et non pas le SP (ou l'OP pourrait simplement utiliser une requête paramétrée dans leur code d'application, à la place). Ce que les autres suggèrent est semblable à se soucier de
my $bar = "foo; unlink('/etc/password');";
my $baz = $bar;
en cours d'exécution du non-lien en l'absence d'une évaluation.
Autres conseils
Règle n ° 1 pour éviter les injections SQL: désinfectez toutes les entrées provenant de quelqu'un ou de quelque chose en qui vous ne pouvez avoir confiance / que vous ne pouvez pas contrôler.
Le problème lui-même ne réside pas dans le code de la base de données, mais dans l'application qui exécute ces instructions.
La Liste blanche * - la longue et la plus sûre protection contre l'injection SQL consiste à En bref, définissez les caractères que vous allez accepter et filtrez-les.
La méthode incorrecte consiste à Liste noire : répertorier en noir les caractères non acceptés est vous allez créer des problèmes, car vous ne pouvez pas suivre le rythme des attaquants. Il existe des solutions pour contourner les listes noires via les tables ASCII, les caractères d’échappement et autres.
En outre, voici un aide-mémoire à essayer sur votre site. Exécutez des tests et essayez d’échouer.
*
Dans l'application, pas la base de données (Thanks James)
Vous ne générez pas de code SQL pour vous-même, cela semble donc sans danger (pour moi).
Je ne sais pas d'où proviennent les données que vous appelez votre procédure stockée. Vous devez donc vous protéger des débordements de mémoire tampon, etc.
Réf. Liste blanche. C'est OK si certaines autres conditions sont suivies. Il est absolument impératif de décomposer toutes les entrées dans sa forme la plus simple. Ne vous contentez donc pas de rechercher des noms de requêtes SQL, des guillemets simples, etc. Ils peuvent être représentés ou encodés à l'aide d'autres jeux de caractères. C'est ce qui fait partie de la liste blanche, mais pas spécifiquement. Mots clés SQL eux-mêmes.
Je travaillais pour un client particulier qui permettait à un nom d'utilisateur / mot de passe d'accéder à une ressource protégée (ce qui pourrait vous permettre d'obtenir un passe d'accès dans des parties sécurisées d'un aéroport!). Vous pouvez contourner le champ de connexion en entrant 'puis en générant des requêtes SQL pour récupérer les comptes d'utilisateurs et les mots de passe.
Le problème était que le client avait déjà soufflé de construire le site avec un fournisseur qui semblait n'avoir jamais réalisé de développement Web auparavant. Le correctif était un autre & # 163; 60k qui était une validation de func () qui ne cherchait que pour l'union, sélectionnez, ayant et autres mots clés. Lorsqu'on leur a demandé ce qu'ils avaient fait pour la canicolisation / l'encodage (ce que j'avais à expliquer ensuite), c'était le temps du tumbleweed.
La maison de développement et le projet (coûteux) ont été mis en conserve.
Vous pouvez envisager de valider le contenu de
v_start_name. Recherchez des points-virgules, des caractères de commentaire, des égaux, etc. dans la chaîne. N'oubliez pas de rechercher les valeurs Chars et Hex. N'oubliez pas de permettre un nom avec trait d'union, par exemple 'Smith-Brown' est probablement acceptable. 'Smith - Brown' est potentiellement une injection.
Si vous n’êtes pas familier avec Hex dans SQL Injection, voici une introduction rapide
http: // www .arejae.com / blog / sql-injection-attack-using-t-sql-and-hexadecimal.html
http://www.securityfocus.com/infocus/1768
DECLARE v_start_name ALIAS FOR $1; r_player v_player%ROWTYPE; v_temp VARCHAR; BEGIN -- new pseudo code here if v_start_name has bad chars exit with error message -- end pseudo code here v_temp := v_start_name || ''%''; FOR r_player IN SELECT first_name, last_name FROM v_player WHERE last_name like v_temp LOOP RETURN NEXT r_player; END LOOP; RETURN; END;
Cordialement Karl
Faites un remplacement sur votre v_start_name pour vous débarrasser de " ;; " etc. c'est-à-dire
v_clean_name VARCHAR;
Select v_clean_name = Replace(v_start_name,';','');
Ceci remplacera le; avec des blancs déjouant une attaque par injection SQL
Pour plus de détails, voir Fonctions de chaîne dans PostgresSQL
Comme LFSR Consulting l’a également commenté. Il vaut mieux utiliser la liste blanche (c.-à-d. Ne traitez aucune entrée contenant des caractères non valides, tels que ';') plutôt que la liste noire (c-à-d. Essayez de nettoyer les données car l'utilisateur pourrait également lancer une attaque par injection SQL sur votre remplacement).
Pour plus d’informations, consultez Attaques d'injection SQL