Revisjon av WordPress-plugins
NB

Revisjon av WordPress-plugins

Sist verifisert: 30. juni 2026
9 min lesetid
Guide
500+ WP-prosjekter
Sikkerhetsrevisor

#Introduksjon: AI-løftet vs. WordPress-realiteten

Å bruke store språkmodeller (LLMer) som GPT-4, Claude 3.5 Sonnet eller Gemini Pro til å skrive WordPress-plugin-kode har blitt en vanlig praksis for både utviklere og nettstedseiere. Løftet er utrolig tiltalende: beskriv den nødvendige funksjonaliteten på vanlig norsk, og AI genererer en klar-til-bruk PHP-fil på sekunder.

Problemet er imidlertid at språkmodeller utmerker seg på syntaks og struktur, men mangler operasjonell kontekst og en reell forståelse av sikkerhetsprinsipper i WordPress-økosystemet. Trent på enorme datasett med offentlig kode, arver de millioner av utdaterte, usikre og dårlig skrevne plugins publisert i løpet av de siste to tiårene. Som et resultat produserer AI ofte kode som er syntaktisk feilfri og funksjonell, men full av kritiske sikkerhetssårbarheter under panseret.

Som WordPress-utviklere må vi ta i bruk en streng “Zero Trust”-holdning overfor all kode skrevet av en AI. Denne guiden bryter ned de fem vanligste sikkerhetsfeilene vi observerer under revisjoner av AI-generert plugin-kode, og illustrerer dem med sårbare PHP-snutter ved siden av sikre, produksjonsklare refaktoreringer som samsvarer med WordPress Coding Standards (WPCS).


#1. Feilaktig bruk av is_admin() for adgangskontroll

Kanskje den vanligste logiske feilen AI gjør når den prøver å sikre et endepunkt, er å stole på funksjonen is_admin() for å begrense adgangen til administratorer.

#Hvorfor det mislykkes

Til tross for navnet, verifiserer ikke is_admin() om den nåværende innloggede brukeren er en administrator. Den sjekker kun om den gjeldende forespørselen gjelder en administrasjonsside (som enhver URL som starter med /wp-admin/).

Hver AJAX-forespørsel sendt til /wp-admin/admin-ajax.php — enten den er initiert av en administrator, en innlogget abonnent med minimale rettigheter, eller en uautentisert anonym besøkende — vil føre til at is_admin() returnerer true.

#Sårbar AI-generert kode:

// En AI-generert hook for å lagre innstillinger
add_action( 'admin_init', 'ai_save_plugin_settings' );
function ai_save_plugin_settings() {
    // AI antar feilaktig at dette begrenser adgangen til administratorer
    if ( is_admin() ) {
        if ( isset( $_POST['my_plugin_option'] ) ) {
            update_option( 'my_plugin_option', $_POST['my_plugin_option'] );
        }
    }
}

#Sikker kode:

For å verifisere de faktiske rettighetene til den innloggede brukeren, må du bruke funksjonen current_user_can(), og sende inn en spesifikk brukerrettighet i stedet for et rollenavn, for eksempel manage_options.

add_action( 'admin_init', 'secure_save_plugin_settings' );
function secure_save_plugin_settings() {
    // 1. Verifiser den nåværende brukerens faktiske rettigheter
    if ( ! current_user_can( 'manage_options' ) ) {
        wp_die( esc_html__( 'Du har ikke rettighet til å utføre denne handlingen.', 'secure-plugin' ) );
    }

    if ( isset( $_POST['my_plugin_option'] ) ) {
        // Bruk sanitysering på inndata (se avsnitt 4)
        $sanitized_value = sanitize_text_field( wp_unslash( $_POST['my_plugin_option'] ) );
        update_option( 'my_plugin_option', $sanitized_value );
    }
}

#2. Komplett utelatelse av nonce-verifisering (CSRF)

Cross-Site Request Forgery (CSRF)-angrep lurer en autentisert brukers nettleser (f.eks. en administrator) til å utføre uautoriserte handlinger på et nettsted de er logget inn på. WordPress bruker kryptografiske token kalt nonces for å beskytte mot CSRF.

AI-generatorer utelater ofte opprettelse og verifisering av nonces i admin-skjemaer, AJAX-handlere og tilpassede REST API-endepunkter. Dette skjer fordi implementering av nonces krever koordinering av frontend-rendringslaget (HTML-skjemaet som inneholder nonce-feltet) med backend-prosesseringskontrolleren, noe som er vanskelig for LLMer å samkjøre på tvers av frakoblede kodegenereringer.

#Sårbar AI-generert AJAX-handler:

