WordPressin wpdb->prepare() on yksi tärkeimmistä välineistä SQL-injektioiden ehkäisyssä. Sen avulla kehittäjä voi rakentaa turvallisia SQL-lauseita siten, että käyttäjän syötteet escapen ja sitoutetaan oikein. Silti on tärkeää ymmärtää, mitä wpdb->prepare() EI suojaa, koska väärinkäyttö voi johtaa vakaviin tietoturvaongelmiin.
wpdb->prepare() ei ole taikatyökalu. Se suojaa vain arvojen sisäänsyötöltä SQL-lauseeseen, ei muuta sovelluksen logiikkaa, HTTP-pyyntöjä tai sivuston yleistä turvallisuutta. Monet kehittäjät tekevät virheen luottaessaan siihen sokeasti.
Mitä wpdb->prepare() tekee
wpdb->prepare() muuttaa SQL-lauseen ja sen parametrien yhdistelmän turvalliseksi. Esimerkki:
global $wpdb;
$user_input = $_GET['id'];
$query = $wpdb->prepare( "SELECT * FROM wp_posts WHERE ID = %d", $user_input );
$results = $wpdb->get_results( $query );
Tässä %d kertoo wpdb->prepare-funktiolle, että kyseessä on kokonaisluku. Funktio varmistaa, että käyttäjän syöte on kunnossa, ja estää suoran SQL-injektion.
Hyödyt
-
Estää perus-SQL-injektiot
-
Escapaa merkit oikein SQL-lauseessa
-
Tekee koodista ennustettavan ja turvallisemman
Mitä wpdb->prepare() EI suojaa
1. Taulujen ja sarakkeiden nimiä
wpdb->prepare() ei voi escapen taulujen tai sarakkeiden nimiä. Esimerkiksi tämä on vaarallinen:
$table = $_GET['table']; // käyttäjä voi syöttää "wp_users; DROP TABLE wp_posts;"
$query = $wpdb->prepare( "SELECT * FROM $table WHERE ID = %d", $id );
$wpdb->get_results( $query );
$table ei ole suojattu, ja käyttäjä voi suorittaa haitallisia SQL-komentoja. Prepare suojaa vain parametrien osalta (%d, %s jne.), ei itse SQL:n rakennetta.
2. ORDER BY ja LIMIT -parametreja ilman tarkistusta
Myös ORDER BY- ja LIMIT-arvot voivat olla hyökkäyskohteita:
$order = $_GET['order']; // esim. "DESC; DROP TABLE wp_users"
$query = $wpdb->prepare( "SELECT * FROM wp_posts ORDER BY post_date $order" );
Prepare ei escapaa SQL-avainsanoja, joten käyttäjä voi lisätä haitallisen koodin.
3. Rinnakkaiset SQL-injektioyrittäjät (kaksoiskomennot)
Jos lauseessa on useita käyttäjän inputteja, mutta prepare on käytetty väärin, hyökkäys on mahdollinen. Esimerkiksi, jos yhdistetään valmis SQL + prepare väärin:
$unsafe_sql = "WHERE post_status = 'publish'";
$query = $wpdb->prepare( "SELECT * FROM wp_posts $unsafe_sql AND ID = %d", $id );
Tässä unsafe_sql voi sisältää haitallista koodia. Prepare ei suojaa valmiiksi liitetyltä SQL:ltä.
4. Muut hyökkäykset kuin SQL-injektio
wpdb->prepare() suojaa vain SQL-injektiolta. Se ei estä:
-
XSS-hyökkäyksiä (javascript injection)
-
CSRF-hyökkäyksiä (lomakepyynnöt)
-
Arbitrary file inclusion -ongelmia
-
Sovelluslogiikan väärinkäyttöä
Nämä vaativat omat turvamekanisminsa (esim. esc_html(), wp_nonce_*).
5. Serialisoitu data ja JSON
Jos syötät serialisoitua dataa tai JSON:ia SQL-lauseeseen, prepare ei tarkista, että rakenne pysyy eheänä. Väärin käsiteltynä tämä voi rikkoa sovelluksen logiikan.
6. Useiden parametrien väärä järjestys
Prepare ei estä virheellisiä formaattimerkkejä tai parametrien järjestyksen rikkomista. Esimerkiksi:
$query = $wpdb->prepare( "SELECT * FROM wp_posts WHERE ID = %d AND post_title = %s", $title, $id );
Tässä %d ja %s ovat väärin järjestyksessä. Prepare ei kaadu, mutta SQL toimii väärin ja voi paljastaa tietoja.
Parhaat käytännöt
-
Käytä preparea aina parametrien kanssa, ei taulujen tai sarakkeiden nimien osalta.
-
Tarkista kaikki käyttäjän syötteet etukäteen: whitelistaa ORDER BY, LIMIT ja taulujen nimet.
-
Käytä aina
esc_html(),esc_attr()jawp_nonce_*muiden hyökkäysten ehkäisyyn. -
Älä koskaan liitä käyttäjän syötettä suoraan SQL:ään ilman tarkistusta, edes preparea käytettäessä.
-
Testaa eri hyökkäysskenaarioita kehitysympäristössä.
Yhteenveto
wpdb->prepare() on tehokas työkalu SQL-injektioiden ehkäisyyn, mutta se EI suojaa SQL:n rakennetta, taulujen nimiä, ORDER BY- ja LIMIT-arvoja, muita hyökkäyksiä kuin SQL-injektioita, eikä väärin järjestettyjä parametreja. Luottamalla pelkkään prepareen voi saada harhan turvallisuudesta.
Oikea turvakäytäntö yhdistää prepare-funktion, käyttäjän syötteen validoinnin ja WordPressin muita turvallisuus-APIja. Silloin koodi pysyy turvallisena, skaalautuvana ja ennustettavana.
