Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Qual é a melhor maneira de tornar esta inserção mais segura e protegida contra injeção e manipulação


Como os comentários acima sugerem, vale a pena usar parâmetros de consulta para se proteger da injeção de SQL.

Você pediu um exemplo de como qualquer coisa maliciosa pode ser feita. Na verdade, nem precisa ser malicioso. Qualquer string inocente que contenha legitimamente um apóstrofo pode quebrar sua consulta SQL. A injeção de SQL maliciosa aproveita essa fraqueza.

A fraqueza é corrigida mantendo os valores dinâmicos separados de sua consulta SQL até que a consulta seja analisada. Usamos espaços reservados de parâmetro de consulta na string SQL e, em seguida, usamos prepare() para analisá-lo e depois combinar os valores quando você execute() a consulta preparada. Assim fica seguro.

Aqui está como eu escreveria sua função. Estou assumindo o uso de PDO que suporta parâmetros de consulta nomeados. Eu recomendo usar PDO em vez de Mysqli.
function updateProfile( $vars, $userId ) {
    $db = new Database();
    $safeArray = [
        "gradYear",
        "emailAddress",
        "token",
        "iosToken",
        "country",
        "birthYear",
        "userDescription",
    ];
    // Filter $vars to include only keys that exist in $safeArray.
    $data = array_intersect_keys($vars, array_flip($safeArray));

    // This might result in an empty array if none of the $vars keys were valid.
    if (count($data) == 0) {
        trigger_error("Error: no valid columns named in: ".print_r($vars, true));
        $response = ["response" => 400, "title" => "no valid fields found"];
        return $response;
    }
    
    // Build list of update assignments for SET clause using query parameters.
    // Remember to use back-ticks around column names, in case one conflicts with an SQL reserved keyword.
    $updateAssignments = array_map(function($column) { return "`$column` = :$column"; }, array_keys($data));
    $updateString = implode(",", $updateAssignments);

    // Add parameter for WHERE clause to $data. 
    // This must be added after $data is used to build the update assignments.
    $data["userIdWhere"] = $userId;
    
    $sqlStatement = "update users set $updateString where userId = :userIdWhere";

    $stmt = $db->prepare($sqlStatement);
    if ($stmt === false) {
        $err = $db->errorInfo();
        trigger_error("Error: {$err[2]} preparing SQL query: $sqlStatement");
        $response = ["response" => 500, "title" => "database error, please report it to the site administrator"];
        return $response;
    }
    
    $ok = $stmt->execute($data);
    if ($ok === false) {
        $err = $stmt->errorInfo();
        trigger_error("Error: {$err[2]} executing SQL query: $sqlStatement");
        $response = ["response" => 500, "title" => "database error, please report it to the site administrator"];
        return $response;
    }

    $response = ["response" => 200, "title" => "update successful"];
    return $response;
}