// AI-generert AJAX-endepunktregistrering
add_action( 'wp_ajax_ai_delete_post', 'ai_delete_post_handler' );
function ai_delete_post_handler() {
    // AI sjekker rettigheter, men ignorerer CSRF fullstendig (ingen nonce-sjekk)
    if ( ! current_user_can( 'delete_posts' ) ) {
        wp_send_json_error( 'Uautorisert.' );
    }

    $post_id = intval( $_POST['post_id'] );
    wp_delete_post( $post_id );
    wp_send_json_success( 'Innlegg slettet.' );
}

#Sikker kode:

Skjemaet må generere et nonce-felt ved hjelp av wp_nonce_field(), og den mottakende PHP-kontrolleren må verifisere tokenet ved hjelp av check_ajax_referer() eller wp_verify_nonce().

// I skjemaets rendringsfil eller javascript-payload:
// wp_nonce_field( 'delete_post_action', 'my_nonce_field' );

// Registrering av sikker AJAX-handler
add_action( 'wp_ajax_secure_delete_post', 'secure_delete_post_handler' );
function secure_delete_post_handler() {
    // 1. Verifiser CSRF-token tidlig
    check_ajax_referer( 'delete_post_action', 'my_nonce_field' );

    // 2. Verifiser brukerrettigheter
    if ( ! current_user_can( 'delete_posts' ) ) {
        wp_send_json_error( 'Uautorisert.' );
    }

    // 3. Valider og typiser inndatavariabler
    if ( ! isset( $_POST['post_id'] ) ) {
         wp_send_json_error( 'Mangler innleggs-ID.' );
    }

    $post_id = absint( $_POST['post_id'] );
    
    if ( wp_delete_post( $post_id ) ) {
        wp_send_json_success( 'Innlegget ble slettet.' );
    } else {
        wp_send_json_error( 'Feil under sletting av innlegget.' );
    }
}

#3. SQL-injeksjonssårbarheter i $wpdb-spørringer

Når en plugin samhandler direkte med databasen i stedet for å bruke den opprinnelige WP_Query-wrapperen, bruker den det globale objektet $wpdb. Dessverre konstruerer LLMer ofte rå SQL-strenger ved direkte sammenslåing av brukerleverte variabler ($_POST, $_GET) i stedet for å parametrisere spørringen.

#Hvorfor det er farlig

Å slå sammen rå variabler direkte inn i databasespørringer lar en angriper manipulere spørrestrukturen. Dette kan føre til uautorisert datagjenvinning (som hashede brukerpassord), sletting av databasen, eller eskalering av administratorrettigheter.

#Sårbar AI-generert spørring:

// Brukersøkfunksjon generert av AI
function ai_find_users_by_city( $city_name ) {
    global $wpdb;
    // Kritisk feil: direkte sammenslåing av spørrevariabelen
    $query = "SELECT * FROM {$wpdb->prefix}custom_users WHERE city = '" . $city_name . "'";
    return $wpdb->get_results( $query );
}

#Sikker kode:

Ingen rå variabler skal noen gang skrives direkte inn i SQL-strenger. Bruk i stedet metoden $wpdb->prepare(), som fungerer som en parametrisert spørremotor, typiserer og escaper verdier ved hjelp av formatspesifikasjoner (%s for strenger, %d for heltall, %f for desimaltall).

function secure_find_users_by_city( $city_name ) {
    global $wpdb;

    // 1. Bruk prepare() med formatspesifikasjoner
    $query = $wpdb->prepare(
        "SELECT * FROM {$wpdb->prefix}custom_users WHERE city = %s",
        $city_name
    );

    return $wpdb->get_results( $query );
}

Merk: Hvis variabelen $city_name kommer direkte fra brukerinput, må den fortsatt sanityseres med sanitize_text_field() før databasebehandling.


#4. Manglende sanitysering på inndata og escaping på utdata (XSS)

Cross-Site Scripting (XSS) er en av de vanligste sårbarhetene i WordPress-plugins. Det lar ondsinnet JavaScript-kode lagres i databasen eller speiles dynamisk, og kjøres i nettleseren til intetanende besøkende.

AI-modeller forveksler ofte sanitysering (rensing av data på vei inn) med escaping (sikring av data på vei ut). Selv om AI sanityserer inndata, viser den ofte variabler i maler uten å escape dem først, noe som etterlater nettstedet åpent for lagret XSS.

#Sårbar AI-generert rendring:

// Feedback-løkke skrevet av AI
function ai_display_user_feedback() {
    $feedbacks = get_option( 'ai_user_feedback_list', [] );
    
    echo '<div class="feedback-list">';
    foreach ( $feedbacks as $feedback ) {
        // Kritisk feil: rå utdata uten escaping
        echo '<p class="feedback-item">' . $feedback['user_comment'] . '</p>';
    }
    echo '</div>';
}

