SQL - Injection


Što je SQL Injection?

SQL ubrizgavanje (Injection) je napad u kojem napadač može ubrizgati ili izvršiti zlonamjerni SQL kod putem ulaznih podataka iz preglednika na poslužitelj aplikacija, kao što je unos web obrasca. Može se koristiti za otkrivanje osjetljivih podataka poput korisničkih brojeva za kontakt, adresa e-pošte, podataka o kreditnoj kartici i tako dalje. Napadač ga čak može koristiti da zaobiđe postupak provjere autentičnosti i dobije pristup cijeloj bazi podataka. Pogledajmo kako to zapravo radi.



Kako funkcioniše SQL Injection

Razmotrite sljedeću SQL izjavu koja je jednostavan primjer provjere autentičnosti korisnika korisničkim imenom i lozinkom u web aplikaciji.

SELECT * FROM users WHERE username='username_val' AND password='password_val';

Ovdje username_val i password_val predstavljaju korisničko ime i lozinku koje je korisnik unio. Ako korisnik unese vrijednosti kao što su "milos" kao korisničko ime i "123" kao lozinku, tada će rezultiat izraz biti:

SELECT * FROM users WHERE username='milos' AND password='123';

Ali pretpostavimo, ako je korisnik napadač i umjesto da u polja unese valjano korisničko ime i lozinku, unijeo je vrijednosti otprilike: ' OR 'x'='x. U ovom će se slučaju gornji SQL upit konstruirati kao:

SELECT * FROM users WHERE username='' OR 'x'='x' AND password='' OR 'x'='x';

Ova je izjava valjana SQL naredba i budući da je WHERE 'x' = 'x'uvijek tačno, upit će vratiti sve redove iz korisničke tabele. Možete vidjeti kako lako napadač može dobiti pristup svim osjetljivim informacijama baze podataka uz samo mali prljavi trik. Ako je tabela korisnika prilično velika i sadrži milione redove, ovaj pojedinačni izraz takođe može dovesti do napada uskraćivanja usluge (DoS napad) preopterećenjem sistemskih resursa i učiniti vašu aplikaciju nedostupnom legitimnim korisnicima.



Sprječavanje SQL Injection

Uvijek provjerite korisnički unos i ne pretpostavljajte. Nikada nemojte graditi SQL izraze direktno iz korisničkog unosa. Ako koristite PHP i MySQL, možete koristiti funkciju mysqli_real_escape_string() za stvaranje pravnog SQL niza koji možete koristiti u SQL izrazu. Evo vrlo osnovnog primjera provjere autentičnosti korisnika pomoću PHP-a i MySQL-a koji pokazuje kako spriječiti ubrizgavanje (Injection) SQL-a uz uzimanje podataka od korisnika.

<?php
// Startovanje sesije
session_start();
 
/* Pokušajte povezati MySQL server. Pod pretpostavkom da koristite MySQL
server sa zadanim postavkama (korisnik 'root' bez lozinke)*/
$link = mysqli_connect("localhost", "root", "", "demo");
 
// Provjera konekcije
if($link === false){
    die("ERROR: Greška sa konekcijom baze podataka.");
}
 
// Izbjegavajte korisničke ulaza radi sigurnosti
$username_val = mysqli_real_escape_string($link, $_POST['username']);
$password_val = mysqli_real_escape_string($link, $_POST['password']);
 
if(isset($username_val, $password_val)){
    // Pokušaj izvršenja upita za odabir
    $sql = "SELECT * FROM users WHERE username='" . $username_val . "' AND password='" . $password_val . "'";
    if($result = mysqli_query($link, $sql)){
        if(mysqli_num_rows($result) == 1){
            // Korisnik je autentificiran radi li vaše stvari ovdje
            $row = mysqli_fetch_array($result);
            /*Zadržavanje vrijednosti u varijabli sesije da bi to 
                moglo biti pristupljeno kasnije u okviru iste reference 
            sesije */
            $_SESSION['user_id'] = $row['user_id'];
            $_SESSION['first_name'] = $row['first_name'];
            header('Location: welcome.php');
        } else{
            echo "ERROR: Pogrešan username ili password.";
        }
    } else{
        echo "ERROR: Nešto nije uredu. Molimo Vas pokušajte kasnije.";
    }
}
 
// Zatvori konekciju
mysqli_close($link);
?>