WordPressin wpdb-prepare: mitä se ei suojaaWordPressin 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() ja wp_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.