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

Était-ce utile?

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

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top