Questa semplice funzione aggiunge qualcosa alle istruzioni preparate?

0

Ho cercato come evitare completamente l'iniezione SQL, ma ci sono così tante diverse forme di iniezione che impediscono completamente che mi sembrino impossibili. Sto usando le dichiarazioni preparate e metto su la seguente semplice funzione per prevenire le iniezioni SQL. Questo è sicuro contro (la maggior parte) delle iniezioni SQL, se eseguo questa funzione su ogni variabile pubblicata? Ho anche letto dei caratteri multi-byte, come posso proteggere le mie query con quello?

function securevar($var)
{
    $var = str_replace("'", "'", $var); //secure '
    $var = str_replace('"', """, $var); //secure "
    return $var;
}
    
posta P.Yntema 26.10.2014 - 21:17
fonte

3 risposte

7

No, non lo fa, usa istruzioni preparate così come lo è una singola query funzioni e corretta convalida dell'input. Quest'ultimo è l'impostazione predefinita per la maggior parte delle funzioni in PHP (ad esempio mysqli::query Vs. mysqli::multi_query ).

Istruzioni preparate

Le istruzioni preparate inoltrano i dati di una variabile e il suo tipo separatamente al DBMS che a sua volta sfuggirà a tutti i caratteri offensivi o analizzerà i dati indipendentemente dalla query effettiva (a seconda del DBMS). Non c'è niente da sapere su quali personaggi devono essere sfuggiti e quali no. Questo è il modo più sicuro per raggiungere questo obiettivo.

<?php

mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new \mysqli(null, null, null, "database");
$mysqli->prepare("SELECT * FROM 'users' WHERE 'id' = ?");
$mysqli->bind_param("d", $_GET["id"]);
$mysqli->execute();
// ...

Tutta questa complessità può essere astratta, dai un'occhiata ad es. Drupal source code.

Funzioni di query singole

Le singole funzioni di ricerca assicurano che una tua query genererà sempre una sola query che verrà passata al DBMS. Uccidere efficacemente ogni possibilità che qualcuno interrompa la tua query e ne esegue un'altra; uno scenario tipico con SQL injection, esempio:

<?php

$_GET["id"] = "1;SET foreign_key_checks=0;DROP TABLE users";

$mysqli->multi_query("SELECT * FROM 'users' WHERE 'id' = {$_GET["id"]}");

Validation

Questo è forse il consiglio più importante ed è sempre importante, indipendentemente da ciò che cerchi di ottenere. Utilizza le funzioni filter_* integrate in PHP e controlla altri progetti di grandi dimensioni per la convalida di materiale non coperto da queste funzioni.

Esempio combinato

Mettiamo tutto insieme.

<?php

// max_range default is PHP_INT_MAX.
$userId = filter_input(INPUT_GET, "id", FILTER_VALIDATE_INT, array(
  "options" => array("min_range" => 1),
));

// Contains either a valid integer now or either FALSE or NULL.
if ($userId === null || $userId === false) {
//if (!$userId) {
  throw new \InvalidArgumentException();
}

mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new \mysqli(null, null, null, "database");
$stmt = $mysqli->prepare("SELECT 'name' FROM 'users' WHERE 'id' = ?");
%stmt->bind_param("d", $userId);
$stmt->execute();
$stmt->fetch($userName);
$stmt->close();
$mysqli->close();

exit("Hello {$userName} with {$userId}.");
    
risposta data 26.10.2014 - 21:57
fonte
14

No. SQL Injection dovrebbe essere prevenuto parametrizzando le tue query.

OWASP ha alcune grandi risorse per aiutarti con questo.

Qui è uno di questi fogli per mostrarlo in diverse lingue. Il cheat PHP ha anche altre informazioni riguardo a sql injection.

Per indirizzare direttamente la tua funzione di filtro codificato, controlla questa fonte dimostrazione dello sfruttamento di filtri hard coded, tra virgolette e citazioni singole.

    
risposta data 26.10.2014 - 21:28
fonte
1

Come @Douglas e @fleshgrinder hanno detto prima, no.

Considera la seguente richiesta:

SELECT title, news FROM news_table WHERE id = $id

Applicato per $id = 5 va bene, ora se $id = 5 OR 1=1 visualizzerà tutte le notizie ... Non è un grosso problema?

Ora se $id = 5 UNION SELECT login as title, password as news from secret_credentials_table where is_admin = 1 dovrebbe essere anche una richiesta SQL valida, senza virgolette ...

  • Utilizza le Richieste preparate
  • Anche gli argomenti tipizzati aiutano (ma non è nemmeno il proiettile d'argento!)

Per l'argomento digitato, se assicuri che il tuo $id sia un numero intero, allora una tale iniezione è impossibile. Ma ovviamente, alcune richieste si aspettano la stringa come input, quindi perdi tutti i benefici di ciò.

    
risposta data 27.10.2014 - 09:19
fonte

Leggi altre domande sui tag