#Sikker kode:

Følg den grunnleggende WordPress-regelen: Sanitize Early, Escape Late (sanityser inndatavariabler umiddelbart; escape utdata umiddelbart før de sendes til nettleseren).

Velg riktig escaping-funksjon for konteksten:

  • esc_html() — for standard tekstnoder i HTML-elementer.
  • esc_attr() — for utdata i HTML-attributtverdier.
  • esc_url() — for utdata av lenker.
  • wp_kses() — når du må tillate spesifikke, sikre HTML-tagger (som strong, anchors).
function secure_display_user_feedback() {
    $feedbacks = get_option( 'secure_user_feedback_list', [] );
    
    echo '<div class="feedback-list">';
    foreach ( $feedbacks as $feedback ) {
        $comment = isset( $feedback['user_comment'] ) ? $feedback['user_comment'] : '';
        
        // 1. Escape utdata kontekstuelt umiddelbart før rendring
        echo '<p class="feedback-item">';
        echo esc_html( $comment );
        echo '</p>';
    }
    echo '</div>';
}

#5. Farlig filopplasting (Arbitrary File Upload)

Å tillate brukere å laste opp filer (som vedlegg i kontaktskjemaer eller opplasting av avatarer) er en av operasjonene med høyest risiko på et nettsted. En feil her lar angripere laste opp en .php-fil, noe som resulterer i ekstern kjøring av kode (RCE) og fullstendig serverkompromittering.

AI-genererte filbehandlere stoler ofte på opprinnelige PHP-kommandoer som move_uploaded_file() kombinert med svake filendelsessjekker (som enkel strengmatching), som er trivielle for angripere å omgå (f.eks. opplasting av filer med navnet malicious.php.jpg eller bruk av alternative etternavn som .phtml).

#Sårbar AI-generert filopplasting:

// Opplastingsbehandler skrevet av AI
function ai_handle_avatar_upload() {
    if ( isset( $_FILES['avatar'] ) ) {
        $file_name = $_FILES['avatar']['name'];
        $ext = pathinfo( $file_name, PATHINFO_EXTENSION );
        
        // AI antar at denne filendelsessjekken er sikker
        if ( in_array( $ext, ['jpg', 'jpeg', 'png'] ) ) {
            $target = wp_upload_dir()['path'] . '/' . $file_name;
            move_uploaded_file( $_FILES['avatar']['tmp_name'], $target );
        }
    }
}

#Sikker kode:

Bruk aldri opprinnelig PHP move_uploaded_file() i WordPress. Bruk i stedet kjernefunksjonen wp_handle_upload(). Den utfører en robust MIME-type-sjekk (verifiserer filens faktiske signatur, ikke bare navnet), validerer opplastingsstatusen og integreres med WordPress-rettighetssystemet.

function secure_handle_avatar_upload() {
    // 1. Valider CSRF-tokenet
    if ( ! isset( $_POST['avatar_upload_nonce'] ) || ! wp_verify_nonce( $_POST['avatar_upload_nonce'], 'upload_avatar_action' ) ) {
        wp_die( esc_html__( 'Ugyldig sikkerhetstoken.', 'secure-plugin' ) );
    }

    // 2. Verifiser capability-sjekker
    if ( ! current_user_can( 'upload_files' ) ) {
        wp_die( esc_html__( 'Du har ikke rettighet til å laste opp filer.', 'secure-plugin' ) );
    }

    if ( isset( $_FILES['avatar'] ) ) {
        if ( ! function_exists( 'wp_handle_upload' ) ) {
            require_once ABSPATH . 'wp-admin/includes/file.php';
        }

        // 3. Tving begrensning av tillatte MIME-typer
        $allowed_mimes = [
            'jpg|jpeg' => 'image/jpeg',
            'png'      => 'image/png'
        ];

        $upload_overrides = [
            'test_form' => false,
            'mimes'     => $allowed_mimes
        ];

        // 4. Deleger opplastingsbehandling til kjernefunksjonen
        $movefile = wp_handle_upload( $_FILES['avatar'], $upload_overrides );

        if ( $movefile && ! isset( $movefile['error'] ) ) {
            $avatar_url = $movefile['url'];
            update_user_meta( get_current_user_id(), 'user_avatar', $avatar_url );
        } else {
            // Logg feilen sikkert
            error_log( 'Filopplasting feilet: ' . $movefile['error'] );
        }
    }
}

#Revisjonsmetodikk: Implementering av Zero Trust for AI-kode

For å distribuere AI-generert kode på en sikker måte, må ingeniørteamet ditt etablere en systematisk gjennomgangsprosess. Implementer disse tre trinnene før du skyver genererte ressurser til produksjon:

