web-dev-qa-db-fra.com

Existe-t-il une injection SQL pour cet exemple de connexion PHP?

Je veux écrire un formulaire de connexion et j'ai obtenu un exemple sur le Web. Je veux savoir s'il y a une injection SQL pour ce code? Si tel est le cas, à quoi pourrait ressembler l'entrée du formulaire Web de l'exploit?

Voici ma forme:

<form method="post" action="">
    <dt class="title"><label for="username">name:</label></dt>
    <dt><input type="text" name="username" id="username"  size="50"></dt>
    <dt class="title"><label for="password">pass:</label></dt>
    <dt><input type="password" name="password" id="password" size="50"></dt>
    <input type="hidden" name="post" value="1" />
    <input type="submit" name="submit" value="submit" class="button">
</form>

et voici mon chèque:

if (($post[username]) AND ($post[password])) 
    {
        $query = 'SELECT * FROM `config` WHERE `config_admin_username`="'.$post[username].'" AND `config_admin_password`=MD5("'.$post[password].'") LIMIT 1';
        $sql_user_check = $db->fetch($query);
        if (!$sql_user_check) { 
            $error .= "Wrong Entry.<br />";
        } else {
            $_SESSION[admin] = 1;
            header("Location:index.php");
            exit;
        }
    }

J'utilise phpmyadmin 3.2.0.1 sur wamp 2.0i

9
sorroshsaket

Vous êtes arrivé au bon endroit. Bienvenue à sécurité informatique !

y a-t-il une injection SQL pour ce code?

Oui

s'il y a quelle est cette entrée?

username: [any username from your website]" /*
password: sux0r")*/ OR ("1"="1

Il exécutera cette requête:

SELECT * FROM `config` 
WHERE `config_admin_username`="[any username from your website]" /* 
      AND `config_admin_password`=MD5("sux0r")*/ OR ("1"="1") LIMIT 1'

Si nous supprimons les parties commentées que le moteur SQL n'analysera pas, cela se traduira par:

SELECT * FROM `config` 
WHERE `config_admin_username`="[any username from your website]" OR ("1"="1") LIMIT 1'

La requête SQL sera analysée jusqu'à la partie commentée (j'ai utilisé le /* et */ paire début-commentaire/fin-commentaire dans mon exemple et en supposant que vous utilisez MySQL , mais cela peut être différent selon le SGBDR utilisé), désactivant efficacement votre vérification de mot de passe. Même si les commentaires en SQL ne sont pas pris en charge ou désactivés, les options pour exploiter votre connexion sont vraiment illimitées. Je n'entrerai même pas dans votre choix de MD5 comme algorithme de hachage de mot de passe, car vous avez beaucoup d'autres choses à considérer en premier. Ce n'est clairement pas l'algorithme de hachage recommandé pour le hachage de mot de passe.

Vous avez fait du bien d'être venu sur ce site et que vous vous posiez des questions concernant la sécurité de votre code. Félicitations, vous êtes déjà un meilleur programmeur PHP que la plupart qui n’ont jamais été aussi loin! Maintenant, c'est à vous de savoir ce que vous apprendrez des questions et réponses déjà existantes ici. Quelques balises pour considérer sont php , authentification , application Web , hachage , ...

19
TildalWave

TildalWave a une excellente réponse, mais il y a une grande médiation à l'injection SQL qui manquait dans la réponse. Déclarations préparées. Comme l'a dit Tildal, l'intégralité de l'instruction avec entrée utilisateur est analysée sans distinction analysable entre les variables et les parties constantes de l'instruction. La solution consiste à envoyer la partie constante de l'instruction avec des espaces réservés variables puis les variables. PDO est ce que j'utilise pour mon interaction SQL. Voici la fonction que j'utilise ...

function _SQL_QUERY($_base_request, $_request_arguments)
{
                $_DB_USERNAME = "bob"; $_DB_PASSWORD="secret"; $_DB_LOCATION="localhost"; $_DB_NAME="MYWICKEDDATABASE"; $_DB_SERVER_TYPE="mysql";
                if(!isset($_DATABASE_CONNECTION))
                {
                        $_DATABASE_CONNECTION = new PDO("$_DB_SERVER_TYPE:dbname=$_DB_NAME;Host=$_DB_LOCATION;charset=utf8", $_DB_USERNAME, $_DB_PASSWORD);
                        $_DATABASE_CONNECTION->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
                }
                $__STMT = $_DATABASE_CONNECTION->prepare($_base_request);
                if($__STMT->execute($_request_arguments))
                {
                        return $__STMT;
                }
                else
                {
/*
        //Helpful ONLY when debugging!!!
                        echo 'ERROR</ br>';
                        echo $_base_request;
                        echo '</ br>';
                        print_r($__STMT->errorInfo());
                        print_r($_request_arguments);
                        die('</ br>');
*/
                        return false;
                }
}

pour l'utiliser, il vous suffira d'exécuter ce

_SQL_QUERY("Select * FROM names WHERE name=:var1 AND age=:var2", array('var1'=>'jim','var2'=>50));

Il y a beaucoup d'améliorations à apporter (principalement sur le plan fonctionnel), mais c'est une vaste amélioration des fonctions SQL traditionnelles. Il est important de savoir que si une ligne a échoué à une injection dans ses données, une sauvegarde et une restauration peuvent en fait réussir en fonction de la méthode utilisée. Félicitations pour avoir fait un audit de sécurité de votre code, si seulement plus de gens apprenaient la programmation avec cette motivation pour la sécurité.

9
David