#Trinn 1: Automatiser statisk analyse (PHPCS)

Konfigurer WordPress Coding Standards (WPCS) for PHP_CodeSniffer-verktøyet. Det skanner filer og flagger manglende sanitysering, utelatte nonces og uescapede variabler automatisk.

# Skann en generert plugin-fil med WordPress-standarder
vendor/bin/phpcs --standard=WordPress-Extra path/to/generated-plugin.php

#Trinn 2: Gjennomfør en manuell kodegjennomgang

Gjennomgå hver handler som utfører HTTP-spørringer, databasetransaksjoner, AJAX-anrop eller REST API-tilkoblinger mot følgende flytskjema:

graph TD
    A["Motta AI-skrevet plugin-kode"] --> B{"Godtar den brukerinput?"}
    B -- Ja --> C["Sjekk for Nonce og Capability-sjekker"]
    B -- Nei --> D{"Modifiserer den databasen?"}
    
    C --> C1["Implementer check_ajax_referer() / CSRF-validering"]
    C --> C2["Implementer current_user_can() rettighetssjekk"]
    C1 --> D
    C2 --> D
    
    D -- Yes --> E["Sjekk for $wpdb->prepare() bruk"]
    D -- No --> F{"Sender den utdata til nettleseren?"}
    
    E --> E1["Implementer parametriserte SQL-variabler"]
    E1 --> F
    
    F -- Yes --> G["Verifiser esc_html(), esc_attr(), eller esc_url()"]
    F -- No --> H["Fortsett til integrasjonstesting"]
    
    G --> G1["Implementer kontekstuell utdata-escaping"]
    G1 --> H

#Trinn 3: Kjør tester med lave rettigheter

Verifiser kodens adgangsgrenser. Logg inn som en bruker med rollen “Abonnent” og utløs pluginens REST- eller AJAX-handlinger direkte via curl eller Postman. Hvis serveren utfører modifikasjoner eller avslører databasedata, mangler rettighetslagene.


#Sammendrag og anbefalinger

Kunstig intelligens er en kraftig akselerator for å skrive kode, men den kan ikke overta ingeniøransvar. Behandle all AI-skrevet kode som om den var skrevet av en uerfaren praktikant.

Sørg for at du implementerer robuste capability-sjekker (current_user_can()), CSRF-verifisering (wp_verify_nonce()), databaseparametrisering ($wpdb->prepare()), sanitysering av inndata og sen escaping av utdata. Ved å kombinere disse kjernepraksisene med statiske analyseverktøy, kan du skrive WordPress-kode raskere samtidig som du opprettholder en helt sikker applikasjon.

Neste steg

Gjor artikkelen om til faktisk implementering

Denne blokken styrker intern lenking og sender leseren videre til de mest relevante tjenestene og innholdet.

Hvorfor er AI-generert WordPress-plugin-kode ofte usikker?#
AI-generatorer (LLMer) er trent på offentlig tilgjengelig kode, og mye av denne inneholder utdaterte eller usikre mønstre skrevet i løpet av de siste 15 årene. AI mangler dessuten operasjonell kontekst for WordPress-kjøring, noe som resulterer i syntaktisk korrekt PHP-kode som helt utelater kritiske rettighetssjekker og CSRF-validering (nonces).
Hva er forskjellen på is_admin() og current_user_can() for sikkerhet?#
Funksjonen is_admin() sjekker kun om den gjeldende forespørselen gjelder en administrasjonsside (som /wp-admin/) og verifiserer ikke brukerrettigheter. Å bruke den til adgangskontroll lar enhver innlogget bruker (inkludert abonnenter) kjøre koden. Sikker adgangskontroll krever current_user_can('manage_options') eller lignende.
Hvordan introduserer AI SQL-injeksjonssårbarheter i WordPress-kode?#
Det vanligste problemet er direkte sammenslåing av brukerinput-variabler ($_POST eller $_GET) i SQL-spørrestrenger, f.eks. $wpdb->query("SELECT * FROM table WHERE id = $id"). For å forhindre SQL-injeksjon må alle dynamiske spørringer kjøres via $wpdb->prepare() med riktige formatspesifikasjoner (%d for heltall, %s for strenger).
Hva er sanitysering og escaping i WordPress-standarder?#
Sanitysereing (som sanitize_text_field) renser inndata før de lagres i databasen. Escaping (som esc_html, esc_attr, esc_url) sikrer utdata umiddelbart før de rendres i nettleseren, noe som forhindrer Cross-Site Scripting (XSS)-angrep. AI-generert kode forveksler ofte disse to praksisene eller glemmer dem helt.

Trenger du FAQ tilpasset bransje og marked? Vi lager en versjon som støtter dine forretningsmål.

Ta kontakt

Relaterte artikler